pax_global_header00006660000000000000000000000064135203066400014511gustar00rootroot0000000000000052 comment=9b3f4f9bbff1be4afd992f68a388faf9b8cbf907 commons-dbcp-commons-dbcp-2.7.0/000077500000000000000000000000001352030664000164575ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/.gitignore000066400000000000000000000003771352030664000204560ustar00rootroot00000000000000target/ 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-commons-dbcp-2.7.0/.travis.yml000066400000000000000000000015721352030664000205750ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT 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 jdk: - oraclejdk11 - openjdk8 - openjdk11 - openjdk12 - openjdk-ea commons-dbcp-commons-dbcp-2.7.0/CONTRIBUTING.md000066400000000000000000000146011352030664000207120ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/LICENSE.txt000066400000000000000000000261361352030664000203120ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/NOTICE.txt000066400000000000000000000002551352030664000202030ustar00rootroot00000000000000Apache Commons DBCP Copyright 2001-2019 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). commons-dbcp-commons-dbcp-2.7.0/README.md000066400000000000000000000126561352030664000177500ustar00rootroot00000000000000 Apache Commons DBCP =================== [![Build Status](https://travis-ci.org/apache/commons-dbcp.svg)](https://travis-ci.org/apache/commons-dbcp) [![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.7.0.svg)](https://javadoc.io/doc/org.apache.commons/commons-dbcp2/2.7.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/javadocs/api-release) 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.7.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-commons-dbcp-2.7.0/README.txt000066400000000000000000000010011352030664000201450ustar00rootroot00000000000000Apache 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-commons-dbcp-2.7.0/RELEASE-NOTES.txt000066400000000000000000000412011352030664000211640ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/checkstyle.xml000066400000000000000000000164601352030664000213460ustar00rootroot00000000000000 commons-dbcp-commons-dbcp-2.7.0/dbcp-RC.sh000077500000000000000000000044621352030664000202360ustar00rootroot00000000000000#!/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-commons-dbcp-2.7.0/dbcp-pre-RC.sh000077500000000000000000000026201352030664000210140ustar00rootroot00000000000000#!/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-commons-dbcp-2.7.0/dbcp-release.sh000077500000000000000000000050721352030664000213500ustar00rootroot00000000000000#!/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-commons-dbcp-2.7.0/doc/000077500000000000000000000000001352030664000172245ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/doc/BasicDataSourceExample.java000066400000000000000000000103721352030664000244020ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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-commons-dbcp-2.7.0/doc/PoolingDataSourceExample.java000066400000000000000000000140771352030664000247760ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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-commons-dbcp-2.7.0/doc/PoolingDriverExample.java000066400000000000000000000163531352030664000241760ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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-commons-dbcp-2.7.0/doc/README.txt000066400000000000000000000027071352030664000207300ustar00rootroot00000000000000=================================================================================== 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-commons-dbcp-2.7.0/doc/abandon.jsp000066400000000000000000000111201352030664000213370ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/doc/static_structure_dia.gif000066400000000000000000000236431352030664000241470ustar00rootroot00000000000000GIF89a#÷ý€€€€€€€€€ÀÀÀÀÜÀ¦Êð@ ` €   À à @ @@@`@€@ @À@à@` `@```€` `À`à`€ €@€`€€€ €À€à€   @ ` €   À à À À@À`À€À ÀÀÀàÀà à@à`à€à àÀààà@ @@@`@€@ @À@à@ @ @@ @` @€ @  @À @à @@@ @@@@@`@@€@@ @@À@@à@@`@ `@@`@``@€`@ `@À`@à`@€@ €@@€@`€@€€@ €@À€@à€@ @  @@ @` @€ @  @À @à @À@ À@@À@`À@€À@ À@ÀÀ@àÀ@à@ à@@à@`à@€à@ à@Àà@àà@€ €@€`€€€ €À€à€ € €@ €` €€ €  €À €à €@€ @€@@€`@€€@€ @€À@€à@€`€ `€@`€``€€`€ `€À`€à`€€€ €€@€€`€€€€€ €€À€€à€€ €  €@ €` €€ €  €À €à €À€ À€@À€`À€€À€ À€ÀÀ€àÀ€à€ à€@à€`à€€à€ à€Àà€àà€À À@À`À€À ÀÀÀàÀ À À@ À` À€ À  ÀÀ Àà À@À @À@@À`@À€@À @ÀÀ@Àà@À`À `À@`À``À€`À `ÀÀ`Àà`À€À €À@€À`€À€€À €ÀÀ€Àà€À À  À@ À` À€ À  ÀÀ Àà ÀÀÀ ÀÀ@ÀÀ`ÀÀ€ÀÀ ÀÀÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ!ùý,#@þû H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(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’=–…¢“ÿ˜(%”QJeŠVfùä‰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«-ŽÉƵlšLƪ§–á®뜲¶º'šånùf»êFfN^{¬rÍY Ӥ‹nœ¬ú+kÀâ ë¿ãž+o·p}»íÃÍÚ‹_t¤‰è0Ä×*1ÃwL›t{,òÈ$“2I'—¬òÊ,#˜²H/·,óÌ4³íÅç¼iÌóñ\óϼÞ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-BŽ0Ÿ&.v¹Ñ–«\eŠg(“ãéÇGN'Ї\È"g™Â\梗³#VÏêëWasþ§ì)D©Q‚ 3&>ål®4ÂÒŒzв*À›`ÙªH ï…Ølµ7Žp]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._` YiÌŸ‚2~!½ çÚ§,iÅ—¯üÁŠ­ùêG~‡¦;þ¯OÞÎ÷º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‡SnžsmA†ž³†~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 ;BYŽg‘ÑEŠÓˆ‘)­pš¡ÿWœ(ê€'úa*:§™~*~ãʃK9Wùö“ÆÈmäø®‡5WìÈo/yyi¯éù©^G°¾ÒžÅj±Ó P{“®,eŠ¿º«¶†\Ÿ¸¬ÍÚþ²J²=µmûZDYw ×m©³8ÛXžu“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¸ƒºÈÞGYÞë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ƒƒGiìÒ}Õ£Õí·a³3ÛVâ‰ù¾ì)¾Î+¬Šy?®å§ØˆÃ tƳtýãͶ=9œZìøŽÛ¸ÝÖ¥¨°þoÒ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&›tòÉç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ÅyOŠw_Ýܵ^~}Í÷Ø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ÛÞZì!Á»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~óEì_ç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ҪʊTY5šA­*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-commons-dbcp-2.7.0/findbugs-exclude-filter.xml000066400000000000000000000051551352030664000237220ustar00rootroot00000000000000 commons-dbcp-commons-dbcp-2.7.0/pom.xml000066400000000000000000000434721352030664000200060ustar00rootroot00000000000000 org.apache.commons commons-parent 48 4.0.0 commons-dbcp2 2.7.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://git-wip-us.apache.org/repos/asf/commons-dbcp.git scm:git:https://git-wip-us.apache.org/repos/asf/commons-dbcp.git https://git-wip-us.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 Gary Gregory ggregory ggregory@apache.org The Apache Software Foundation 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.5.1 test org.hamcrest hamcrest-all 1.3 test org.mockito mockito-core 3.0.0 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.26 test com.h2database h2 1.4.199 test org.jboss.narayana.jta narayana-jta 5.9.5.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.0.Final org.jboss.logging jboss-logging-spi test org.jboss.logging jboss-logging 3.4.0.Final test UTF-8 UTF-8 1.8 1.8 dbcp RC1 org.apache.commons.dbcp2 2.7.0 for JDBC 4.2 on Java 8 2.4.0 for JDBC 4.1 on Java 7 commons-dbcp-${commons.release.3.version} 1.4 for JDBC 4 on Java 6 commons-dbcp-${commons.release.4.version} 1.3 for JDBC 3 on Java 1.4 or 5 dbcp https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-dbcp site-content DBCP 12310469 3.0.0 3.1.1 2.7.0 0.13.1 0.8.4 javax.transaction;version="1.1.0",javax.transaction.xa;version="1.1.0";partial=true;mandatory:=partial,* true 2.6.0 true Gary Gregory 86fdc7e2a11262cb false org.apache.maven.plugins maven-scm-publish-plugin ${commons.scm-publish.version} javadocs org.apache.maven.plugins maven-checkstyle-plugin ${commons.checkstyle.version} ${basedir}/checkstyle.xml false 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/7/docs/api https://commons.apache.org/proper/commons-pool/api-${commons.pool.version} 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 org.codehaus.mojo findbugs-maven-plugin 3.0.5 Normal Default ${basedir}/findbugs-exclude-filter.xml org.apache.maven.plugins maven-javadoc-plugin ${commons.javadoc.version} http://docs.oracle.com/javase/7/docs/api https://commons.apache.org/proper/commons-pool/api-${commons.pool.version} 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 ${commons.checkstyle.version} ${basedir}/checkstyle.xml false org.codehaus.mojo clirr-maven-plugin ${commons.clirr.version} info maven-pmd-plugin 3.12.0 ${maven.compiler.target} pmd cpd commons-dbcp-commons-dbcp-2.7.0/src/000077500000000000000000000000001352030664000172465ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/changes/000077500000000000000000000000001352030664000206565ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/changes/changes.xml000066400000000000000000001631701352030664000230200ustar00rootroot00000000000000 Apache Commons DBCP Release Notes 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-commons-dbcp-2.7.0/src/changes/release-notes.vm000066400000000000000000000066441352030664000240020ustar00rootroot00000000000000## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT 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-commons-dbcp-2.7.0/src/main/000077500000000000000000000000001352030664000201725ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/assembly/000077500000000000000000000000001352030664000220115ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/assembly/bin.xml000066400000000000000000000031371352030664000233070ustar00rootroot00000000000000 bin tar.gz zip false LICENSE.txt NOTICE.txt README.txt RELEASE-NOTES.txt target *.jar target/site/apidocs apidocs commons-dbcp-commons-dbcp-2.7.0/src/main/assembly/src-tar-gz.xml000066400000000000000000000053411352030664000245270ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/src/main/assembly/src-zip.xml000066400000000000000000000053531352030664000241300ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/src/main/java/000077500000000000000000000000001352030664000211135ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/000077500000000000000000000000001352030664000217025ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/000077500000000000000000000000001352030664000231235ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/000077500000000000000000000000001352030664000245765ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/000077500000000000000000000000001352030664000255705ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/AbandonedTrace.java000066400000000000000000000124031352030664000312650ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 db connection usage for recovering and reporting abandoned db 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 = 0; /** * 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); } /** * Initializes abandoned tracing for this object. * * @param parent * AbandonedTrace parent object. */ private void init(final AbandonedTrace parent) { if (parent != null) { parent.addTrace(this); } } /** * Gets the last time this object was used in milliseconds. * * @return long time in milliseconds. */ @Override public long getLastUsed() { return lastUsedMillis; } /** * 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; } /** * 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 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; } /** * 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; } else if (traceInList == null) { // Clean-up since we are here anyway iter.remove(); } } } } /** * 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); } } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java000066400000000000000000002637061352030664000314450ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.ObjectName; 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 * shopping" solution for basic requirements. *

* * @since 2.0 */ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBeanRegistration, AutoCloseable { /** * @since 2.0 */ private class PaGetConnection implements PrivilegedExceptionAction { @Override public Connection run() throws SQLException { return createDataSource().getConnection(); } } 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.IS_SECURITY_ENABLED) { final ClassLoader loader = BasicDataSource.class.getClassLoader(); final String dbcpPackageName = BasicDataSource.class.getPackage().getName(); loader.loadClass(dbcpPackageName + ".BasicDataSource$PaGetConnection"); 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 = 0; /** * 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 = false; /** *

* 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 = false; /** * 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 = false; /** * 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 = false; /** * 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 = false; 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. *

*

* 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; try { if (oldPool != null) { oldPool.close(); } } catch (final Exception e) { /* Ignore */ } } /** * 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 factort 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; PoolableConnectionFactory poolableConnectionFactory; try { poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory); poolableConnectionFactory.setPoolStatements(poolPreparedStatements); poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements); success = true; } catch (final SQLException se) { throw se; } catch (final RuntimeException rte) { throw rte; } 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 se) { throw se; } catch (final RuntimeException rte) { throw rte; } 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) { 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.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() { if (abandonedConfig != null) { return abandonedConfig.getLogWriter(); } return null; } /** * 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() { if (abandonedConfig != null) { return abandonedConfig.getUseUsageTracking(); } return false; } /** * 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.IS_SECURITY_ENABLED) { final PrivilegedExceptionAction action = new PaGetConnection(); 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; if (result == null) { return Collections.emptyList(); } return result; } /** * Provides the same data as {@link #getConnectionInitSqls()} but in an array so it is accessible via JMX. */ @Override public String[] getConnectionInitSqlsAsArray() { final Collection result = getConnectionInitSqls(); return result.toArray(new String[result.size()]); } 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; if (result == null) { return Collections.emptySet(); } return 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() { final Collection result = getDisconnectionSqlCodes(); return result.toArray(new String[result.size()]); } /** * 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() { if (abandonedConfig != null) { return abandonedConfig.getLogAbandoned(); } return false; } /** * 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; if (pool != null) { return pool.getNumActive(); } return 0; } /** * [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; if (pool != null) { return pool.getNumIdle(); } return 0; } /** * 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() { if (abandonedConfig != null) { return abandonedConfig.getRemoveAbandonedOnBorrow(); } return false; } /** *

* 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() { if (abandonedConfig != null) { return abandonedConfig.getRemoveAbandonedOnMaintenance(); } return false; } /** *

* 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() { if (abandonedConfig != null) { return abandonedConfig.getRemoveAbandonedTimeout(); } return 300; } /** * 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; } /** * 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(String value) { return value == null ? true : 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 false; } 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; } try { ObjectNameWrapper.wrap(requestedName).registerMBean(this); } catch (final MalformedObjectNameException 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(String message, 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) { final String requestedName = getJmxName(); if (requestedName != null) { try { registeredJmxObjectName = ObjectNameWrapper.wrap(requestedName); } catch (final MalformedObjectNameException e) { log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored."); } } if (registeredJmxObjectName == null) { registeredJmxObjectName = ObjectNameWrapper.wrap(objectName); } return ObjectNameWrapper.unwrap(registeredJmxObjectName); } /** * 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); } /** * 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; } // ----------------------------------------------------- DataSource Methods /** * 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 the ConnectionFactory class name. * * @param connectionFactoryClassName A class name. * @since 2.7.0 */ public void setConnectionFactoryClassName(final String connectionFactoryClassName) { if (isEmpty(connectionFactoryClassName)) { this.connectionFactoryClassName = null; } else { this.connectionFactoryClassName = 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.size() > 0) { 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.length() > 0) { 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) { if (isEmpty(defaultCatalog)) { this.defaultCatalog = null; } else { this.defaultCatalog = 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) { if (isEmpty(defaultSchema)) { this.defaultSchema = null; } else { this.defaultSchema = 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.size() > 0) { 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) { if (isEmpty(driverClassName)) { this.driverClassName = null; } else { this.driverClassName = 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); } } /** * 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); } } // ------------------------------------------------------ Protected Methods /** * 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) { if (isEmpty(validationQuery)) { this.validationQuery = null; } else { 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. *

* 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 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 { throw new SQLException("BasicDataSource is not a wrapper."); } 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); } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java000066400000000000000000000644401352030664000327670ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 semi-colon 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_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_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 /** *

* 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.keySet().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.keySet().contains(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()); } } } /** * 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 = null; 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.valueOf(value).booleanValue()); } value = properties.getProperty(PROP_DRIVER_CLASS_NAME); if (value != null) { dataSource.setDriverClassName(value); } value = properties.getProperty(PROP_LIFO); if (value != null) { dataSource.setLifo(Boolean.valueOf(value).booleanValue()); } 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.valueOf(value).booleanValue()); } value = properties.getProperty(PROP_TEST_ON_BORROW); if (value != null) { dataSource.setTestOnBorrow(Boolean.valueOf(value).booleanValue()); } value = properties.getProperty(PROP_TEST_ON_RETURN); if (value != null) { dataSource.setTestOnReturn(Boolean.valueOf(value).booleanValue()); } 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.valueOf(value).booleanValue()); } 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.valueOf(value).booleanValue()); } value = properties.getProperty(PROP_REMOVE_ABANDONED_ON_BORROW); if (value != null) { dataSource.setRemoveAbandonedOnBorrow(Boolean.valueOf(value).booleanValue()); } value = properties.getProperty(PROP_REMOVE_ABANDONED_ON_MAINTENANCE); if (value != null) { dataSource.setRemoveAbandonedOnMaintenance(Boolean.valueOf(value).booleanValue()); } 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.valueOf(value).booleanValue()); } value = properties.getProperty(PROP_ABANDONED_USAGE_TRACKING); if (value != null) { dataSource.setAbandonedUsageTracking(Boolean.valueOf(value).booleanValue()); } value = properties.getProperty(PROP_POOL_PREPARED_STATEMENTS); if (value != null) { dataSource.setPoolPreparedStatements(Boolean.valueOf(value).booleanValue()); } 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.valueOf(value).booleanValue()); } 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.valueOf(value).booleanValue()); } value = properties.getProperty(PROP_ROLLBACK_ON_RETURN); if (value != null) { dataSource.setRollbackOnReturn(Boolean.valueOf(value).booleanValue()); } 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.valueOf(value).booleanValue()); } 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; } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java000066400000000000000000000202331352030664000324620ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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; /** * Defines the methods that will be made available via JMX. * * @since 2.0 */ public interface BasicDataSourceMXBean { /** * See {@link BasicDataSource#getAbandonedUsageTracking()} * * @return {@link BasicDataSource#getAbandonedUsageTracking()} */ boolean getAbandonedUsageTracking(); /** * See {@link BasicDataSource#getDefaultAutoCommit()} * * @return {@link BasicDataSource#getDefaultAutoCommit()} */ Boolean getDefaultAutoCommit(); /** * See {@link BasicDataSource#getDefaultReadOnly()} * * @return {@link BasicDataSource#getDefaultReadOnly()} */ Boolean getDefaultReadOnly(); /** * See {@link BasicDataSource#getDefaultTransactionIsolation()} * * @return {@link BasicDataSource#getDefaultTransactionIsolation()} */ int getDefaultTransactionIsolation(); /** * See {@link BasicDataSource#getDefaultCatalog()} * * @return {@link BasicDataSource#getDefaultCatalog()} */ String getDefaultCatalog(); /** * See {@link BasicDataSource#getDefaultSchema()} * * @return {@link BasicDataSource#getDefaultSchema()} * @since 2.5.0 */ default String getDefaultSchema() { return null; } /** * See {@link BasicDataSource#getCacheState()} * * @return {@link BasicDataSource#getCacheState()} */ boolean getCacheState(); /** * See {@link BasicDataSource#getDriverClassName()} * * @return {@link BasicDataSource#getDriverClassName()} */ String getDriverClassName(); /** * See {@link BasicDataSource#getLifo()} * * @return {@link BasicDataSource#getLifo()} */ boolean getLifo(); /** * See {@link BasicDataSource#getMaxTotal()} * * @return {@link BasicDataSource#getMaxTotal()} */ int getMaxTotal(); /** * See {@link BasicDataSource#getMaxIdle()} * * @return {@link BasicDataSource#getMaxIdle()} */ int getMaxIdle(); /** * See {@link BasicDataSource#getMinIdle()} * * @return {@link BasicDataSource#getMinIdle()} */ int getMinIdle(); /** * See {@link BasicDataSource#getInitialSize()} * * @return {@link BasicDataSource#getInitialSize()} */ int getInitialSize(); /** * See {@link BasicDataSource#getMaxWaitMillis()} * * @return {@link BasicDataSource#getMaxWaitMillis()} */ long getMaxWaitMillis(); /** * See {@link BasicDataSource#isPoolPreparedStatements()} * * @return {@link BasicDataSource#isPoolPreparedStatements()} */ boolean isPoolPreparedStatements(); /** * See {@link BasicDataSource#getMaxOpenPreparedStatements()} * * @return {@link BasicDataSource#getMaxOpenPreparedStatements()} */ int getMaxOpenPreparedStatements(); /** * See {@link BasicDataSource#getTestOnCreate()} * * @return {@link BasicDataSource#getTestOnCreate()} */ boolean getTestOnCreate(); /** * See {@link BasicDataSource#getTestOnBorrow()} * * @return {@link BasicDataSource#getTestOnBorrow()} */ boolean getTestOnBorrow(); /** * See {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()} * * @return {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()} */ long getTimeBetweenEvictionRunsMillis(); /** * See {@link BasicDataSource#getNumTestsPerEvictionRun()} * * @return {@link BasicDataSource#getNumTestsPerEvictionRun()} */ int getNumTestsPerEvictionRun(); /** * See {@link BasicDataSource#getMinEvictableIdleTimeMillis()} * * @return {@link BasicDataSource#getMinEvictableIdleTimeMillis()} */ long getMinEvictableIdleTimeMillis(); /** * See {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()} * * @return {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()} */ long getSoftMinEvictableIdleTimeMillis(); /** * See {@link BasicDataSource#getTestWhileIdle()} * * @return {@link BasicDataSource#getTestWhileIdle()} */ boolean getTestWhileIdle(); /** * See {@link BasicDataSource#getNumActive()} * * @return {@link BasicDataSource#getNumActive()} */ int getNumActive(); /** * See {@link BasicDataSource#getNumIdle()} * * @return {@link BasicDataSource#getNumIdle()} */ int getNumIdle(); /** * See {@link BasicDataSource#getPassword()} * * @return {@link BasicDataSource#getPassword()} */ String getPassword(); /** * 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#getConnectionInitSqlsAsArray()} * * @return {@link BasicDataSource#getConnectionInitSqlsAsArray()} */ String[] getConnectionInitSqlsAsArray(); /** * See {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()} * * @return {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()} */ boolean isAccessToUnderlyingConnectionAllowed(); /** * See {@link BasicDataSource#getMaxConnLifetimeMillis()} * * @return {@link BasicDataSource#getMaxConnLifetimeMillis()} */ long getMaxConnLifetimeMillis(); /** * See {@link BasicDataSource#getLogExpiredConnections()} * * @return {@link BasicDataSource#getLogExpiredConnections()} * @since 2.1 */ boolean getLogExpiredConnections(); /** * 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#getLogAbandoned()} * * @return {@link BasicDataSource#getLogAbandoned()} */ boolean getLogAbandoned(); /** * See {@link BasicDataSource#isClosed()} * * @return {@link BasicDataSource#isClosed()} */ boolean isClosed(); /** * See {@link BasicDataSource#getFastFailValidation()} * * @return {@link BasicDataSource#getFastFailValidation()} * @since 2.1 */ boolean getFastFailValidation(); /** * See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()} * * @return {@link BasicDataSource#getDisconnectionSqlCodesAsArray()} * @since 2.1 */ String[] getDisconnectionSqlCodesAsArray(); } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/ConnectionFactory.java000066400000000000000000000025021352030664000320610ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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; } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/ConnectionFactoryFactory.java000066400000000000000000000063301352030664000334140ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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("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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/Constants.java000066400000000000000000000025701352030664000304130ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 for use with JMX. * * @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"; } DataSourceConnectionFactory.java000066400000000000000000000063021352030664000337570ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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; } } DelegatingCallableStatement.java000066400000000000000000001226441352030664000337350ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java000066400000000000000000000750171352030664000325300ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.Iterator; 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 autoCommitCached; private Boolean readOnlyCached; private Integer defaultQueryTimeoutSeconds; /** * Creates a wrapper for the Connection which traces this Connection in the AbandonedObjectPool. * * @param c * the {@link Connection} to delegate all calls to. */ public DelegatingConnection(final C c) { super(); connection = c; } /** * 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 StringBuffer sb = new StringBuffer(); sb.append(hashCode()); final DatabaseMetaData meta = conn.getMetaData(); if (meta != null) { sb.append(", URL="); sb.append(meta.getURL()); sb.append(", UserName="); sb.append(meta.getUserName()); sb.append(", "); sb.append(meta.getDriverName()); str = sb.toString(); } } } catch (final SQLException ex) { // Ignore } } return str != null ? str : super.toString(); } /** * Returns my underlying {@link Connection}. * * @return my underlying {@link Connection}. */ public C getDelegate() { return getDelegateInternal(); } protected final C getDelegateInternal() { return connection; } /** * 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); } /** * 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 != null && conn instanceof DelegatingConnection) { conn = ((DelegatingConnection) conn).getDelegateInternal(); if (this == conn) { return null; } } return conn; } /** * Sets my delegate. * * @param connection * my delegate. */ public void setDelegate(final C connection) { this.connection = connection; } /** * 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 boolean isClosedInternal() { return closed; } protected void setClosedInternal(final boolean closed) { this.closed = closed; } 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; } } } 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; } private void initializeStatement(final DelegatingStatement ds) throws SQLException { if (defaultQueryTimeoutSeconds != null && defaultQueryTimeoutSeconds.intValue() != ds.getQueryTimeout()) { ds.setQueryTimeout(defaultQueryTimeoutSeconds.intValue()); } } @Override public Statement createStatement() throws SQLException { checkOpen(); try { final DelegatingStatement ds = new DelegatingStatement(this, connection.createStatement()); initializeStatement(ds); return ds; } catch (final SQLException e) { handleException(e); return null; } } @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); try { final DelegatingStatement ds = new DelegatingStatement(this, connection.createStatement(resultSetType, resultSetConcurrency)); initializeStatement(ds); return ds; } catch (final SQLException e) { handleException(e); return null; } } @Override public PreparedStatement prepareStatement(final String sql) throws SQLException { checkOpen(); try { final DelegatingPreparedStatement dps = new DelegatingPreparedStatement(this, connection.prepareStatement(sql)); initializeStatement(dps); return dps; } catch (final SQLException e) { handleException(e); return null; } } @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); try { final DelegatingPreparedStatement dps = new DelegatingPreparedStatement(this, connection.prepareStatement(sql, resultSetType, resultSetConcurrency)); initializeStatement(dps); return dps; } catch (final SQLException e) { handleException(e); return null; } } @Override public CallableStatement prepareCall(final String sql) throws SQLException { checkOpen(); try { final DelegatingCallableStatement dcs = new DelegatingCallableStatement(this, connection.prepareCall(sql)); initializeStatement(dcs); return dcs; } catch (final SQLException e) { handleException(e); return null; } } @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); try { final DelegatingCallableStatement dcs = new DelegatingCallableStatement(this, connection.prepareCall(sql, resultSetType, resultSetConcurrency)); initializeStatement(dcs); return dcs; } catch (final SQLException e) { handleException(e); return null; } } @Override public void clearWarnings() throws SQLException { checkOpen(); try { connection.clearWarnings(); } catch (final SQLException e) { handleException(e); } } @Override public void commit() throws SQLException { checkOpen(); try { connection.commit(); } catch (final SQLException e) { handleException(e); } } /** * Returns the state caching flag. * * @return the state caching flag */ public boolean getCacheState() { return cacheState; } @Override public boolean getAutoCommit() throws SQLException { checkOpen(); if (cacheState && autoCommitCached != null) { return autoCommitCached.booleanValue(); } try { autoCommitCached = Boolean.valueOf(connection.getAutoCommit()); return autoCommitCached.booleanValue(); } catch (final SQLException e) { handleException(e); return false; } } @Override public String getCatalog() throws SQLException { checkOpen(); try { return connection.getCatalog(); } catch (final SQLException e) { handleException(e); return null; } } @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 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; } } @Override public boolean isReadOnly() throws SQLException { checkOpen(); if (cacheState && readOnlyCached != null) { return readOnlyCached.booleanValue(); } try { readOnlyCached = Boolean.valueOf(connection.isReadOnly()); return readOnlyCached.booleanValue(); } catch (final SQLException e) { handleException(e); return false; } } @Override public String nativeSQL(final String sql) throws SQLException { checkOpen(); try { return connection.nativeSQL(sql); } catch (final SQLException e) { handleException(e); return null; } } @Override public void rollback() throws SQLException { checkOpen(); try { connection.rollback(); } catch (final SQLException e) { handleException(e); } } /** * 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; } /** * 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 the state caching flag. * * @param cacheState * The new value for the state caching flag */ public void setCacheState(final boolean cacheState) { this.cacheState = cacheState; } /** * Can be used to clear cached state when it is known that the underlying connection may have been accessed * directly. */ public void clearCachedState() { autoCommitCached = null; readOnlyCached = null; if (connection instanceof DelegatingConnection) { ((DelegatingConnection) connection).clearCachedState(); } } @Override public void setAutoCommit(final boolean autoCommit) throws SQLException { checkOpen(); try { connection.setAutoCommit(autoCommit); if (cacheState) { autoCommitCached = Boolean.valueOf(autoCommit); } } catch (final SQLException e) { autoCommitCached = null; handleException(e); } } @Override public void setCatalog(final String catalog) throws SQLException { checkOpen(); try { connection.setCatalog(catalog); } catch (final SQLException e) { handleException(e); } } @Override public void setReadOnly(final boolean readOnly) throws SQLException { checkOpen(); try { connection.setReadOnly(readOnly); if (cacheState) { readOnlyCached = Boolean.valueOf(readOnly); } } catch (final SQLException e) { readOnlyCached = 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); } } @Override public boolean isClosed() throws SQLException { return closed || connection == null || connection.isClosed(); } 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."); } } protected void activate() { closed = false; setLastUsed(); if (connection instanceof DelegatingConnection) { ((DelegatingConnection) connection).activate(); } } 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 thrown = new ArrayList<>(); final Iterator traceIter = traces.iterator(); while (traceIter.hasNext()) { final Object trace = traceIter.next(); if (trace instanceof Statement) { try { ((Statement) trace).close(); } catch (Exception e) { thrown.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 (Exception e) { thrown.add(e); } } } clearTrace(); if (!thrown.isEmpty()) { throw new SQLExceptionList(thrown); } } setLastUsed(0); } @Override public int getHoldability() throws SQLException { checkOpen(); try { return connection.getHoldability(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public void setHoldability(final int holdability) throws SQLException { checkOpen(); try { connection.setHoldability(holdability); } catch (final SQLException e) { 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 rollback(final Savepoint savepoint) throws SQLException { checkOpen(); try { connection.rollback(savepoint); } catch (final SQLException e) { handleException(e); } } @Override public void releaseSavepoint(final Savepoint savepoint) throws SQLException { checkOpen(); try { connection.releaseSavepoint(savepoint); } catch (final SQLException e) { handleException(e); } } @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { checkOpen(); try { final DelegatingStatement ds = new DelegatingStatement(this, connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability)); initializeStatement(ds); return ds; } catch (final SQLException e) { handleException(e); return null; } } @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { checkOpen(); try { final DelegatingPreparedStatement dps = new DelegatingPreparedStatement(this, connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); initializeStatement(dps); return dps; } catch (final SQLException e) { handleException(e); return null; } } @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { checkOpen(); try { final DelegatingCallableStatement dcs = new DelegatingCallableStatement(this, connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); initializeStatement(dcs); return dcs; } catch (final SQLException e) { handleException(e); return null; } } @Override public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); try { final DelegatingPreparedStatement dps = new DelegatingPreparedStatement(this, connection.prepareStatement(sql, autoGeneratedKeys)); initializeStatement(dps); return dps; } catch (final SQLException e) { handleException(e); return null; } } @Override public PreparedStatement prepareStatement(final String sql, final int columnIndexes[]) throws SQLException { checkOpen(); try { final DelegatingPreparedStatement dps = new DelegatingPreparedStatement(this, connection.prepareStatement(sql, columnIndexes)); initializeStatement(dps); return dps; } catch (final SQLException e) { handleException(e); return null; } } @Override public PreparedStatement prepareStatement(final String sql, final String columnNames[]) throws SQLException { checkOpen(); try { final DelegatingPreparedStatement dps = new DelegatingPreparedStatement(this, connection.prepareStatement(sql, columnNames)); initializeStatement(dps); return dps; } catch (final SQLException e) { handleException(e); return null; } } @Override public boolean isWrapperFor(final Class iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return true; } else if (iface.isAssignableFrom(connection.getClass())) { return true; } else { return connection.isWrapperFor(iface); } } @Override public T unwrap(final Class iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return iface.cast(this); } else if (iface.isAssignableFrom(connection.getClass())) { return iface.cast(connection); } else { return connection.unwrap(iface); } } @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; } } @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 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 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); } } @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 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; } } @Override public void setSchema(final String schema) throws SQLException { checkOpen(); try { Jdbc41Bridge.setSchema(connection, schema); } catch (final SQLException e) { handleException(e); } } @Override public String getSchema() throws SQLException { checkOpen(); try { return Jdbc41Bridge.getSchema(connection); } catch (final SQLException e) { handleException(e); return null; } } @Override public void abort(final Executor executor) throws SQLException { checkOpen(); try { Jdbc41Bridge.abort(connection, executor); } 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 int getNetworkTimeout() throws SQLException { checkOpen(); try { return Jdbc41Bridge.getNetworkTimeout(connection); } catch (final SQLException e) { handleException(e); return 0; } } } DelegatingDatabaseMetaData.java000066400000000000000000001616771352030664000334670ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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) { super(); 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 != null && 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) { connection.handleException(e); } else { throw 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; } else if (iface.isAssignableFrom(databaseMetaData.getClass())) { return true; } else { 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; } } /* JDBC_4_ANT_KEY_BEGIN */ @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); } else if (iface.isAssignableFrom(databaseMetaData.getClass())) { return iface.cast(databaseMetaData); } else { 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.java000066400000000000000000000527101352030664000337740ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/DelegatingResultSet.java000066400000000000000000001637471352030664000323730ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 conn * Connection which created this ResultSet * @param res * ResultSet to wrap */ private DelegatingResultSet(final Connection conn, final ResultSet res) { super((AbandonedTrace) conn); this.connection = conn; this.resultSet = res; } /** * 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 != null && 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 != null && statement instanceof DelegatingStatement) { ((DelegatingStatement) statement).handleException(e); } else if (connection != null && 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; } else if (iface.isAssignableFrom(resultSet.getClass())) { return true; } else { 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); } else if (iface.isAssignableFrom(resultSet.getClass())) { return iface.cast(resultSet); } else { 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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java000066400000000000000000000554501352030664000323740ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 = false; /** * 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 thrown = 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 int size = resultSetList.size(); final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[size]); for (final ResultSet resultSet : resultSets) { if (resultSet != null) { try { resultSet.close(); } catch (Exception e) { if (connection != null) { // Does not rethrow e. connection.handleExceptionNoThrow(e); } thrown.add(e); } } } clearTrace(); } if (statement != null) { try { statement.close(); } catch (Exception e) { if (connection != null) { // Does not rethrow e. connection.handleExceptionNoThrow(e); } thrown.add(e); } } } finally { closed = true; statement = null; if (!thrown.isEmpty()) { throw new SQLExceptionList(thrown); } } } @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; } } @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; } } @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 != null && 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; } } @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) { connection.handleException(e); } else { throw 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; } else if (iface.isAssignableFrom(statement.getClass())) { return true; } else { 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); } else if (iface.isAssignableFrom(statement.getClass())) { return iface.cast(statement); } else { return statement.unwrap(iface); } } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/DriverConnectionFactory.java000066400000000000000000000047501352030664000332440ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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() + " [" + String.valueOf(driver) + ";" + String.valueOf(connectionString) + ";" + String.valueOf(properties) + "]"; } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/DriverFactory.java000066400000000000000000000065201352030664000312210ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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(); String driverClassName = basicDataSource.getDriverClassName(); ClassLoader driverClassLoader = basicDataSource.getDriverClassLoader(); 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.java000066400000000000000000000114561352030664000344610ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/Jdbc41Bridge.java000066400000000000000000000446511352030664000305710ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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). * * @since 2.6.0 */ public class Jdbc41Bridge { /** * Delegates to {@link Connection#abort(Executor)} without throwing a {@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 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 a {@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 a {@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 a {@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 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 a {@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 Connection#setNetworkTimeout(Executor, int)} without throwing a {@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 a {@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 } } /** * Delegates to {@link Statement#closeOnCompletion()} without throwing a {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link Statement#closeOnCompletion()}, then just check that the connection * is closed to then throw a 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 Statement#isCloseOnCompletion()} without throwing a {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link Statement#isCloseOnCompletion()}, then just check that the * connection is closed to then throw a 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 CommonDataSource#getParentLogger()} without throwing a {@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()"); } } } LifetimeExceededException.java000066400000000000000000000026621352030664000334260ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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() { super(); } /** * 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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/ListException.java000066400000000000000000000035101352030664000312240ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/ObjectNameWrapper.java000066400000000000000000000063301352030664000320050ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 MBeanServer MBEAN_SERVER = getPlatformMBeanServer(); private static MBeanServer getPlatformMBeanServer() { try { return ManagementFactory.getPlatformMBeanServer(); } catch (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 (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 (LinkageError | Exception e) { log.warn("Failed to complete JMX unregistration for " + objectName, e); } } } public ObjectName unwrap() { return objectName; } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/PStmtKey.java000066400000000000000000001130101352030664000301470ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 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.intValue(), resultSetConcurrency.intValue()); } } /** * 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.intValue(), resultSetConcurrency.intValue(), resultSetHoldability.intValue()); } } /** * 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.intValue()); } } /** * 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.intValue(), resultSetConcurrency.intValue()); } } /** * 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.intValue(), resultSetConcurrency.intValue(), resultSetHoldability.intValue()); } } /** * 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, Integer.valueOf(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 = Integer.valueOf(resultSetType); this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency); this.resultSetHoldability = Integer.valueOf(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 = Integer.valueOf(resultSetType); this.resultSetConcurrency = Integer.valueOf(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, Integer.valueOf(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 = Integer.valueOf(resultSetType); this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency); this.resultSetHoldability = Integer.valueOf(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 = Integer.valueOf(resultSetType); this.resultSetConcurrency = Integer.valueOf(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 (autoGeneratedKeys == null) { if (other.autoGeneratedKeys != null) { return false; } } else if (!autoGeneratedKeys.equals(other.autoGeneratedKeys)) { return false; } if (catalog == null) { if (other.catalog != null) { return false; } } else if (!catalog.equals(other.catalog)) { return false; } if (!Arrays.equals(columnIndexes, other.columnIndexes)) { return false; } if (!Arrays.equals(columnNames, other.columnNames)) { return false; } if (resultSetConcurrency == null) { if (other.resultSetConcurrency != null) { return false; } } else if (!resultSetConcurrency.equals(other.resultSetConcurrency)) { return false; } if (resultSetHoldability == null) { if (other.resultSetHoldability != null) { return false; } } else if (!resultSetHoldability.equals(other.resultSetHoldability)) { return false; } if (resultSetType == null) { if (other.resultSetType != null) { return false; } } else if (!resultSetType.equals(other.resultSetType)) { return false; } if (schema == null) { if (other.schema != null) { return false; } } else if (!schema.equals(other.schema)) { return false; } if (sql == null) { if (other.sql != null) { return false; } } else if (!sql.equals(other.sql)) { return false; } if (statementType != other.statementType) { return false; } return true; } /** * 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; } /** * 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; } /** * 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() { final int prime = 31; int result = 1; result = prime * result + ((autoGeneratedKeys == null) ? 0 : autoGeneratedKeys.hashCode()); result = prime * result + ((catalog == null) ? 0 : catalog.hashCode()); result = prime * result + Arrays.hashCode(columnIndexes); result = prime * result + Arrays.hashCode(columnNames); result = prime * result + ((resultSetConcurrency == null) ? 0 : resultSetConcurrency.hashCode()); result = prime * result + ((resultSetHoldability == null) ? 0 : resultSetHoldability.hashCode()); result = prime * result + ((resultSetType == null) ? 0 : resultSetType.hashCode()); result = prime * result + ((schema == null) ? 0 : schema.hashCode()); result = prime * result + ((sql == null) ? 0 : sql.hashCode()); result = prime * result + ((statementType == null) ? 0 : statementType.hashCode()); return result; } @Override public String toString() { final StringBuffer buf = new StringBuffer(); 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.java000066400000000000000000000121431352030664000334170ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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()); } /** * 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 e) { throw e; } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot close CallableStatement (return to pool failed)", e); } } } /** * 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(); } /** * 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 thrown = new ArrayList<>(); final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[resultSetList.size()]); for (final ResultSet resultSet : resultSets) { if (resultSet != null) { try { resultSet.close(); } catch (Exception e) { thrown.add(e); } } } clearTrace(); if (!thrown.isEmpty()) { throw new SQLExceptionList(thrown); } } super.passivate(); } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java000066400000000000000000000313311352030664000322110ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 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 (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 = false; /** * 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 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 } } } /** * * @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); } @Override protected void passivate() throws SQLException { super.passivate(); setClosedInternal(true); } /** * {@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; } /** * 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 e) { throw e; } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot close connection (return to pool failed)", e); } } } /** * Actually close my underlying {@link Connection}. */ @Override public void reallyClose() throws SQLException { if (jmxObjectName != null) { jmxObjectName.unregisterMBean(); } if (validationPreparedStatement != null) { try { validationPreparedStatement.close(); } catch (final SQLException sqle) { // Ignore } } super.closeInternal(); } /** * 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(); } /** * 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.length() == 0) { 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; } } /** * 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; } @Override protected void handleException(final SQLException e) throws SQLException { fatalSqlExceptionThrown |= isDisconnectionSqlException(e); super.handleException(e); } /** * @return The disconnection SQL codes. * @since 2.6.0 */ public Collection getDisconnectionSqlCodes() { return disconnectionSqlCodes; } /** * @return Whether to fail-fast. * @since 2.6.0 */ public boolean isFastFailValidation() { return fastFailValidation; } } PoolableConnectionFactory.java000066400000000000000000000525701352030664000334720ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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 int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; private long maxConnLifetimeMillis = -1; private final AtomicLong connectionIndex = new AtomicLong(0); 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 conn = p.getObject(); conn.activate(); if (defaultAutoCommit != null && conn.getAutoCommit() != defaultAutoCommit.booleanValue()) { conn.setAutoCommit(defaultAutoCommit.booleanValue()); } if (defaultTransactionIsolation != UNKNOWN_TRANSACTION_ISOLATION && conn.getTransactionIsolation() != defaultTransactionIsolation) { conn.setTransactionIsolation(defaultTransactionIsolation); } if (defaultReadOnly != null && conn.isReadOnly() != defaultReadOnly.booleanValue()) { conn.setReadOnly(defaultReadOnly.booleanValue()); } if (defaultCatalog != null && !defaultCatalog.equals(conn.getCatalog())) { conn.setCatalog(defaultCatalog); } if (defaultSchema != null && !defaultSchema.equals(Jdbc41Bridge.getSchema(conn))) { Jdbc41Bridge.setSchema(conn, defaultSchema); } conn.setDefaultQueryTimeout(defaultQueryTimeoutSeconds); } @Override public void destroyObject(final PooledObject p) throws Exception { p.getObject().reallyClose(); } /** * @return The cache state. * @since Made public in 2.6.0. */ public boolean getCacheState() { return cacheState; } /** * @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 try { conn.close(); } catch (final SQLException ignore) { // ignore } // 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(Long.toString(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.setCacheState(cacheState); } // Register this connection with JMX 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 = Boolean.valueOf(conn.getAutoCommit()); if (!connAutoCommit.booleanValue() && !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 = Boolean.valueOf(conn.getAutoCommit()); } if (!connAutoCommit.booleanValue()) { conn.setAutoCommit(true); } } conn.passivate(); } public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) { this.autoCommitOnReturn = autoCommitOnReturn; } public void setCacheState(final boolean cacheState) { this.cacheState = cacheState; } /** * 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) { try { this.pool.close(); } catch (final Exception e) { // ignored !?! } } 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 lifetime = System.currentTimeMillis() - p.getCreateTime(); if (lifetime > maxConnLifetimeMillis) { throw new LifetimeExceededException(Utils.getMessage("connectionFactory.lifetimeExceeded", Long.valueOf(lifetime), Long.valueOf(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; } } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/PoolableConnectionMXBean.java000066400000000000000000000041351352030664000332460ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 { // Read-only properties boolean isClosed() throws SQLException; // SQLWarning getWarnings() throws SQLException; String getToString(); // Read-write properties boolean getAutoCommit() throws SQLException; void setAutoCommit(boolean autoCommit) throws SQLException; boolean getCacheState(); void setCacheState(boolean cacheState); String getCatalog() throws SQLException; void setCatalog(String catalog) throws SQLException; int getHoldability() throws SQLException; void setHoldability(int holdability) throws SQLException; boolean isReadOnly() throws SQLException; void setReadOnly(boolean readOnly) throws SQLException; String getSchema() throws SQLException; void setSchema(String schema) throws SQLException; int getTransactionIsolation() throws SQLException; void setTransactionIsolation(int level) throws SQLException; // Methods void clearCachedState(); void clearWarnings() throws SQLException; void close() throws SQLException; void reallyClose() throws SQLException; } PoolablePreparedStatement.java000066400000000000000000000117001352030664000334600ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 = false; /** * 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()); } /** * 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 e) { throw e; } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot close preparedstatement (return to pool failed)", e); } } } @Override public void activate() throws SQLException { setClosedInternal(false); if (getConnectionInternal() != null) { getConnectionInternal().addTrace(this); } super.activate(); } @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 thrown = new ArrayList<>(); final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[resultSetList.size()]); for (final ResultSet resultSet : resultSets) { if (resultSet != null) { try { resultSet.close(); } catch (Exception e) { thrown.add(e); } } } clearTrace(); if (!thrown.isEmpty()) { throw new SQLExceptionList(thrown); } } super.passivate(); } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java000066400000000000000000000537111352030664000320710ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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; /** * 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); } } } /** * 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 columnIndexes * column indexes * * @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); } 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 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 catalog = null; try { catalog = getSchema(); } catch (final SQLException e) { // Ignored } return catalog; } /** * {@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 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 { try { return (CallableStatement) pstmtPool.borrowObject(createKey(sql, StatementType.CALLABLE_STATEMENT)); } catch (final NoSuchElementException e) { throw new SQLException("MaxOpenCallableStatements limit reached", e); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow callableStatement from pool failed", e); } } /** * 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 { try { return (CallableStatement) pstmtPool.borrowObject( createKey(sql, resultSetType, resultSetConcurrency, StatementType.CALLABLE_STATEMENT)); } catch (final NoSuchElementException e) { throw new SQLException("MaxOpenCallableStatements limit reached", e); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow callableStatement from pool failed", e); } } /** * 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 { try { return (CallableStatement) pstmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.CALLABLE_STATEMENT)); } catch (final NoSuchElementException e) { throw new SQLException("MaxOpenCallableStatements limit reached", e); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow callableStatement 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} */ @Override public PreparedStatement prepareStatement(final String sql) throws SQLException { if (null == pstmtPool) { throw new SQLException("Statement pool is null - closed or invalid PoolingConnection."); } try { return pstmtPool.borrowObject(createKey(sql)); } 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); } } @Override public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { if (null == pstmtPool) { throw new SQLException("Statement pool is null - closed or invalid PoolingConnection."); } try { return pstmtPool.borrowObject(createKey(sql, autoGeneratedKeys)); } 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 * @param columnIndexes * column indexes * @return a {@link PoolablePreparedStatement} */ @Override public PreparedStatement prepareStatement(final String sql, final int columnIndexes[]) throws SQLException { if (null == pstmtPool) { throw new SQLException("Statement pool is null - closed or invalid PoolingConnection."); } try { return pstmtPool.borrowObject(createKey(sql, columnIndexes)); } 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 * @param resultSetType * result set type * @param resultSetConcurrency * result set concurrency * @return a {@link PoolablePreparedStatement} */ @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { if (null == pstmtPool) { throw new SQLException("Statement pool is null - closed or invalid PoolingConnection."); } try { return pstmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency)); } 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 * @param resultSetType * result set type * @param resultSetConcurrency * result set concurrency * @param resultSetHoldability * result set holdability * @return a {@link PoolablePreparedStatement} */ @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { if (null == pstmtPool) { throw new SQLException("Statement pool is null - closed or invalid PoolingConnection."); } try { return pstmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); } 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 * @param columnNames * column names * @return a {@link PoolablePreparedStatement} */ @Override public PreparedStatement prepareStatement(final String sql, final String columnNames[]) throws SQLException { if (null == pstmtPool) { throw new SQLException("Statement pool is null - closed or invalid PoolingConnection."); } try { return pstmtPool.borrowObject(createKey(sql, columnNames)); } 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); } } /** * 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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java000066400000000000000000000205661352030664000320260ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 { private static final Log log = LogFactory.getLog(PoolingDataSource.class); /** Controls access to the underlying connection */ private boolean accessToUnderlyingConnectionAllowed; /** * 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 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; } /** * 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; } /* JDBC_4_ANT_KEY_BEGIN */ @Override public boolean isWrapperFor(final Class iface) throws SQLException { return false; } @Override public T unwrap(final Class iface) throws SQLException { throw new SQLException("PoolingDataSource is not a wrapper."); } /* JDBC_4_ANT_KEY_END */ @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } // --- DataSource methods ----------------------------------------- /** * 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 SQLException e) { throw e; } catch (final NoSuchElementException e) { throw new SQLException("Cannot get a connection, pool error " + e.getMessage(), e); } catch (final 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(); } /** * Returns my log writer. * * @return my log writer * @see DataSource#getLogWriter */ @Override public PrintWriter getLogWriter() { return logWriter; } /** * 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."); } /** * 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; } /** My log writer. */ private PrintWriter logWriter = null; private final ObjectPool pool; protected ObjectPool getPool() { return pool; } /** * 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); } /** * @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 void close() throws SQLException { if (getDelegateInternal() != null) { super.close(); super.setDelegate(null); } } @Override public boolean isClosed() throws SQLException { return getDelegateInternal() == null ? true : super.isClosed(); } } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java000066400000000000000000000206111352030664000312160ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.Set; 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 { /** 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<>(); /** 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; } /** * Returns the value of the accessToUnderlyingConnectionAllowed property. * * @return true if access to the underlying is allowed, false otherwise. */ protected boolean isAccessToUnderlyingConnectionAllowed() { return accessToUnderlyingConnectionAllowed; } /** * 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; } /** * 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); } /** * 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); } } } /** * Gets the pool names. * * @return the pool names. */ public synchronized String[] getPoolNames() { final Set names = pools.keySet(); return names.toArray(new String[names.size()]); } @Override public boolean acceptsURL(final String url) throws SQLException { return url == null ? false : url.startsWith(URL_PREFIX); } @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 SQLException e) { throw e; } catch (final NoSuchElementException e) { throw new SQLException("Cannot get a connection, pool error: " + e.getMessage(), e); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot get a connection, general error: " + e.getMessage(), e); } } return null; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } /** * 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) { // normal case final PoolGuardConnectionWrapper pgconn = (PoolGuardConnectionWrapper) conn; @SuppressWarnings("unchecked") final ObjectPool pool = (ObjectPool) pgconn.pool; try { pool.invalidateObject(pgconn.getDelegateInternal()); } catch (final Exception e) { // Ignore. } } else { throw new SQLException("Invalid connection class"); } } @Override public int getMajorVersion() { return MAJOR_VERSION; } @Override public int getMinorVersion() { return MINOR_VERSION; } @Override public boolean jdbcCompliant() { return true; } @Override public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) { return new DriverPropertyInfo[0]; } /** 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; /** * 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; } } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/SQLExceptionList.java000066400000000000000000000033661352030664000316150ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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; /** * A 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(List causeList) { super(String.format("%,d exceptions: %s", causeList.size(), causeList), causeList.get(0)); this.causeList = causeList; } public List getCauseList() { return causeList; } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/SwallowedExceptionLogger.java000066400000000000000000000041471352030664000334210ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/Utils.java000066400000000000000000000137741352030664000275470ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.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. */ public static final boolean IS_SECURITY_ENABLED = System.getSecurityManager() != null; /** 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 { 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(); } /** * 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(); } /** * 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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/cpdsadapter/000077500000000000000000000000001352030664000300625ustar00rootroot00000000000000ConnectionImpl.java000066400000000000000000000310751352030664000335750ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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(); } } } /** * 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; } } /** * 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; } } @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 autoGeneratedKeys) throws SQLException { checkOpen(); try { return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, autoGeneratedKeys)); } 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; } } // // Methods for accessing the delegate connection // /** * 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; } /** * 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; } } DriverAdapterCPDS.java000066400000000000000000000720361352030664000340640ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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.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 String KEY_USER = "user"; private static final String KEY_PASSWORD = "password"; 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 long timeBetweenEvictionRunsMillis = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; private int numTestsPerEvictionRun = -1; private int minEvictableIdleTimeMillis = -1; 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-arg 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(RefAddr ra) { return Boolean.valueOf(getStringContent(ra)).booleanValue(); } /** * 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 datasource. 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; } 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 this.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 #setMinEvictableIdleTimeMillis * @see #setTimeBetweenEvictionRunsMillis * @return the minimum amount of time a statement may sit idle in the pool. */ public int getMinEvictableIdleTimeMillis() { return minEvictableIdleTimeMillis; } /** * 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(KEY_USER); if (isNotEmpty(ra)) { setUser(getStringContent(ra)); } ra = ref.get(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; } /** * 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 classloader - ignore the exception upon first invocation. try { if (connectionProperties != null) { update(connectionProperties, KEY_USER, pooledUserName); update(connectionProperties, 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.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis()); config.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun()); config.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis()); } 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.setTimeBetweenEvictionRunsMillis(-1); config.setNumTestsPerEvictionRun(0); config.setMinEvictableIdleTimeMillis(0); } 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(KEY_PASSWORD, getPassword())); ref.add(new StringRefAddr(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("timeBetweenEvictionRunsMillis", String.valueOf(getTimeBetweenEvictionRunsMillis()))); ref.add(new StringRefAddr("numTestsPerEvictionRun", String.valueOf(getNumTestsPerEvictionRun()))); ref.add(new StringRefAddr("minEvictableIdleTimeMillis", String.valueOf(getMinEvictableIdleTimeMillis()))); ref.add(new StringRefAddr("maxPreparedStatements", String.valueOf(getMaxPreparedStatements()))); return ref; } private String getStringContent(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 #setTimeBetweenEvictionRunsMillis(long) */ public long getTimeBetweenEvictionRunsMillis() { return timeBetweenEvictionRunsMillis; } /** * 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(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(KEY_USER)) { setUser(connectionProperties.getProperty(KEY_USER)); } if (connectionProperties.containsKey(KEY_PASSWORD)) { setPassword(connectionProperties.getProperty(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 v * Value to assign to description. */ public void setDescription(final String v) { this.description = v; } /** * Sets the driver class name. Setting the driver class name cause the driver to be registered with the * DriverManager. * * @param v * 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 v) throws ClassNotFoundException { assertInitializationAllowed(); this.driver = v; // make sure driver is registered Class.forName(v); } /** * 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) { loginTimeout = seconds; } /** * Sets the log writer for this data source. NOT USED. */ @Override public void setLogWriter(final PrintWriter out) { logWriter = out; } /** * 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 minEvictableIdleTimeMillis * minimum time to set (in ms) * @see #getMinEvictableIdleTimeMillis() * @see #setTimeBetweenEvictionRunsMillis(long) * @throws IllegalStateException * if {@link #getPooledConnection()} has been called */ public void setMinEvictableIdleTimeMillis(final int minEvictableIdleTimeMillis) { assertInitializationAllowed(); this.minEvictableIdleTimeMillis = 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 #numIdle})/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 #setTimeBetweenEvictionRunsMillis(long) * @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, 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, 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 */ public void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { assertInitializationAllowed(); this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; } /** * Sets the value of URL string used to locate the database for this datasource. * * @param v * Value to assign to url. * @throws IllegalStateException * if {@link #getPooledConnection()} has been called */ public void setUrl(final String v) { assertInitializationAllowed(); this.url = v; } /** * Sets the value of default user (login or user name). * * @param v * Value to assign to user. * @throws IllegalStateException * if {@link #getPooledConnection()} has been called */ public void setUser(final String v) { assertInitializationAllowed(); this.userName = v; update(connectionProperties, KEY_USER, v); } /** * 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(timeBetweenEvictionRunsMillis); builder.append(", numTestsPerEvictionRun="); builder.append(numTestsPerEvictionRun); builder.append(", minEvictableIdleTimeMillis="); builder.append(minEvictableIdleTimeMillis); builder.append(", maxPreparedStatements="); builder.append(maxPreparedStatements); builder.append(", getConnectionCalled="); builder.append(getConnectionCalled); builder.append(", connectionProperties="); Properties tmpProps = connectionProperties; final String pwdKey = "password"; if (connectionProperties != null && connectionProperties.contains(pwdKey)) { tmpProps = (Properties) connectionProperties.clone(); tmpProps.remove(pwdKey); } builder.append(tmpProps); 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); } } } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PStmtKeyCPDS.java000066400000000000000000000104561352030664000331250ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.java000066400000000000000000000732711352030664000347440ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.Vector; 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 Vector eventListeners; /** * StatementEventListeners. */ private final Vector statementEventListeners = new Vector<>(); /** * 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 = new Vector<>(); closed = false; } /** * My {@link KeyedPooledObjectFactory} method for activating {@link PreparedStatement}s. * * @param key * Ignored. * @param pooledObject * Ignored. */ @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); } } /* JDBC_4_ANT_KEY_BEGIN */ @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 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 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 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; } } private String getSchemaOrNull() { try { return connection == null ? null : Jdbc41Bridge.getSchema(connection); } 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; } /** * 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} */ 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} * @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); } } 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); } } /** * 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}. * @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 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); } /* JDBC_4_ANT_KEY_BEGIN */ @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; } /** * 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; } /** * @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(); } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/cpdsadapter/package-info.java000066400000000000000000000060301352030664000332500ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/datasources/000077500000000000000000000000001352030664000301055ustar00rootroot00000000000000CPDSConnectionFactory.java000066400000000000000000000403121352030664000347720ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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 final String userName; private char[] userPassword; private long maxConnLifetimeMillis = -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.userName = userName; this.userPassword = 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)); } /** * (Testing API) Gets the value of password for the default user. * * @return value of password. */ char[] getPasswordCharArray() { return userPassword; } /** * Returns the object pool used to pool connections created by this factory. * * @return ObjectPool managing pooled connections */ public ObjectPool getPool() { return pool; } /** * * @param pool * the {@link ObjectPool} in which to pool those {@link Connection}s */ public void setPool(final ObjectPool pool) { this.pool = pool; } @Override public synchronized PooledObject makeObject() { PooledConnectionAndInfo pci; try { PooledConnection pc = null; if (userName == null) { pc = cpds.getPooledConnection(); } else { pc = cpds.getPooledConnection(userName, Utils.toString(userPassword)); } 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, userName, userPassword); pcMap.put(pc, pci); } catch (final SQLException e) { throw new RuntimeException(e.getMessage()); } return new DefaultPooledObject<>(pci); } /** * 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(); } @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); if (rset.next()) { valid = true; } else { valid = false; } 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; } @Override public void passivateObject(final PooledObject p) throws Exception { validateLifetime(p); } @Override public void activateObject(final PooledObject p) throws Exception { validateLifetime(p); } // *********************************************************************** // java.sql.ConnectionEventListener implementation // *********************************************************************** /** * 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(); } } // *********************************************************************** // PooledConnectionManager implementation // *********************************************************************** /** * 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); } } /** * Sets the database password used when creating new connections. * * @param userPassword * new password */ public synchronized void setPassword(final char[] userPassword) { this.userPassword = Utils.clone(userPassword); } /** * Sets the database password used when creating new connections. * * @param userPassword * new password */ @Override public synchronized void setPassword(final String userPassword) { this.userPassword = Utils.toCharArray(userPassword); } /** * 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. */ public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { this.maxConnLifetimeMillis = maxConnLifetimeMillis; } /** * 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.userName)) { return; } } try { pool.close(); } catch (final Exception ex) { throw new SQLException("Error closing connection pool", ex); } } private void validateLifetime(final PooledObject p) throws Exception { if (maxConnLifetimeMillis > 0) { final long lifetime = System.currentTimeMillis() - p.getCreateTime(); if (lifetime > maxConnLifetimeMillis) { throw new Exception(Utils.getMessage("connectionFactory.lifetimeExceeded", Long.valueOf(lifetime), Long.valueOf(maxConnLifetimeMillis))); } } } /** * @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(maxConnLifetimeMillis); builder.append(", validatingSet="); builder.append(validatingSet); builder.append(", pcMap="); builder.append(pcMap); builder.append("]"); return builder.toString(); } } InstanceKeyDataSource.java000066400000000000000000001322441352030664000350670ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.util.NoSuchElementException; 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 long defaultMaxWaitMillis = BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS; 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 long maxConnLifetimeMillis = -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; protected abstract PooledConnectionManager getConnectionManager(UserPassKey upkey); /* JDBC_4_ANT_KEY_BEGIN */ @Override public boolean isWrapperFor(final Class iface) throws SQLException { return false; } @Override public T unwrap(final Class iface) throws SQLException { throw new SQLException("InstanceKeyDataSource is not a wrapper."); } /* JDBC_4_ANT_KEY_END */ @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } // ------------------------------------------------------------------- // Properties /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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. */ public long getDefaultMaxWaitMillis() { return this.defaultMaxWaitMillis; } /** * 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. */ public void setDefaultMaxWaitMillis(final long maxWaitMillis) { assertInitializationAllowed(); this.defaultMaxWaitMillis = maxWaitMillis; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleTimeMillis()} for each per user * pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleTimeMillis()} for each per * user pool. */ public long getDefaultMinEvictableIdleTimeMillis() { return this.defaultMinEvictableIdleTimeMillis; } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleTimeMillis()} for each per user * pool. * * @param minEvictableIdleTimeMillis * The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleTimeMillis()} for each * per user pool. */ public void setDefaultMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { assertInitializationAllowed(); this.defaultMinEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * Sets the backend ConnectionPoolDataSource. This property should not be set if using JNDI to access the * data source. * * @param v * Value to assign to connectionPoolDataSource. */ public void setConnectionPoolDataSource(final ConnectionPoolDataSource v) { assertInitializationAllowed(); if (dataSourceName != null) { throw new IllegalStateException("Cannot set the DataSource, if JNDI is used."); } if (dataSource != null) { throw new IllegalStateException("The CPDS has already been set. It cannot be altered."); } dataSource = v; instanceKey = InstanceKeyDataSourceFactory.registerNewInstance(this); } /** * 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; } /** * 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 v * Value to assign to dataSourceName. */ public void setDataSourceName(final String v) { assertInitializationAllowed(); if (dataSource != null) { throw new IllegalStateException("Cannot set the JNDI name for the DataSource, if already " + "set using setConnectionPoolDataSource."); } if (dataSourceName != null) { throw new IllegalStateException("The DataSourceName has already been set. " + "It cannot be altered."); } this.dataSourceName = v; instanceKey = InstanceKeyDataSourceFactory.registerNewInstance(this); } /** * 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; } /** * 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 v * Value to assign to defaultAutoCommit. */ public void setDefaultAutoCommit(final Boolean v) { assertInitializationAllowed(); this.defaultAutoCommit = v; } /** * 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; } /** * 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 v * Value to assign to defaultReadOnly. */ public void setDefaultReadOnly(final Boolean v) { assertInitializationAllowed(); this.defaultReadOnly = v; } /** * 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; } /** * 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 v * Value to assign to defaultTransactionIsolation */ public void setDefaultTransactionIsolation(final int v) { assertInitializationAllowed(); switch (v) { 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 = v; } /** * 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; } /** * 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 v * Value to assign to description. */ public void setDescription(final String v) { this.description = v; } 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 backend 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; } /** * Sets the value of the given JNDI environment property to be used when instantiating a JNDI InitialContext. This * InitialContext is used to locate the backend 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 JNDI environment to be used when instantiating a JNDI InitialContext. This InitialContext is used to * locate the backend 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); } /** * Gets the value of loginTimeout. * * @return value of loginTimeout. */ @Override public int getLoginTimeout() { return loginTimeout; } /** * Sets the value of loginTimeout. * * @param v * Value to assign to loginTimeout. */ @Override public void setLoginTimeout(final int v) { this.loginTimeout = v; } /** * 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; } /** * Sets the value of logWriter. * * @param v * Value to assign to logWriter. */ @Override public void setLogWriter(final PrintWriter v) { this.logWriter = v; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * Returns 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. */ public long getMaxConnLifetimeMillis() { return 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. */ public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { this.maxConnLifetimeMillis = maxConnLifetimeMillis; } // ---------------------------------------------------------------------- // Instrumentation Methods // ---------------------------------------------------------------------- // DataSource implementation /** * 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 {@link 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 NoSuchElementException e) { closeDueToException(info); throw new SQLException("Cannot borrow connection from pool", e); } catch (final RuntimeException e) { closeDueToException(info); throw e; } catch (final 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 NoSuchElementException e) { closeDueToException(info); throw new SQLException("Cannot borrow connection from pool", e); } catch (final RuntimeException e) { closeDueToException(info); throw e; } catch (final 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 con = info.getPooledConnection().getConnection(); try { setupDefaults(con, userName); con.clearWarnings(); return con; } catch (final SQLException ex) { try { con.close(); } catch (final Exception exc) { getLogWriter().println("ignoring exception during close: " + exc); } throw ex; } } protected abstract PooledConnectionAndInfo getPooledConnectionAndInfo(String userName, String userPassword) throws SQLException; protected abstract void setupDefaults(Connection connection, String userName) throws SQLException; private void closeDueToException(final PooledConnectionAndInfo info) { if (info != null) { try { info.getPooledConnection().getConnection().close(); } catch (final Exception e) { // do not throw this exception because we are in the middle // of handling another exception. But record it because // it potentially leaks connections from the pool. getLogWriter().println("[ERROR] Could not return connection to " + "pool during exception handling. " + e.getMessage()); } } } 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) { cpds = (ConnectionPoolDataSource) ds; } else { throw new SQLException("Illegal configuration: " + "DataSource " + dataSourceName + " (" + ds.getClass().getName() + ")" + " doesn't implement javax.sql.ConnectionPoolDataSource"); } } // 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(", defaultMaxWaitMillis="); builder.append(defaultMaxWaitMillis); 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); } } InstanceKeyDataSourceFactory.java000066400000000000000000000330731352030664000364170ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.Iterator; 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; /** * A JNDI ObjectFactory which creates SharedPoolDataSources or PerUserPoolDataSources * * @since 2.0 */ abstract class InstanceKeyDataSourceFactory implements ObjectFactory { private static final Map instanceMap = new ConcurrentHashMap<>(); static synchronized String registerNewInstance(final InstanceKeyDataSource ds) { int max = 0; final Iterator iterator = instanceMap.keySet().iterator(); while (iterator.hasNext()) { final String s = iterator.next(); 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. instanceMap.put(instanceKey, ds); return instanceKey; } static void removeInstance(final String key) { if (key != null) { instanceMap.remove(key); } } /** * 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<>(instanceMap.size()); final Iterator> instanceIterator = instanceMap.entrySet().iterator(); while (instanceIterator.hasNext()) { // Bullet-proof to avoid anything else but problems from InstanceKeyDataSource#close(). final Entry next = instanceIterator.next(); if (next != null) { @SuppressWarnings("resource") final InstanceKeyDataSource value = next.getValue(); if (value != null) { try { value.close(); } catch (final Exception e) { exceptionList.add(e); } } } } instanceMap.clear(); if (!exceptionList.isEmpty()) { throw new ListException("Could not close all InstanceKeyDataSource instances.", exceptionList); } } /** * 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 = instanceMap.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 = instanceMap.get(key); } if (obj == null) { final InstanceKeyDataSource ds = getNewInstance(ref); setCommonProperties(ref, ds); obj = ds; if (key != null) { instanceMap.put(key, ds); } } } } } return obj; } 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.valueOf(refAddr.getContent().toString()).booleanValue()); } 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.valueOf(refAddr.getContent().toString()).booleanValue()); } 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.valueOf(refAddr.getContent().toString()).booleanValue()); } refAddr = ref.get("testOnBorrow"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultTestOnBorrow(Boolean.valueOf(refAddr.getContent().toString()).booleanValue()); } refAddr = ref.get("testOnReturn"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultTestOnReturn(Boolean.valueOf(refAddr.getContent().toString()).booleanValue()); } refAddr = ref.get("testWhileIdle"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultTestWhileIdle(Boolean.valueOf(refAddr.getContent().toString()).booleanValue()); } 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.valueOf(refAddr.getContent().toString()).booleanValue()); } 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())); } } /** * @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); /** * 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; /** * 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 { if (in != null) { try { in.close(); } catch (final IOException ex) { // ignore } } } } } KeyedCPDSConnectionFactory.java000066400000000000000000000336051352030664000357630ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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 long maxConnLifetimeMillis = -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; } public void setPool(final KeyedObjectPool pool) { this.pool = pool; } /** * Returns the keyed object pool used to pool connections created by this factory. * * @return KeyedObjectPool managing pooled connections */ public KeyedObjectPool getPool() { return pool; } /** * Creates a new {@link PooledConnectionAndInfo} from the given {@link UserPassKey}. * * @param upkey * {@link 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 upkey) throws Exception { PooledConnectionAndInfo pci = null; PooledConnection pc = null; final String userName = upkey.getUsername(); final String password = upkey.getPassword(); if (userName == null) { pc = cpds.getPooledConnection(); } else { pc = cpds.getPooledConnection(userName, password); } 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, userName, upkey.getPasswordCharArray()); pcMap.put(pc, pci); return new DefaultPooledObject<>(pci); } /** * Closes the PooledConnection and stops listening for events from it. */ @Override public void destroyObject(final UserPassKey key, final PooledObject p) throws Exception { final PooledConnection pc = p.getObject().getPooledConnection(); pc.removeConnectionEventListener(this); pcMap.remove(pc); pc.close(); } /** * Validates a pooled connection. * * @param key * ignored * @param pooledObject * wrapped {@link 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); if (rset.next()) { valid = true; } else { valid = false; } 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; } @Override public void passivateObject(final UserPassKey key, final PooledObject p) throws Exception { validateLifetime(p); } @Override public void activateObject(final UserPassKey key, final PooledObject p) throws Exception { validateLifetime(p); } // *********************************************************************** // java.sql.ConnectionEventListener implementation // *********************************************************************** /** * 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(); } } // *********************************************************************** // PooledConnectionManager implementation // *********************************************************************** /** * 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); } } /** * 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. } /** * 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. */ public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { this.maxConnLifetimeMillis = maxConnLifetimeMillis; } /** * 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); } } private void validateLifetime(final PooledObject p) throws Exception { if (maxConnLifetimeMillis > 0) { final long lifetime = System.currentTimeMillis() - p.getCreateTime(); if (lifetime > maxConnLifetimeMillis) { throw new Exception(Utils.getMessage("connectionFactory.lifetimeExceeded", Long.valueOf(lifetime), Long.valueOf(maxConnLifetimeMillis))); } } } } PerUserPoolDataSource.java000066400000000000000000001236631352030664000350760ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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() */ @Override public void close() { for (final PooledConnectionManager manager : managers.values()) { try { getCPDSConnectionFactoryPool(manager).close(); } catch (final Exception closePoolException) { // ignore and try to close others. } } 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.booleanValue(); } /** * 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.booleanValue(); } /** * 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.intValue(); } /** * 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.intValue(); } /** * 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.longValue(); } /** * Gets the user specific value for {@link GenericObjectPool#getMinEvictableIdleTimeMillis()} 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.longValue(); } /** * 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.intValue(); } /** * 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.intValue(); } /** * Gets the user specific value for {@link GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} 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.longValue(); } /** * 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.booleanValue(); } /** * 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.booleanValue(); } /** * 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.booleanValue(); } /** * 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.booleanValue(); } /** * Gets the user specific value for {@link GenericObjectPool#getTimeBetweenEvictionRunsMillis()} 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.longValue(); } /** * 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.setMaxConnLifetimeMillis(getMaxConnLifetimeMillis()); // 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#getMinEvictableIdleTimeMillis()} 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#getSoftMinEvictableIdleTimeMillis()} 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#getTimeBetweenEvictionRunsMillis ()} 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.intValue(); } } if (defaultAutoCommit != null && con.getAutoCommit() != defaultAutoCommit.booleanValue()) { con.setAutoCommit(defaultAutoCommit.booleanValue()); } if (defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION) { con.setTransactionIsolation(defaultTransactionIsolation); } if (defaultReadOnly != null && con.isReadOnly() != defaultReadOnly.booleanValue()) { con.setReadOnly(defaultReadOnly.booleanValue()); } } } PerUserPoolDataSourceFactory.java000066400000000000000000000074431352030664000364230ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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(); @Override protected boolean isCorrectClass(final String className) { return PER_USER_POOL_CLASSNAME.equals(className); } @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; } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java000066400000000000000000000050301352030664000323300ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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; /** * @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 (dataSourceName == null) { if (other.dataSourceName != null) { return false; } } else if (!dataSourceName.equals(other.dataSourceName)) { return false; } if (userName == null) { if (other.userName != null) { return false; } } else if (!userName.equals(other.userName)) { return false; } return true; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((dataSourceName == null) ? 0 : dataSourceName.hashCode()); result = prime * result + ((userName == null) ? 0 : userName.hashCode()); return result; } @Override public String toString() { final StringBuffer sb = new StringBuffer(50); sb.append("PoolKey("); sb.append(userName).append(", ").append(dataSourceName); sb.append(')'); return sb.toString(); } } PooledConnectionAndInfo.java000066400000000000000000000047051352030664000354000ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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; import org.apache.commons.dbcp2.Utils; /** * Immutable poolable object holding a 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 char[] userPassword; private final String userName; private final UserPassKey upKey; /** * @since 2.4.0 */ PooledConnectionAndInfo(final PooledConnection pc, final String userName, final char[] userPassword) { this.pooledConnection = pc; this.userName = userName; this.userPassword = userPassword; this.upKey = new UserPassKey(userName, userPassword); } /** * @deprecated Since 2.4.0 */ @Deprecated PooledConnectionAndInfo(final PooledConnection pc, final String userName, final String userPassword) { this(pc, userName, Utils.toCharArray(userPassword)); } PooledConnection getPooledConnection() { return pooledConnection; } UserPassKey getUserPassKey() { return upKey; } /** * Gets the value of password. * * @return value of password. */ String getPassword() { return Utils.toString(userPassword); } /** * Gets the value of password. * * @return value of password. * @since 2.4.0 */ char[] getPasswordCharArray() { return userPassword; } /** * Gets the value of userName. * * @return value of userName. */ String getUsername() { return userName; } } PooledConnectionManager.java000066400000000000000000000042221352030664000354260ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 PooledConnection and remove it from the connection pool to which it belongs, adjusting pool counters. * * @param pc * PooledConnection to be invalidated * @throws SQLException * if an SQL error occurs closing the connection */ void invalidate(PooledConnection pc) throws SQLException; // /** // * Sets the database password used when creating connections. // * // * @param password password used when authenticating to the database // * @since 3.0.0 // */ // void setPassword(char[] password); /** * Sets the database password used when creating connections. * * @param password * password used when authenticating to the database */ void setPassword(String password); /** * 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; } SharedPoolDataSource.java000066400000000000000000000220621352030664000347060ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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()); } // ------------------------------------------------------------------- // Properties /** * Gets {@link GenericKeyedObjectPool#getMaxTotal()} for this pool. * * @return {@link GenericKeyedObjectPool#getMaxTotal()} for this pool. */ public int getMaxTotal() { return this.maxTotal; } /** * 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; } // ---------------------------------------------------------------------- // 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(); } // ---------------------------------------------------------------------- // Inherited abstract methods @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); } } } PooledConnectionAndInfo info = null; final UserPassKey key = new UserPassKey(userName, userPassword); try { info = pool.borrowObject(key); } catch (final Exception e) { throw new SQLException("Could not retrieve connection info from pool", e); } return info; } @Override protected PooledConnectionManager getConnectionManager(final UserPassKey upkey) { return factory; } /** * Returns a SharedPoolDataSource {@link Reference}. */ @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; } 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.setMaxConnLifetimeMillis(getMaxConnLifetimeMillis()); 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(getDefaultMaxWaitMillis()); 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; } @Override protected void setupDefaults(final Connection connection, final String userName) throws SQLException { final Boolean defaultAutoCommit = isDefaultAutoCommit(); if (defaultAutoCommit != null && connection.getAutoCommit() != defaultAutoCommit.booleanValue()) { connection.setAutoCommit(defaultAutoCommit.booleanValue()); } final int defaultTransactionIsolation = getDefaultTransactionIsolation(); if (defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION) { connection.setTransactionIsolation(defaultTransactionIsolation); } final Boolean defaultReadOnly = isDefaultReadOnly(); if (defaultReadOnly != null && connection.isReadOnly() != defaultReadOnly.booleanValue()) { connection.setReadOnly(defaultReadOnly.booleanValue()); } } /** * 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); } } @Override protected void toStringFields(final StringBuilder builder) { super.toStringFields(builder); builder.append(", maxTotal="); builder.append(maxTotal); } } SharedPoolDataSourceFactory.java000066400000000000000000000032431352030664000362360ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 boolean isCorrectClass(final String className) { return SHARED_POOL_CLASSNAME.equals(className); } @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; } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java000066400000000000000000000073071352030664000331750ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 org.apache.commons.dbcp2.Utils; /** *

* Holds a user name and password pair. Serves as a poolable object key for the KeyedObjectPool backing a * 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 * 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 String userName; private final char[] userPassword; /** * @since 2.4.0 */ UserPassKey(final String userName) { this(userName, (char[]) null); } /** * @since 2.4.0 */ UserPassKey(final String userName, final char[] password) { this.userName = userName; this.userPassword = password; } UserPassKey(final String userName, final String userPassword) { this(userName, Utils.toCharArray(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; if (userName == null) { if (other.userName != null) { return false; } } else if (!userName.equals(other.userName)) { return false; } return true; } /** * Gets the value of password. * * @return value of password. */ public String getPassword() { return Utils.toString(userPassword); } /** * Gets the value of password. * * @return value of password. */ public char[] getPasswordCharArray() { return userPassword; } /** * Gets the value of user name. * * @return value of user name. */ public String getUsername() { return userName; } /** * Only takes the user name into account. */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((userName == null) ? 0 : userName.hashCode()); return result; } @Override public String toString() { final StringBuffer sb = new StringBuffer(super.toString()); sb.append("["); sb.append(userName); sb.append(']'); return sb.toString(); } } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/datasources/package-info.java000066400000000000000000000132251352030664000332770ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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 backend 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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/managed/000077500000000000000000000000001352030664000271645ustar00rootroot00000000000000BasicManagedDataSource.java000066400000000000000000000251351352030664000342270ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 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; import javax.sql.DataSource; import javax.sql.XADataSource; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import java.sql.SQLException; /** *

* 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; /** * Gets the XADataSource instance used by the XAConnectionFactory. * * @return the XADataSource */ public synchronized XADataSource getXaDataSourceInstance() { return xaDataSourceInstance; } /** *

* 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(); } /** * Gets the required transaction manager property. * * @return the transaction manager used to enlist connections */ public TransactionManager getTransactionManager() { return transactionManager; } /** * 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 transaction registry. * * @return the transaction registry associating XAResources with managed connections */ protected synchronized TransactionRegistry getTransactionRegistry() { return transactionRegistry; } /** * 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; } /** * Gets the optional XADataSource class name. * * @return the optional XADataSource class name */ public synchronized String getXADataSource() { return xaDataSource; } /** * Sets the optional XADataSource class name. * * @param xaDataSource * the optional XADataSource class name */ public synchronized void setXADataSource(final String xaDataSource) { this.xaDataSource = xaDataSource; } @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(), 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.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; } } DataSourceXAConnectionFactory.java000066400000000000000000000237101352030664000356060ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/managed/** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import javax.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; import java.sql.Connection; import java.sql.SQLException; import java.util.Objects; /** * 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; } /** * 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 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; } public char[] getUserPassword() { return userPassword; } 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; } /** * 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.java000066400000000000000000000333071352030664000346110ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 org.apache.commons.dbcp2.ConnectionFactory; import javax.transaction.TransactionManager; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import java.sql.Connection; import java.sql.SQLException; import java.util.Objects; /** * 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 final Connection connection; private Xid currentXid; // @GuardedBy("this") private boolean originalAutoCommit; // @GuardedBy("this") 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 a 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 new Xid[0]; } /** * 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 a 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) { Objects.requireNonNull(transactionManager, "transactionManager is null"); Objects.requireNonNull(connectionFactory, "connectionFactory is null"); this.transactionRegistry = new TransactionRegistry(transactionManager); 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.java000066400000000000000000000310341352030664000333250ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 org.apache.commons.dbcp2.DelegatingConnection; import org.apache.commons.pool2.ObjectPool; import java.sql.Connection; import java.sql.SQLException; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 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); } 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; } // 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.java000066400000000000000000000072221352030664000332620ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 org.apache.commons.pool2.ObjectPool; import org.apache.commons.dbcp2.PoolingDataSource; import java.sql.Connection; import java.sql.SQLException; import java.util.Objects; /** * 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.java000066400000000000000000000061531352030664000350070ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.java000066400000000000000000000115051352030664000363340ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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(Long.toString(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.java000066400000000000000000000213161352030664000336050ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/managed/** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import javax.transaction.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; import java.sql.Connection; import java.sql.SQLException; import java.util.Objects; import java.lang.ref.WeakReference; /** * 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; /** * 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; } /** * 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); } /** * 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; } /** * 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; } /** * 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 ? false : transaction.getStatus() == Status.STATUS_COMMITTED); return; } final Synchronization s = new Synchronization() { @Override public void beforeCompletion() { // empty } @Override public void afterCompletion(final int status) { listener.afterCompletion(TransactionContext.this, status == Status.STATUS_COMMITTED); } }; if (transactionSynchronizationRegistry != null) { transactionSynchronizationRegistry.registerInterposedSynchronization(s); } else { getTransaction().registerSynchronization(s); } } catch (final RollbackException 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); } } /** * 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); } } 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; } /** * Sets the transaction complete flag to true. * * @since 2.4.0 */ public void completeTransaction() { this.transactionComplete = true; } /** * Gets the transaction complete flag to true. * * @return The transaction complete flag. * * @since 2.4.0 */ public boolean isTransactionComplete() { return this.transactionComplete; } } TransactionContextListener.java000066400000000000000000000024551352030664000353160ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.java000066400000000000000000000144521352030664000337740ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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; /** * 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; } /** * Provided for backwards compatibility * @param transactionManager the transaction manager used to enlist connections */ public TransactionRegistry(final TransactionManager transactionManager) { this (transactionManager, null); } /** * 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); } /** * 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; } /** * 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; } } /** * 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); } private Connection getConnectionKey(final Connection connection) { Connection result; if (connection instanceof DelegatingConnection) { result = ((DelegatingConnection) connection).getInnermostDelegateInternal(); } else { result = connection; } return result; } } XAConnectionFactory.java000066400000000000000000000044651352030664000336410ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 { /** * 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(); /** * 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; } commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/managed/package-info.java000066400000000000000000000036161352030664000323610ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/overview.html000066400000000000000000000017311352030664000303260ustar00rootroot00000000000000 Overview of the org.apache.commons.dbcp component

Commons Database Connection Pooling

commons-dbcp-commons-dbcp-2.7.0/src/main/java/org/apache/commons/dbcp2/package-info.java000066400000000000000000000154501352030664000307640ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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 * behaviour. *

*

* 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-commons-dbcp-2.7.0/src/main/resources/000077500000000000000000000000001352030664000222045ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/resources/org/000077500000000000000000000000001352030664000227735ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/resources/org/apache/000077500000000000000000000000001352030664000242145ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/resources/org/apache/commons/000077500000000000000000000000001352030664000256675ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/resources/org/apache/commons/dbcp2/000077500000000000000000000000001352030664000266615ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/main/resources/org/apache/commons/dbcp2/LocalStrings.properties000066400000000000000000000025421352030664000334060ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT 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-commons-dbcp-2.7.0/src/media/000077500000000000000000000000001352030664000203255ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/media/dbcp-logo-white.xcf000066400000000000000000000573311352030664000240240ustar00rootroot00000000000000gimp 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-ShadowÌ     ÿÿÿúÿÿÿú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[\[XUQNLLì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;>@AAì?=;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-commons-dbcp-2.7.0/src/site/000077500000000000000000000000001352030664000202125ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/site/resources/000077500000000000000000000000001352030664000222245ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/site/resources/download_dbcp.cgi000077500000000000000000000002351352030664000255120ustar00rootroot00000000000000#!/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-commons-dbcp-2.7.0/src/site/resources/images/000077500000000000000000000000001352030664000234715ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/site/resources/images/dbcp-logo-blue.jpg000066400000000000000000000125671352030664000270010ustar00rootroot00000000000000ÿØÿà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ú¶°­–Ò…¬Ù½}YÞö>hñ—üÚÏý„'ÿÑY5­ã/ùõŸûOÿ£²kÙŽÈò%» (¢˜‚¾…ý>é|qâoê:œ2Ü46Ù´k¹S†‘‹+dnÊã ~CÉÈǃhšmÖ³­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«Ì›‹žAò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§È~wì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¿>@#€Çjžkæ½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:îöÙt1ž20º¢­~½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ŠÍè{wìU¤Á©|kK©—sišl÷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¾#ÿŸÝ'þþÉÿÄQEòTð©|Gÿ?ºOýý“ÿˆ¯¥?áÕ¿çâËþûoþ&Š+—7¡Õ†ŠÔÿÙcommons-dbcp-commons-dbcp-2.7.0/src/site/resources/images/dbcp-logo-white.png000066400000000000000000000300421352030664000271620ustar00rootroot00000000000000‰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îËõë××§æoìÞ½ÛB ëêêŒ]»vÙÖuãÆ ã»ï¾3ûÒ!¿9EÄü׿þeÙà/¾øÂ2‘ºº:sànݺÙ½bÅ ã믿6ßk×®YÿÝwß3fÌÐ" í_mÖ!ClãdeeiÇ7nœ1dÈcèСâÁ¬^½Ú8sæŒ9ÿ¸¸8cìØ±Æ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ý_¿~Ý<¤¯¾úÊ.úfffšc¨q¾üòK³ŽS(DïÚµ«±mÛ6ãË/¿4û¨ªª2ªªªŒcÇŽ‰k[²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#))Éü¿š£šoXX6oÞŒ‡~Ø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=Ï<ó î¹çqŽt;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/^lŽCçäöòÃŒŽŽ6ÿ®„¤ú¹}ûö6@ˆŒŒtDJÕGBB‚­íÖ­[µÀ^[[«EÌÈÈH‘«C‡¶¶ááá–5©÷Æ–>:vìhk[PP`CÍsñâÅ6n§CDŽ`ê›Aƒ‰ˆFÏÎ1 Ú¾ˆˆ0÷¥1„òÊ•+¶oèÏ aàÒ¥K˜7ož6é:Õº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"## mò·šÀ| r-5yŽtcé÷ïß߆˜GµGNr©µ©uòÃÔ!¦ßï·ˆ! ëŸùê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¨|,)¬¼­úEÞ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ðáÀÈÍÚ\çrò‡¤‡.Éê|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ÍàóùlžPZZ*ŠX:cµzÒ§cÇŽ6®@ÅLbJîbn@C•{§oÜAÇ=ݨºb9é4W][ºNJá[¶liûöøñãÚKu®8¥ÛyºéÁÜ0évŽTÓ@ÞoDDÆŒƒµk×"55UDεk׊̆âŽN¼õªàUéêáðáÃ6Hý,YN•ØúÁ`ìØ±!qM…˜üº@Ç=tw¢ýúõE6ÝaJE AÌ⺳ø: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„„ÏMšcôé{ï½×ö}QQ‘+œp£wÜÑÑÑøóŸÿl#zn¹wœ¤‰ÆœvïÞ-ˆ´wC† Ѧ$_gQ·\—Œ7NäšÛ·oǨQ£PZZª5°|ùräääàòåËX´h‘x}âõzñÚk¯ÙÆX»v­éäf54 Ã⎃gžyF‹¡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ß;wŠOÚ/é),,ÄðáÃ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*ÒJž1 ع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Íš‰Ž47Štì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­•—¦ÇãÑgbwòÚáŽËº×É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¡sŽ9RDh§ÂC<æ“–£§¥ì;vìhà-[¶ˆÈLéi2常8äååYJ!rÂÀ ýûˆ#ëzm%!&¦uZ:wîliSRR‚/¾øÂŒ1ÖÕåáiElye‹ nêßc]mL›Æô÷ß7‚ðc_§¸I*BòÌ´ê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;U5nžŽfP ó¤^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!æMòè²}óð.)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]¾džoŠÏ#¦ÒÁËÊÊ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{œRŠXÒ!¨S¹'¨K•B‰(fûoߛ݊ñr/“üü|·¼ë®»´‰µtW N‰·è›ššjëãäÉ“¶>h!\õS•rJ¡€ºP¼PöÕ)xŸrËPc‰›8æ/Äø —””XÒcÀÃ?ìÊ$ŽÉÕ-;ž®_õ]Ïž=mßmذÁvWë¶åÙ£ã¤NHéæ+ÍÓeò@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 YÌ+Ûôüïr .àïÿ;Ö¯_/~…„„ Àq.11ƒ ÂàÁƒoµºTaUµµµæÏÁ`ÇÇôéÓ-ŽÛôiÛ¶-Zµjeá<WëСÆoΓ‡FÑ»IŽäÕÕÕ˜1cN:e»}ûöèØ±£‰555(--Åûï¿ääd¼ð èÑ£‡¶ÆJCCæÎ‹gžyÆ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Šà‰'žÀˆ#PZZŠC‡iËR4E—ÜdÖXŽ8<>‘»ÈÑï¤$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Þ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-commons-dbcp-2.7.0/src/site/resources/images/uml/000077500000000000000000000000001352030664000242665ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/site/resources/images/uml/AbandonedObjectPool.gif000066400000000000000000000540651352030664000306230ustar00rootroot00000000000000GIF89aÄJ÷ÿÿ{{{{{„{„{{„„„{{„{„„„{„„„”)”1œ)œ1œ9½½½½Æ½½ÆÆÆ½½Æ½ÆÆÆ½ÆÆÆ÷ÿÆ÷ÿÎÿÿÿÿÿÿÆÿÿÎÿÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,ÄJþ;H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóꕸ Aƒ¾€ÿ¼€ðßÃ{+^̘fƒŽKžL¹²Æ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Žêzì‡G]ðÊ@K]=Ïáþ꯱oª‡¨vo;ßÓë|üë¼;ÒÚçG<ÛÐ ›ª‡Þ’l¯²‚ßìô1Ëû/ý¤óÐúg´©É®uï{^üJƼ9åKoðCÜïæ/›éÏxµûøhE8®Y¥òà}7Bû™Ï}èó—ú@²ž…0Ä`ÝH…¢Z/wÁÒ°ôW¸Í} |þBò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&À”ÙRVjPže¼è=ш°"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‰žÖ¶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*ñí¶³,®$À&Ü mò·¿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Î…öû¹>õ®=ú•¦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²MŠNfTx{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?€ølìˆ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•VÞ#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ئÂXšys§uÚ,&Û4=‚UÄNÌé6þœ…4XšvTº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·,»ÀÒ®Ú+\nÞ=£Û,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~$ukŽGãµå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̽1iÌâÝ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úƒÚ*>”ÇUŠ2µ×=ç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‘,ižì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·lò/¨¾ˆþÜ0¿ ×´Ó<û&›±ø°ZÌÑ#p£ mò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ŽwìŠ÷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#jdŽ4JfBt‡*Ô]&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†ëÔÔ¨E̲µ>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'*Kò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ÐÒ¿°@Aì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&ó˜¯ Ÿuì¿óÈ 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˜rUŽyÆ!u riÊñKšr;¿mìê“{º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/ô£FX1OrsOžiܣйÑZ©üâZXAÚn¤*êSBÂH%ß$:¢Ke#)DyD™‘Å8ÍðÖÕ*ÚÙý"°ÝÇ„\NvÃð·¢ãÎìÔÏDQrJäÄÂ8RÝ“•¾ý[¡xÞèåàÉb"Éø©ýMˆ§8ŸãÉ›Zà˜¹ÁÙ:òÖpÎ å#~Eׯ §¢ÀjÕŠSÜtÒZSù ÈaÜ8Õ«Lò½\<þ`û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×’ôÞ÷ìAÞ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·ÖgŽP5cûÃYÔÙMÊôÖåÈŽÚ’1žb§%{—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ÇÆ7ŽlÕc8Z5í³Ø7i:»§É±éóðr4¦{¥Æ )™Ømg´ö‰¸ºXr¦@¡w¬I®Q„ñ²àþraŽFÉ .ç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ѰùQ9Žšz{Qïz‰îs~IÚh™‹þã ²/qy׫>;eË—¿ÀÇÁ”Ðùç¨H²ºÂ+Üj.å"ï†×i·óW¾`–jX&i†Üô©ê"qšk™l¡º}ØL/zËßú{Û%qÿÞÄVpšáêµþ¶Þöíúlì2èÏCÖÇmeùÊ¿QÃ14j‘_Õ†Võ@&·-7ü´h‰¬PoóìàΈ 6@ðàÀƒ &D¨`CˆNŒ(ñ¡EŠ+rÜèQaÆAŽt(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{Eì²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†£ä'WÞò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‰-Uvò#É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^dKAŽ2yWÙÍžÐxœ`-mUI¦6Ào ˆÄ¸]ðüĆtË}ÙŒÍß#ÙÔkðÕ‹MDXE¶à6Ê89!xA¡÷Y`%N ÷ è\Ni"Ô~PÂνe Éáà]\£MÑà$Ð#RRÔÅÙ™H¥azŠF0ιð®ÝgqH‡ôÅiÝ2¢Ì9æÕ@tžþ$êQfŸNcƒDÎ ®¡!*Ä"&”ÑÝÎ'qð´O3º‹SçÍ!n„–¹ñpÀÝÙ™'áÒщ٪hV D.é!— íG^^#º LýX4&¤Áa  àב)YŸ•'EÎÍáHöÅþÑšå%¡AÞQ,FÂÕʸ0wp£M[¬¾1t0MIRïŠP¶¬š?! Ù­¡æÁ–Bö$µaÛ’ÉŸñ×Ôqˆm=Í_aˆ–#:ŸA `A#£å‹àðc7â˜Ö˜\Û¨M Öbú#"òSì#–$|-#ü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 ÐÐ]]ú%VÞ…(ˆ²¨ ñ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.ò¹­ûÊiŽR0 çœ×ðYlhÊÜ—M‚Ä(nê7PW‘¦¦j‡¦`òÁ0ü61Ñ\0G±::?Ë rO'!ëi{*[\Z¢aW,°‚E/3iÌ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{±«\›þ±õ:¬žOÒ­Ûz€dxVGŸ.!P]¨òßã8.ù_~8šštTúŽè Ì} ¯Z™ “«ƒM ,¾]°ßŒ)ö%x£þëÈ‘ÁÔzñåc¹ÔB;;{h2,þ^!zKé`¸oXÈå–×N쀩㜠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¸‡Ušòÿ\®þÜ#Rl’óÍ=Ï ÒgaìpS1i&éô[ÍBÙíâw“d&ÙþŠW0ÁÐ*N»ZÖðŽö®öQË>r¡•Ã40AÞ‡$!¸î×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-þ&©êËÑRìÏ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ÀPšNo ã¬Ò(’ 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öéƒølKìªê€(ˆôç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©ÎÙš-ŠÎ='uì¶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ì¢#š¢k¬¢=£7vŸ½¸„B¬ã £ZÕÙ/ž‚¥%–ezBe/^ú'‚b;Í]ãc¨rš#þMú ¡/M–N™ý„ïüOmz[ŠúûYA,;õeŸÖ­‰/p·®—ó…:-yŒšš%ö‰ìVNüô1`ºŽ»–ÃæÙ5cšŽ/ÜÂÒCUž0hy ¾®å—:¬×ßðƒ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|$¼¸†ÆMtHò'³BRð:3K•:â¾NŽqEA=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ƒ]Ùë½åoÞq~âãÝbþPžn=^¶K~çaÞæžè 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-commons-dbcp-2.7.0/src/site/resources/images/uml/BasicDataSource.gif000066400000000000000000000373111352030664000277560ustar00rootroot00000000000000GIF89aÄ™÷ÿÿ„{{„„„”)”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ãÇŽ‡H`-]µ{ÓòÕü—ófÏuAËYóeÓ¤C“f;Y ÏÑqÝÒ•ýYõØÙŸcçî|›7íÝ£mÿ>\xm]÷>>tPСþéhuéa…F—^Ö­sì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ÝkTŠráá}±é [„sýK°RÓªF„žÅ%Ÿ´ÒÆ^dQ! ÙÅgÌXc슱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áAÞ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Ⱦ(€ÂàÄ”&¥¤|ÖNžz¦U¯%M`‚ʧþËvÉC –º½dÕOð€ó¯=úNTýÙQ&4Oõ„+OÉÉSxv´£ïúbñ;QnB,“ –¡þ’ ô¼X£:ðC»*©oIê¯6Íêx¨œçbZئ@°ˆòš^Y¦Y¤ð=ôè ‹Ð2uÕÆ²dÇbšQƒÊ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óÌÜà ±ÍeìïÎñ¹†öï{ÄÇ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®‡(ÖAÞÕ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‰·eÞâTúÅ ­v–ò±–¤2Lh6R©²è_–(IÞ%&Õ„æ—ç!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›ÜšrŽaa™Ô¨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~qŽkh傱u¥–Řh°›uq›©!€‰¦þų£¯ÓGUʦ¢ݳ† ©Ð@`ÓòJʸ-\II÷X²¹§mˆJnEžRd¦¢{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þôRdžvâÄ©^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¶„Â*‹b5Žv(Â^‚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ÕcVògæl/9Ýûa$=’É$g½fÌt*Ïêô¨tšlVFÊ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íŠxšoÓS¶TYì‘ÜÞ¨Ò¢Ú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(¸€cÇ‹ŠÄ¹3*ÔžS•výX–aΦ9ÙŽwæÑŒRïÖ\óªÈ¾&ýb]Šr¥„!pÀ˜c€n^t[¶íQ‚–*NJ‘'ܼþS‰–ìÌ´¢ÄˆBj&¬ÖçM‹!¯æ”œ÷¤\†·Jüú52Z tͲ€ycAÉ£uŽmj²véãË÷ÎôÊñ©Ëª4µ+ 9ä׃’¡vm2ëá–7†,^øZŠ© ”\{§û©§CÃ$8ºyN’3o ¨j¨8ú`ð3„¼³,,…Ü“¬ª'N7•¸ˆ£ÆˆÌ¥Þ‹ ðâCp1ˆê[¨7ðī;:1<úJìm$íÛ €&:кŒnì¯D‹“£kBPH°àÓI+•ÒCÎÈE:€Ñt$ F7ŠD+‘£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ŒU̦8=ΫëfÓkÑVïrµRhËL2¼/Ëd³L0ËìÌP®ÜrLº<ˆÂÁrµ¸«ôœ°£+uÒMj ºAH‹-ª*¹" Õ s5ÑFdIÒ=€·}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;kxžuÑÆ: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 —*Ü þzKì¥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ƒ°`ESššDú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=Ü/Ñ$Ï"œ›|¾,ÈýëÁâ5ŠPÎÖü)º™Å-°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²¤ƒRša1;œ¾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Ý3Dž8°‰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î<‚Œ oÞ•{2­_ëdžZ¬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¹å½‹®«]>®!«é.‚=MHò±”\FR-%Ý©c“…ì[=.§à"ÑâÊËÆqT““SeÌ_)àÜnXBj&z7€î’ä:½1Éâ]éÁ’© i¹¯ Ù·2=¯²qy´£?].Iþ[%7Åo…\Tåžò5ÁÝ:ê;‹qCÊ+À ÞÖ[±Ó÷çzT¯°íÊgÅ›3jS^è5qjdÜýJ¢hæ‰;@‰ë•䤖{Q_ÊPe¶9 ú#V„ñl™²[œDŠZº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ËHòŽŽ~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¤Vò=¯È(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 ؠÂ%.œEŠB„˜°á…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~…ݬ‘IÞÊ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&<šr"Ð’Xä\ãǰ=#ªL6Ñç¶*‡~™Ý2õfÉü.œQ܉OÞ}²­¨Û˜ÎnæO³õ³&VËN¨7´!Ä„i«R?ýYOÌ %¤R:Ínšf:ËlUà†;þ‡¤OlŠÅ´&"~¶Sœ5%ȉž9>ÌŽ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½æOÒú YÛXNJñQ5“f³Â1‚G W(ÕÉ7irJØìNÛšA+[íjtÓÖ(]Ùè#좸¬'®K9ð¾ÈŠþ5¹B%: ¸‚2_ñVö‚l•ðîƒ;23¿|F{­ÒjŽXÙ€íã-”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Í?ÎfiŽÞ è ©‘ú¨ ‘Ä@铺臶èWáŒÜµcŠR©cZŠaÅ(Zì¥jàÑ=ZšŸ©œÙ%Šš)³"š¦aš:—6‡YଞÎÁ˜6é쉩Ú8¶)é­Äif”KF)¢©‘_¢ZH£*jŽjÙ£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Ô1ŽP#ÈæÕž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†mòªe`W¼ŸömüŠJBž—*^ŰÝÝ•^¹¤Ûrò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-commons-dbcp-2.7.0/src/site/resources/images/uml/ConnectionFactory.gif000066400000000000000000000127361352030664000304150ustar00rootroot00000000000000GIF89ab±÷”)”1œ)œ1œ9÷ÿÆ÷ÿÎÿÿÿÿÆÿÿÎÿÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,b±þH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“$ @€¥Ë–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Ý—î_Kì2Jòò•!»—{ò_ã-0.Ç+7­É(çk„-¿lô[Øâg³zNiß’c9MœÓýÎŒWWëŽn´¦Ç4{-&PôÑd{ó^¾Òˆ0¸µi-–zj›ù´Èyì×qõèæþÍÕõkÙ€›D±SÑÑ÷Éuœ­Þ‘+6kÆ«„žKÐí®¹Hgãh£Ó€¾§¡¢»Šü^~ŠùVîÈl…¥ÛÍ£çžy¤co®ûŠIÓ£5 ɨ™¶7ËÞêÀO^|±?¶^¨Ž6¼ô“W.]î»gÏPçFê…ºÜÒ/dŽzO8¯Ò¯ú^²ŸW¸˜ÀûJ{‡oŠ­ýý ~a³>Ê~ôÀ“›²0D¬à=zÆû™|ùxç;œÂ‚=üYp Û_Pg¼#AGÍ:Öìôö#é1poJtJèÁù<VÒº  ¢?¾ü'Ywj€¶$hñ+6þçÚÙ´­î †qš¡’Á±Í5ŠL¹¬&Ú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¥¦î|YÌ…©FžÓ†<\dA«¨H…ŽS3:$@*1ÉÐË*ža˜] vI'fÔ,dá(fžu'‘6e¢…\¶æ*úñSŸ²˜:qc&½6žL$`PšÒj `gÎAÀˆ"DT@ŠRµÓ]Ò¨Ôê4GžzXO/¸Mï9H¨Å †¤‘zuGOÅÛVô´F5i…§SU‚`u:?´O%×##ë…IqÛ'qTÌí}Úˆî‚Ö´RŠEäé”PãI>Émv |žyj³%ä…Ioì’ÝD”(O½eL¤KçRXÃÎ)A»j ÎÔYBmÕK¬UþÒfÒÄ)? ëQ/<©h–ÏVmQŽ4­ö+²<%Ì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ëÃûcIò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›QŠw.GȈà÷*ž,ǵ,#D:$ðC>°³` cËØzŸØ<¥z+ÃbÆe®ØCb|täG3èݸ¹2ŽCƒœ±Ž»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·é›ÒEò¹ž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¹èEÞÔÀ<ÁÜCë‹xàŽ§y¹•ikŸÞrŠ’›¹UF” iæ[xéç‘+Üõ–øÊ0+ÌÂÓºÁIåO)œVÀaR¥{Zó¬å®#ÓæÛÃ,x¡{·¶ˆ+tkC9ffaµ8¥fPLŰqć™^h‘Ö( ‰§DKdèZ²õw–eÌ’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#GìÊÞ!)DoŠC0:{þXüw;œ¸ èÎE’åuŽ·ØÀLƒ1NÆ-DÜàúÆßñíO" â¸-S·êÁšË¦J‰ã¦lÀDȃ­¦j¤æ¥æ¶l;L$‡iM.»®Fy;Xj´{ä7Á¾\Þå;commons-dbcp-commons-dbcp-2.7.0/src/site/resources/images/uml/Delegating.gif000066400000000000000000001052011352030664000270170ustar00rootroot00000000000000GIF89a­÷ÿÿ”)”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¥`“‚(¦¨âŠ,¶(”ZWuÞÕ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…iÞ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¿;Þð’÷¼ÄEìVH2Ðòº½ï5¯|ãK_ø®·±Å¯~ Ú€Ò¶¨ Õ/pø«‘ÿ&1Àš5°€‹B`¼®w{ îi„lU¯4XiŽi†)ì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å·'sì\¾Jý–7¸u½ktÏ[ܾ&ø¯ÙýTwÿ›EwŠ5 òçœ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`Suì–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å Pìµ)Yœ)|—”øŒ¶q »HÀAèÇÚ9ƒ¥Ó‹¡¢Æ¡I³"lDŒr¦´w­”z¡4j÷ºz·õÊ"7 y Ó¹¾„ÇӓQ €æHñ8¾…ã4SÙ'-|ž/ÜÃÿó1ÔX‘‡Üž,S&ƒI…Dòùx™5"‹¾K\ìEþzœ´¹Ã7,ǿ؛ÉÈÀ¬H'Á\ʵB‘$&͌ĊòIì iþôÅ™Gi–‡F¼9Ëh9¹l˜ßRÌ›)ÅÔÇéŒËÙ1†÷1Ïüø?9x¬¦/¨ƒ\Í¢ˆÂ/ÄìËüøŠ\Êj‰½ìþNÚ„Õ·Hû&VŠz(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½]#¹TišAœÜ¨©ø‹ßlÜ(±\`‡e)ÅR ­-(ñÒ–ÞGÛ|ÍÈåݱÓÁºZ‹3¡«¬nJ/H™ÛGìØìûYÞÔᇕß_7H µ˜×HU±­x­pá=ÞÞ͉ó‡ì꣰û2Fª»v»À ÞØM#â5Á ÆØ/AyúßèñC¥+ ®D Æ›VÔóT“;®ájÚ¡¨õb­™*5¡Q1ÖŠáNÎÎáãDÔÏ@qß?¡æOÒ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¯ÖkìñJ=—Á•ØÎLÅL,Íj¥åg$ÔBt‘B.”õ\_B„¡õÁ§Bbß`ö0ÔõXïõtB?ï/Ù=R"“FÁQKž%` ?Et÷8±ó âqÔþN€qAwaòÑÕÚ§|ïT4`Ç/©ÜëEÎH‰ÿ`‹•FÏó%“÷’ˆá¬÷ EG¶äùP¢¯¹åèçQ¯ê!úðÄor“¿=ªú-g —i‹UI©¤ä± »OùØ= oXò”ʯûó~4ßn˜?_ËÄþ”üÿTò¥¿_¦ïV½DËTqG …AÞßýàÿýâfaº2þèþêŸþìŸÊ½ïMÎôþïýŠuüÄ“BIò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(Yìñ¾%,è ‡Òìµ²Ò$ŒÊ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™þsšg›‹ÖÙç£饕&:館õ¬œ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*¼Ê"sò*|Ú&¹z™Mª™vº*4úŽ! ½‹Ò?LâBE|-/¢»7ª"’D* þÛ£;¡NÌ£¨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*mžcû¢íÄ 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Ò«\ÖXža×Ñå´ UL¤!þ¡Ìù´?õYB¼E`ü^¸5ª•‚<´ž€»"Íþ"õž•Äø©SÅm¦HÍZ¸ÝÒó“ÖØŒÍÐʆ •†c cFã¹ÜÇ b„3¨®Ó®áÙU)ˆÒÛj + bt,Ð!T­ÇIÚè…cüŸ–¬9Šm]Ô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-á«nšV2# Ó½Æp,ØþMšI ‰k÷ÿyÓrlÆá²¤W¼œ%Ö£?Fš?F‚¢#>½Èm"µ+ø¾º÷«¨é”6H¥~îˆ!Y>.D\‡–¢‘$ÎUdNhжâTܽ¨ Œ4b¥så¸%žöAVÀ…y:¦¡V”-µÐptñtœ¡±iX‚4JY%œ‘N¹ UwúIa—iÞ~lqÇ”¡H5”èC Eôæ’qÎHå£sZy%„uR¥å¥J• 'Z ©ˆ’§Ð¢A5 ©q¶ë‚ÑZ+³¯-Û,X·úP^ êŠwg¢èbN¸w¬Îø(±ŽºZl¥Ðêø˜µPu«+hƉ׈ÇÕ ï·ûž+§ªÈ¾:éÀþõ¬ºŽu9žŠJd­½Ø.™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Í’ñ#µwò…$ iv‚ÖªÿË«Áq$t .¤þ li‘$-I)ѧM1¦Pnzöô±Y¶-P*_6Ô±ÓäjÉ—@’ÆñAî¼ë y˜ÏÊ­k‘ˆMì†É („žëî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ÈA2nÞ¬+.ð¾oª"ÏðέòrnòÒm»DÆK@aÁï¡.^ŒØéPŒ‘Û˜©q¼‰nžhÛÈßœ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ܵ:³pš16÷ï;×-ûîÏnÓ<Çslè2pbòÂ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ÇôÛ͵gylì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²»ÛµõvŠP[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ƒ¢¾]Ç}ñ;<}¿I̽˜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<† ËnDMì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*ÉøâÓõÜø¹6OžsŸ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‘YÌa:ó—¾Ü¥”ÙÌcB³šÙÄf/¯9jòò›ÏD¦4ÉÍpŽs𻼥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‹–žŠ×\âUAÒ{Pòª~BärÚÑŠ$»â /|ãÑëò·]¨íq Û$²gp?úßÑѱçõ§; ÛP UCù噃ßÂaøzxÁì qÜ6„`ûG#%NñËLl'ãuÄSqs^Œ¿ýOÅ€IÌ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ùÊYÞ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èLìú®¯4å‘1m c“»R3FH%ŠoåÚN”àòåx3“ÒNæv“8}3ÿ£ŠLbsêÎ#¼.ã „+ƒÊ6a³1¯ÓÅP†¥è-[ic”Nò„'‘ÄSñ(/<½3'¼è]Qúø°9·nfÞÆþ5©s/c„¢h“§$μòÏø3/.ÕÇc2‰-g‘ÚR@ϲ‘nÄ…ˆ¢ý*0)âelE*ë“#CyhIÚ0¢¬’<üSFèqô°ó¤¼/&®ßömšx‰™ @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Èoò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%šÅ•-æbnš9bè—|Âöç‰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 ­nwì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úzò·ÿ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Æ‘$KšDxñ¤J• ¦\i’àaÚ¸ …/f¨a‚>&è ƒ&Æ8¤‹- I“†F8¡G66Éd‘Rî8å‘T^ÉàG?²&$ŽQzY¡‘DbùaƒA:å“Næ(f›UŽiå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“BLoYŠR¸Ê[Ê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šÕŒ!Ê®`5VEÒ¦²'_ø¹*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ôL쿤µ­{K«V¢"$…Eäîv·Br¥å.XÄÔÈþNœâ‰ÌÉPfq”íÔ°(w̺[–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êˆz쥳•ˆõ…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‰{ÐDòè#Ô‡öè_'å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‘ØÃ`Æ!ÆÙÃþáÅaìÅÆ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{¼<ÁÜø*òœëñÇïOò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æLš5mÞÄ™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Áï½·Ñ~{ѧ¤Õ¸ð½§¹Õ4YÞ¡¼ÿüء䉾ÙäßvÞÞ¯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Ÿ ÛíbPMòÅ 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Á6SòÜ&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ìKõRÏÌ~çÄ¢ö§‚{$Ä™žÝ í³:6Äü(=S„äþCéLèûö¯ùvWËŒЦežÖþA¾òSŽLyÊ>™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+rArì!–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ÌGEÌ–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é"é¾NìÁö2Âl/.»î*4N&ÌV—·ÆëÏæ{hÈñlw)ê¶‹9Î.˜íÖ¦µÒ† Ûò0Øî°• mÓpºš8íÑPmºíPém×îÓømy€Íæ Ö®í™(nÞ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ûÁ¯öþÇ”÷£ÝOÒè³§Ù›Ê˽fÓ¥V×k ÅŠÏúiÄdõ4cÂ÷|ÉÚú›È]l ÚE^Âf±:ÜY¶BØ£žBbgyŽ$P[ØÒ—ÅÏÇý–}L…žá}ô_×)DòÔ¬JAŽZ1X—*Ô‡ú’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¨|õ.5Št0á†#N¬x1ãÆŽ# Y§R¿}/Æœ9ëÒ«c"üºð¡]У½¶mVôh¸eY¿åxp Y¯œogäœy·î¬%O.|8ñâÆ#O®¼&ðå,+o~йwDšmW…Ÿ¹?‹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—Tò˜£˜c’Y¦™gærB ˜RZ)ä—ò]IU•U6P”YÐV ʼnŸQÑé× –Éâ‹^Χ&šB©¤“RŠR°à—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Ó™Å\fŠMhbÓ˜Ê$3IfÍmS˜'9Ý5NpvóœÇܦ6ÙÍd@ã‰.}iÏ{âó8rÃc&ûéÏ4 (A jP®1Ÿ ](Cã#iU¬–±”¨¡*Ú5‹Rô¢Í(G¹Q@2`” )IK)ÎT¡Ôdþ"ÑÈÒ—®4¦*é¢iÒ›â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Ò\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ÉGnò’£üä*O9ËW>/ar³å2wùÌkNód„Ûß9Ï›¨KŽÏè=:Ñ‹nôz;commons-dbcp-commons-dbcp-2.7.0/src/site/resources/images/uml/PoolingConnection.gif000066400000000000000000001104651352030664000304130ustar00rootroot00000000000000GIF89a™÷÷ÿÿ{{{{„{{„„„{{„{„„„{„„„ŒŒŒ”)”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^ÆKŽLy2Þ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Ç ºвĢͨ¶0ŠŽP£ ýŸG 2Ò“”4¤1\çØX¨ÒœTLãi)JE¨Øt-8íJNoªÓžòô§; ªO… Ô¡µ¨H%ªR{º–ÊÔ"/åHTUòÔ™Îèˆôœ*F–šÔ£rõ«^ +T¼iÕ~ “tU…g˘ֲ:H«‰ò%*i˜Aº•cpéý"×oÞÕcvý_[!’WE1ò¯ú*,¢ÛÐ*±tyìó$ &Ê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]²Kò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ô‚lšfCƇ~ÿ§‚«§.S*Ø—‡èRŠò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è#‚Ÿ«úrÞò¡û‰Œ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š~GjiÌ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ÅÐ}#šð½gŠB0—(€O¦ZÞÃ’Þv'º)øÞóúN€Yk‡WÇV›œ>bãÉúÈí¹¨…;t#?ë |ó"xU~A‰é©&ê Mé yi¡*àc7ÇOjÇ Z*Ò·|¬±‚:G§ôþöMQÂ>÷Õ~œ§xŠYùª‹•¨{ˆ¬™À4¿œÏIœÄó¥ œî„±ßw_i lšÍ’ùï(*YX’†¨ºCZˆXû¦‹)žˆ)Ãé…ä©ûÕ¹]o_oùÊ+•ÆþŒ½²'{ùüqy¼ÇB—¨Yý{ÿ­ê‰jt»'þ(AkÖ!•ƒùöѯ÷²˜•ÖX;pÛè•ÙXÂÉ$ç¢÷³Â.ÂÊ’<É$$XÐàA„ .BÄC‡!JœH1¢Ä‹)NìÀÇCŠ9²$HªìpR¤Ê”;šT2¦Í)A¢üØ¡áK-kª\¹ÒáÈŸ“jܘ±"Óˆ ü ° ‡„XXÅ*p+U¾¬jµ`ƒ†>!î$J³hQœ;ߺdÛVnÌ™l…ÕéÒg]£rRŒ”mÇã=)w±Q¨ ÌN¦\ÙòeÌ™5oæ¬áÒ§þ¡Av:1Ê |]Âå9ôtј]³úÑmÂD#.¦3v‡Q›'nÑøRÉ•·~eþ‘ H;½Ž…:õæÎ­\^ùsp  C¶ ›nyÞ®ÁÇ^ “¼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øAÞ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(JŠYëþóe1«÷¸“-¥}‰|Q3“G© ±(Rj™.D/@ê•ë`1{Õ¸Œá kÍ'Ex†¿A:szê¤H°lÖ.t5@|Ö¤g=õ¦=ƒ³r´ZŸÌVÖÏhŠkŸÉ¬„.F6L  ÝH-ëéF®­•óã& 9Kþ!•’óEÿЄí3–ˆ{ˆzRzRQ†óx÷Òhò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*ÖÌ”eò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‘rUKšò—ŠàXpº!­_WšL¥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þ›TŠ3­² \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ì¬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Ü«×ìNzìž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ýË6eìº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'ÏÁ|ciÞ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\ßö©UÞݦɒØdªÞ4JÈR8KÂqŠZ¦º]ñ+®g¯3¬ˆ:ƒþ˜õ„8{ùnßwiyëÜ)¨ž¤¥úD»r‘Ų˜²ÊHˆxLJ¤Ú¿^vç±x¿®X¿wj¿÷|Ïx~ßx;£0ýÃy&ö‰h‘÷YªUl6­ÑÁje_tò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µzìŸ 럻FcGÁ:=@dmˆDˆX ÁE(4ˆ¡A…%&\8ñ!CŒ/jʱ#ȇ+†”h²‰”*W²léò%̘2gÒ|¹ &N•ròìéó'Р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‘uÒ•àjÜi¸Ñ…Í|xÑG[‰}˜”‚­ø"Œ1Ê8# 6X–t|]Fþx£i÷#„>j'š¤Q” GCZáEÒ&߉yE™‰æÙG#Q-Þ§R‹Xzù%˜aþdcw€àŽIÂ5QgÞíEžGBdœ ¢×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,Ó®žiÒ½×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 "ºÜiŠnÅÈ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çmŠZxºyŠ'¦g…™Á)‘rªç=²'wþäÙ§|B#}&‘{:\~þ§Ùì'|Ϩ Ra§®'b%~^'‚6èšMèåôŽ@Å'…r¢…þN&VœIA܆þšb‡V_"ÜyލŠÊH‰Ï®(Œ.’jÙ¦iÆètÎ(Å}—.-¦.b‹ZŽwFbrhmvWzè)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Í+½Öëõõ–ˆÀמeÒþ‰Þ†ä«FŒ@ Ú½¬Á,å„˨†™™£>æÃF[ĪuÝÂL¬Ãf,²bìÆj,Äzì¬Êæ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_éuŠx4®ü`ßv”mú…ÕG‰ªºŽWQ-¬rî-’mŽ•Ì4ØùMö4ŽXt†IÊÒÖÓ åfÙ­ë¡Ø•RœØ*†ç&F(šç‹•js îê™mn˜FÇP†á»t–ï1SšP‡³èÔ¥,Ÿ‚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è…%›WŠDsÜÝ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Л‹Ùô辎IcŽlÙseÒ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‘³EŽx< 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ÝUÞŽù­—ã‘ ˜`Ûj¢WR&E>7d”?ֵ͕ïÍ/Ôðêä’uÞ¹Ð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¾ùßã¿ú÷á­gIòÌ-ºšÿ±—¹EY‚â÷ÈîNÊÔþ¤D¿È}/ìLg>ã©QŽvò£år[?IZ0(1ôN ;àû8’ÃÍ…Üò‘¶Þ/…R§õLÛEGg¥œ®3¤Õä<ƒ*¤P–©v¬ÚWè(òYÊx{Ôpdz+ýp“h¯JHò’©Ó‰Ö“§¢3ã=ÿGQ¢–õyE%ëËFšT·–ò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Ÿ~©¡Aò•™Úo–\'.²1²7.,Fü¶¹aLÂ#K¶—^²½sgAû%?ú…Ì«ÊR@”þ m[ßmwé3¢ÏÂA).ƒž Tp éÝÑîh)†mW×LÑ6s­&èÔÝÞà4á£T‡g»Ø²úÜHW—Ö¯–u¬i=kòÑ´$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Ù:â÷^ð-QErì*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®Ó21PžpÝ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?+«˜šæõ¤(pMjŽE˜hÄ’m—z»lñì#ð’1ìxi2?ê>ãÍEù ½†ÂƒDe[âð숭1 C ‹òì½ÂÃ%÷ ñBˆ6³Ó[~’È"¯´Ð½<4RsŠ2H"½LÌbÃ~r,-qy3Lƒè²:‘}ž+m´.þ$µp°TjKíl/Oò&`Ñô èµî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Õ[kì¿Ô&_Ó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®Âå’Œô¦:SŽOð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ñš/ŽàÔ!²ÒIÞÜ–6ËØ‰CØ!v˜6Hx¡ú•ý´KôHÒvÐýÀ‘ƒ­cLuâ5µ ê¼Tÿ~„Ñþøz`êg *d›%:û“ܼMléåPK[-mHqX÷8B÷”$Gù?I0‹Òe/µÙBÐýªPT²D=+™{ŸIò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ðgìŽ-³)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„Ä tŠ1£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ê|%!·aŠl´÷ ¾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…þoì6(K£(¬‹Ï(ëT9AJ™Ñ\JQŠVÞˆ|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©ï YÞŠ‡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‹­CŽeo‰Áá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”Š)‘msrì·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韋êŠaŠjpgHM)†š¸Ÿ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ÌÆmìÆN\¸f<»šØqDHw\¤g¢Ç}œÇlH~È_âL¼ºtL®™ôÆ‹Ü ŒìÈ,mdìˆ\2q’L€ŒÇƒ¬É¯JP™ìÉ{ŒÉ ¼ÉƒÇç(Ƀ™™»2ƒÁ#®±l²‰gUò%}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Þä“ÜNìÝß͉„¤dsªßr­&ÕSm²ˆßsª«{½7Çõý&hü­ >†Ð9ЖRBÜÊÊCöW·4ómÊ…ENk ¸ô¸þµÝâ>â"îáNâtkâ÷Ëâï”NÞTâ/Nã+î¶"þá6^ã(Þ¶^Mµà˜ò½ ÉEŽ%í EiläA[Ü]ºA.ät%ÈŸ<墜ßU>mV®åXŽÉèsàPî!„õ“þÆ™üL>£lg¾™ùý6{Ä̵ *[ÏîâÊ¢1ÌSÄ´L«±¬—“1>Ã`¾$Ìž©%ÞÉPx!f<”&eA$uÞÄÔ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þEìèýï¾çí¦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ÔUÒ”ó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 ÛÑ^“¸Cž7=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ãOLžCé‚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=?ÕÞ_.ªñ: ¢ÑŠøTžJÞÝÀ¦^lÁUÔ`TNŒGi%6‹Q$…õ)q&´[ÅOÜã9dfˆœ–\²  Á Ý×fëM)•#â}*ZSŽbØ|ÚÌé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Ó6Šfœ=;¡ävIYÅ”^ã2–¹.>®ÔN*"?0tä™!8ëÂמñ›¥ZؤMõ¾‘hËmĬâ\•*ÖôâuqwžXtæf³­×­hÖ,¯rh.[Ó=ÛãN[BIù\Ý]G¤ö²²Ñç=Ki…®wl PUVžsyF<¢(\¤8ܱd^t´ k®ºÜ6ú0¤\ª~*3u5\Gåþlè¼XHô*tj-]#;Ý’æ! ‚Å>Î/yy²¾3 ]µMãÑ@oá,袛Šq$AXuVÞÛ;à®ÊQf&éñë þcP„‹µ²¢ÎGŠ£Ë° $šE´­gweñõKòµ]Î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ž,”Ê’{^þü«TŽQÍt ×d-?g\Fˆ¢¹þÎÖ Vì´ÇËCˆD^äŒã¬ËŠcº´ìÑâ‹ùËS¾=Mî¬Ba•[¹ †¡DpbŠz°/Ø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Ó­rŽt‹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À ÷PŽhÙç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¢Œlš2ë ó°º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Æ;¤äDCžgiÏÂ’#hCðéÐJÅ1 0–¦èpè„J\"WÒ›™ ?·òVu\×(o=Jˆ]»  Œ³:¶93G$ÍXÖt¯<¹.”agFØÄ7±y ¨þb·Ä¸IdŠz 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ºfŽLqù*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­Â2ž1ë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¯ÁYŽV‰n™WØÌró{÷¢jŽN9œ õ{›Ð¦}É[_kšÄ1þ4±¡Š­mm‹Ë¡Bh@Ó"ͱ±h°ÝõdTÙ2Ε’:tŽ1}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 )ãþ;[®Ùçæ-nšVð¯‹\èé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®>mŠB¿•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^…YÞV袢"^Ÿý±â1JKsMO@W®õœðE_i8G€56Ý2…ÅûÈ0š"7ž"‰‰á!ã8^‹b ºE:6ZšaÄ‚ù‡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–pAÞ†ý6òbƒ¥fpšÜ¢ômZKŠÜqrœ}›rR*ÊÞM^çEER çuÅŸ5“ÝPwúœw‚çwŠg‰Ý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Âç¾zìKtklEÞû±cl©¬yE}è˜U¬ªG™4êÈÓI ,ÙëU0V‡Y(©Îb“UêÇíJ|=ù,NŠ(E²‘íM6 Rô†>-Œ|«yb>Ò¾íu*ÜÑf¨h×zí×JEÓm4ŽmÙ"•>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-commons-dbcp-2.7.0/src/site/resources/images/uml/PoolingDataSource.gif000066400000000000000000001325041352030664000303440ustar00rootroot00000000000000GIF89aJÊ÷ÿÿ{{{{„{{„„„{{„{„„„{„„„”)”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`_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Ê!tòþ`€M”nÄþ$¬ÇýMzjZ¾ç®ìøçéµùûÕùó= ýÞ0tÿ8ž3 YýM³ùQoàþ·¶_@ða£áµÞö¢=FòcâÚÍͦ˜½Á,6(¿+Ñã=òüSÏìvo¨Ëæñc#ýž$ù ñhVŽY;¾ó”¤ÙëÆí±!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¼âtò1w’ò!‡ ¸z&è3Â{`ÂE{(Ú…:r!‡ lwà‰çg,؇xSˆ'3!¡'$àw|(GTŒGƒaÒ‰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—©—yŽx ˜óÈ€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,Mì½EüÃV\ÅX|ÄYW¤4<Ü¢[ÆZ<ÆWXÐs°:ܽJ¼ÁL\ÇR<Çnì9Ÿ–ÆÊqÇS‘j3ÑK¬þìÄt,ÇuÈ…cTz 7À•È…Á ÒT2¡Á†Œ“LÈ–LÇ ÄÈÉ¡Éüµ@TÆ1ÅÈ—\Ç£KœŒÇòók„À7hì@©Œ³Ì\WâÊ ¡g¡üÇŽD<Šö6µÜX üB"̪|ÌÅÃiÞ‹dÈÜ̇„T™³tÎ<ÍÃ5UÔ|Í’TUIv%ÆŒÍÞ¬EšÅÝüÍä<5ÎDkÄGå¼Î5D‰Á½ìϲüÎ`Œkò|Ï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.äì] Þá,çbŽy±!¨+‰£þ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õiLòìžÜë•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Ò=äVŠk¥äú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/àÛ"¤° PìaëZÓâæˆ€a¾#J'#;œâxÃEŠ1!þ‘ò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ËXvò +Ukw +Sœ"ò¨ÕÙêo{kÙínq°Þõov¥ÓÙÀÁ5Ž1®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Ї&¹yŠuåvÒÈÁ£]†'žp—½ìè¶²ŒÅ ¶ø—Iòâ²+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}÷½OšmY¾±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§ßØ0ŠJ- j±‹J1!cŸ‰-µÎÊÄ‹ÓvŽw ¥ÉCð#kj£® ±‰²Å œÍÀ0ò;JdSq#P½h=Xžå£”Ä*3) äÖú©¬IZ,ïâ­ôZ²¢ *¢zÅ8츳f Ù ýÒ÷$ \Y؆š©tLšJ,RÔªš«#»²ª0@â@œµÚõÒ²žÛ¡˜ÔªÚ–Å‚ºòËÄ4*üz+Ù"«Ùk¤¾UŠ€íšvôB·¥±‘%ÙAÁ X¬-ŸK± Û–/}…²¿½•¼Cj[m¶•[i]Üþºe }(±mŠq2Ú¦Í\³¢¯©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`ƒì½jžf†‹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…;ê>²HxIjžHãäæ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¸Ršuñõ˜Ñõ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ÍiÞü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Ì AŠxÂ%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é©cŽžnLÊ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“®IÒÃh¡*Ò’¼uEþdIÔærº×¾ÎÊÍ’T“¶Õ¸Yì}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ô°'lìÜÜ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åèØÙŒjžfâ°ÍÚÈÛøÝ$ªéXq|%fî™@zÄb2&Ñ= r¤^‘bJ-Ç¢å^SYÖ[3²¤Gf#¬ñàÉdLHBŠ>R¢È| —Õ&y&Úmaï ÆMŽgØÍ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Ý"²öÖ­…Á¦«Á€£gì Ê©aO´äF„õª©ÕÛ>X±ÝE©ù…ÅUžqF‡xÖ¤î¬ßUiȳæGWFVÓ-TtŽQ#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)ŸëöRìÚ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Š$±ðõÿ¾ˆÝ%PEÒ#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*Kò‹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ÇŠ` ¬™×fIò Ïß´¿T*IwJÇÔ5!;R™®ÉÚ„zÍEª_ÔÞ¡=´ÀjàfF|&N ï‡Øs„Ò V ù¡r VdçiIKã[’ÍøÈ˜Øž)o™í)þÇ:îÖ%Óq††·¤º-dŸÅwâ…3ß!RèkìÙÎ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¤½ÖhŠ6„²¸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ômGì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µðŠ8kžSЍ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–;™Ô%ONKž0lý':Ð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êuštÖ½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Æ}Lò(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,tò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‹§ÆüpšBì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¨lžMhä‰úðPl~®Ú¥oä ÞÆ°ä<6D&9ÆÄV-™0bþâ ðGeqëQuÌø°bijÅàoé,-Ô’°§–*3D ÏÈ$°.TP§8%,KO˜&8ôãæxOò¢QǯänFÀšÏ- û ÏZt-jðݰŠäîÞ¼.­Ò+®?ä°ôðËàÀƯI%cÑu2'{ƒ_ªˆãάÔL++ÚðSþÐÄ3 ¦ ¿°‹Qe|¬LT¦²8ŠpA ²>êÏÊÈ&- ñ'ÎqC¦q#ï"fúŽïªÝŒ$ü#€tðnþ.$чü8‘õï(&Ê]ÒñºPzâÓ “ â'!IØË+?ï+Ü1Œ¸DTÖâ,2£{æk¨L-2} ¯f£)i¦¤³–ŽÐÖ ,yB,•'7LL#eŽRjEs¸Ð5nû ³ -ñíþX 1Ò%gÓ, HíÈÌE ‡Íú¥è±' Ó9 ïÔ I¥Ü¾ µâI†Ì˜B¯Ô‚‘¿® ËJoó˜d<Ïd²Æ 'óÈä;¿8cbizbþ5›‚,ú†¦Å/¾Q4æîeô±.ÁéPS6Èc>ÑQ;‘øHò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ó>+Dò³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õXLLì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.ã­ÀÊ‚³ *Rò¨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 öŒÑA쪳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æLò‡,Ù2,¹´°ÏÁs¢&{ô² ÆN"6•ì‹òU|¢žÒg3чy ƒ´jùgþ]6@ö&l÷vý4Q%úÝx e$ÑíÃ<©¤;eÔv-é«5kò+Þ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’ìnŽc)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¥ä–«Sò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Þ‚0žr÷§Ø§$‰’v1€{X”æ…'™”)yKÁ:Ù/V![&ÕVhRzøØÆ'’Xî(\™LØ”gY…‘‡–»’kÉP‚Fé|Y#‘&W• ÷[VÁ'ظ‘>irß“'”‰G”n …Y‰L¹–ÓöA\(ø÷|yIò.”Æ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§ƒÕ«˜êjšhoø•ð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Ë•rŽdI©Ÿ¡²Äû6Dç8äÆS !³jP–aAšù[x%KX3Š:ÈDÏ‹£)ü šÆªèzá²r¼³|œŽº¬°}LÊSƒŠaXq¨D,.¥ŒÄû¸=ƒÌ«O†H뤬vü;s5™tò²°*•œ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¡ÐAÒ ¿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ÈNì›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’%MžD™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ýikUŠGo‡½ì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³µOMtòó·¹Ì›&Cµv¥<" §!›uò>+Û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<´Æïàü.ÿvòÚ4mäÁ=ÊPa R(oÊ6±³ ÇÒ ì%j[ìÅâfÝ›¥ö)ß HcÌcQ3ÕeÝ=?Ï?Gž¤À“g¾µØH§ñ5Ï]üñt«—^òJ5×rÌ!ïÞggiùæ5zþ÷›ÖòþãµtQLu9¿ù‹Tq—ÜžA¥²]dÔó?EeŠO€²çη@¨†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ÒoŽ3‡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 )4š1«›«Ã@)œˆ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²Aò¼;”Õ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Å)rEdò3š›š;NpZ0ìÐÁQª°£â`UTlŸÒV1(†ÑØõ+B%«©›¼™…õ•Á‹¨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˜Œ½ºPì½RÌ 5W“{C’þûØ»[hs:ïîÝô[oâÆDMæOC”æ~³d$mÈÆø<‹Æb1ËÔï-'ñ6¼ñXU€:G _`¬‹ ‡[RKÞWlPnÏå)*QN\ªX1¥+ÆãL$ߣ>\¤”8·׿ò7O¦hæÉÈIìµ&Å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ÎÁélŠvØ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[udšh=eSw;9ÔÐnUÄÑUOÅ`Vßm¨þ”MX”T» %Pxý¡Vn]yÖœd6˜s¡ap€ÅÕô"E3´Øj\·“dé†! ÆH#$z•¢“OB‰–zìá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«dD27Aò¾;¯¼Ä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©:IÌ´Üs›7ZwL7°z§ÅV  Pã±Å¡º£Euº²\J™¶Vù,çGDÿIaª8¿\êeâøÐU}’ÖçA®õi§Ý|§ÅîÛKÝXf‹n]¯ÀTþ¿ëP“åË6Ž3Þ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;çÙæ<'²sŠB<ç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öeÞÁ¯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¶ÉÆ¡’ˆEì$ã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Ü þÉnEŠVHKuXA<"ß ÊþšÜ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~›oÞ³ èĨà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(}šDvMò¦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&’yò¥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ðAÞ ^Ê(ž<]Ô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ÇyìÑÇ ‰ö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ë­nì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¢ÈoòK‹… Öô(6©™m~“¤%5éG䈢Pq’…”˜¾õÒ¶ó0¿˜Îªh-¿l+J6û–yVò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'aìË~\Æ~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•(VÞ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®Õ«™\¥Ú€0vṮlåE´Æ´L{í÷~áxûÈQ%w Í`°ƒW±FŽX1çä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¥PŠLðq‚[fÝp¯7÷8à|ÑI›%ããÐØ«œL/4 ìË’3a“6ËÔ÷¹Ôq}¶Û8«ZNuÒ|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ãaÞ2ñ†Ø†Nw…ÚÇÐC¦ÿE×%æ…þÞœ»‰«¨x:qªr%³R ay:sÅ­†þâ^£‡>ëõÌ£•˘¾|¿åÙ]5,o…8Ô8*XmãÏòåµþíãE°›ÈežxîãË“µºä—:Õ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“TYÒ“~´ŽR†d•Z¹‘e¢òø#šÎ¥@’pÆ)çœþtÖYØ’Y2ô¥•$r™¥w…Y~gþIU®ÇšŸ.æ…h¡m®)išbÔ€˜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ËAÌ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þýøç°{;é_ß; I̵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´îmòÃâ×Å:Úñ~rÚó^g‘ÍH.vnUç4w‘4*ÐsU<äåø-Þñ‘Œ›û*Â1Ô4ç4ëËšŽ,iÅÑô‹­˜Hšò”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âßIžt@„ÄT»—XµAQ$¡}1ã>õ™O–F £0)‘4úÌu¬†É;˜ó2x2:©£¨z§K'úÌQ2Dš2Mª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Ñü/òºôÏRŽYã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`Ì/¿ì/]€…Dò¿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ç*׺¢´¡ÜhGžQæð¯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ˆéKaÒ–x·þ­pŠq»Ãt#Üè4^Ü iØøÆÒ¨±ŽsÌãû¸Ç@Öq7†\cÙÆË¨­ [ó hpãÉÑ€F4¦|ã[9ÈX¾²–³Ìå-{¹Ë9~q”ŸÌbÄÔ¦ý(Pþzj˜ï`xÆðpò‘¿Lg0×ùÎvÎ3žuÌ 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Ï»Þé!÷¸Ã}ä°F3ŠŽt,Žqrz ®Ñö¸‹#îÖлä'OùÊ[þò˜Ç{5Èqk!¯Ë9ΦÇýp × ‡ã3ÏúÖ»þõ°|9®AƒRŽmiM9Ò 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¡âHŽ5Y”Ù’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[„šÍaHrò.@”Åþ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É­<ÍçœÎè·¼‰xŽ5ü Þ‹Þ€Žºð…õ\Ï„)󜌿@˜ €ûü Á(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 á nÞÃÑ[­Ü³lÔ|H A͆QZÞ ê…_}Üè õ@óü…ôÿw ø ƒ ß8Œ50 5àÅÀ0žc(³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½ %݃yì÷ÎÏKÍå<€Áî¶ÜÄܾ›"ŽÃ°ŒÈºêèN˜_Ó­=Ò×ýÝl®þ >ÖkΠXÝŒHÙ~Üò¸î3Ýá"ŽÖ+ÝÔ~ìY>á~îÚÎȤþÓÂ)àïó†k ×=ØQ=1ÜÑe^òŒ=Õ)=æÛ óUÑH?ç}ìYíîÍ úœØ8˜ÿ7çÅnÏ[}èFÅxÞÎÕà€·í *ÏÙMçÿWÞð…„YÞ€¨½â;ˇò€ _ü ¼ð õ " ˆŒC’â´ÃØâ· ÓO/Ö¥… z=ÏM}ö©` ~íØ{v` ¨ïú® ˜ÕÂÒ}`xðæMì'_ÙMÑ'¿½1€ýýßnî t/Ñ îœˆÈJù‚¸ {þÐxPÑGýÔ¾PÏ @¥€ú#ÝM˜¥Ð‰0›@©Òª@ ` ð®ïÿ÷xЋЌ†nÓxÿÚö?õ­®üò0 ög'ÿ ô7ð_AðþÁãvDœ<ˆò~E¤8Q¢¯ˆ»tÑ‹Ho¢.yAḆTžB{Jq™ËãDPˆtéúµJâMš˜ä°±³i&½™wɳ%/ž<¿@–š’£·Imìà‘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!PžR¸Bj“B(É;ÔÀ£²\ò0. èq)nó(4yPYPºoX I•6èhC·BòÅ)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ÑÅÖ.ô¤ULòÆŽ\¹PVPÌK.þ'z÷ð’× xð]Q‡d”ì#¤¬-Ä'K¹Ež]Æ£TYVy,aDêU@Â$P€ dM›ÖJЖÈÅ“] ­‘º>—žU6Q™a7Ñä4z¹8¯éqåÜoJ!$d„ ¡ä’<@¥Ha«*$Å_Öå"£VutŹ+¯„òÔ^Ö[õè÷iì±Éþ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 Š<ˆ0Czš8X`Å|…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 oÌÃPŠE`Ko @,°r!¬¬7«“ï½²~Ü·šÝŽ®+AjÈ•@E‘E ¨p8P‘QܦG+î@Ä¡ ÎUqÅÅ¢X$p•‰FdB´‰pE%áâ«hpœõ³É°²]&BÑ@øñÑ–ç}0øº»¾V¡- R§ñK=±@ðA¡Àg#Þ ¸HXžb%Š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æ£îêÀæê«&‡yì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•6ŠV„Ÿþ¿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¦œiŽhÐ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½æ aÞ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/‘H4ž4á;—÷=$– ÁþîÙ½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^ æ çá ž.aÞmWöÐàJ¸Þ"Ž?ŒÄCy \ˆÄÃ.·¨Yþ܆ˆBÌTˆØ[Ê}¡¶TÝ.]WˆA>胓`“ãq;ìÃ5ˆÁ0ˆµ|aCˆÈL•!!²àÏbŠ¥!ÅÉ,ìÂ,‰Î’$¢½U"íÈÛ bz—,8Ž7ChÃ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=Dò 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< 1EŽkMÀ å¸@|Ž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;¨>ìçCìÇ>ìß>8ƒ(^CëŸþêû>ëû~:äC9¤~;Dƒ*ƒ,Ó}Ä:ü4pÃð??àÃïӾ췃õƒnì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«@ñÚIŽYM¶Ýª®G¬nm¶›£¶hD±ýç0?¥G 6|qâ£FÿKØ®H3qò(ÿ¢|Yže̺è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ã–’¨@6ŽXââc¢—1;îËzà#ßxøh½ö}/<ãß=£>ÊLÆ|ãû#øÙ=ÞҒ˜ ¥*UG¶±uC=ð¤î0ÈJ[®qm ôÇ ,)F²EÑoKê²u8ÂG!ÛPèË^¶’˜¹àAt EZBóš¨Ìæq—º1Žql ˜ÈÔÀmžÓ™èÄ& ‰Âr1ñ\ç<µÉ£Á4¨œ½ b éùÌzöSÿ\Pç<7PÚ©`š­äâ?êO‡”˜VJþÜN‹¶­¢Îƒžd"ÙQHÂÏ‘Ü _¹HÍ r¿‰oVªRF¾Ï‘ßëèóxÈò\D€8|¨< QuŠmoÒØ)@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¥¿*–1ŠtÌ,vn íƒgÜcÿלâòúúa…þÉI®í’ê âÆ1ÑÄ ‰žt;¿é-Ë-%diY™,™aÀùÆ÷nsÒ.ôÌUŽ.$¿áŒ"\Dg Âñç”\ç ®¯BåšùÌáòB5ÈCtŸþ},«¹Eòr MhGÓ–ÄkÒ’ƒÒ@uÖJ—ð×v O'X¢AY“kãZJŽšl7Ê´¥¿µØÎ²Ó¯ ¡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×'Ê „:ðëüÜçyÒ{žðˆÛ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ÿ–SŠòê­þÜÛžûÏÏþþ”où¹¾-3޹.ŽlÎðh¯îž…o…îÐõðYŽ"^`/²Èö®¯ú.Ð30û†¯Âª­â,± pùˆ7°/ðZ/p¤¢A¾F5g°MP‘m—šdqF)ûÏGòlDâ,èV~my˜ œŠhÁKg Çžäôy¨pîoPLnmò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º$‹ˆ#OÒ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;pì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éZì´`—­†°•¢/¸É¾HkvzÒ È oÚaÃZöbCöPʦcodL†Pas5K83? ¶aÕ°S·ä ¢¡dõe…B½e‰nöuì©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•aUòn«d” ?5ôq§´sÙøœBscw1$u—R_ÖýÁ0÷!l·Uë=¢.«$'…—@b±~7ÇRVyQ_5§Sç­{¯W{³—{·÷zah»W|½w|Ë—|«WJ ìtOÒ¢´þù‚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 —wPgsŠnÙßá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—­µ¥ÂÔúºZšcº®㡟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|À{ÜuÒ—äËÅ­)Æ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Ï‘_37šfhÈ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ÕŽNÌùÔÛ†"Ž•?ؽ¤–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î‰çmòù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ÊqŽt¬£ïˆÇí‘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È, È §¡®¥2MšXa ^žü‰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(‹©(_xŠy(¸ˆŠ\èŠ`¨…~øŠ¿8Šc¸†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›RŽ1(k°o:s|!IIÓ /p!(¹lè,cÁ[GNì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"áñ†žYÞ7/…/HšY3'Ø! ê(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„);Eìè­‹ò²ÏÃ~5gã4²B{³!q£;ð Gû´öâ!ÀÙ'T[µ¡ã ñO‹43Ø=[«vÀÒm:²ŽZÑi<ëM+£#¾&²4c¶¹’D®yw;OeFŽwv|»*~ê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:Pì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ŒÏyìÆ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ß¡ßûmìzQ«Ä% a‰>K wìÿ{ƒ ‡>×°`K¨T8”Œ\v?$³WÙj#?oŽ@Ÿ’B¯yêÞ vCôK¯ôM߃D/T;viÒ‡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ƒçÏß:ý„ZDšTéR¦M>…UêB‚ÿÚÔÑMäT®]½~ö_Õ±áIc²UìZ¶lá1ÑJµí\ºS *|÷bMxN¤iþ½:¶èѺJÙY<ü/ñá}±!\¬Xò;‡K~\Y²dË—?¶¼Yôå‚¡KEÇpñçÂð²YXölÚ_ýµë¦"?‚wkÿ\8؃[áíö¢Ê(Uvî<¨OAÒí_‡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ónÌ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åkŠPÚ¡  ¥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ý’kòÃçë#äçVñA«+Ò}°wÅrÙ7l|“ÛÖ)zòM-© d¹i†ŒaàÍtÒ€[4ðö¿ÿÛ ‹ ¨#0üÀÑÀýK@É 6Áû½VC@ò‹ŠB'Ú£@ K šx êqž $‰»¾ÐÁÉ ‰Üp8ŒK·Ú{3ã7¶C>}³¶óŒì?Îè $ªgØÆCþ«ƒ8Åh´ BlH³LŠw#°LÀÐ8ŒÌ¸Œ%|BÎX@ɸ(Ø8Œv ƒ¸ŠÞ»> 6–(Áû½¸`oC™8í[‰1L àÝ(;zÚ3C6ZÓ t²¼øË<áXB)\ˆô?Ö`:&< Ó¨A¼Aì?¨+Eü¿w‹B¢šÄ0x8°«€Û¨³4¬ªnP=,ŽÔóÄsRŸvð*®Rì: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€Ä•<8švƒ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­vIÌÈ 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¨#}@ÃÇÎë*‰šsìÔ‹uh :Š |Gí;‚€¡â޳S<ù+êQˆRöÍï€U µÈ:ÞåÅüP($K]NS ÎÍæj¬æåcÕ^ÝUo •ÄðŒX}a­î]U>Q ™4JdLäwl qîîEî0Wìæî£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Ù†à:àAÒ)féê "6ß VrHó!2!ã}0 xxÜ·Q'²È;`û«²pžTguTwõ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ðìxŠGƒ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±£Ž<ö¤Aò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­Ò·AŽ8´Ú†åŽ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>TŽò)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ü±Ž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ý—솔fžt¤`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¹Ù³àÛë&ZŠs‚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àNÞ” Õ¤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»ãsŽf/¹˜ì\£%ÏÉ¥³€BÜ›_žnÚepþ¥mÖ\Mf|ÞçMÝÛÒÝ%Oò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">)eŠD AˆD•B<<„réw.çI‰Ôˆö[‰Ri’W\bÉË­™^ÎÙ¦#FÑ~æåB]â-]mb†B]7ÎéÑù ѕ߽Õ&àf°Ü±E‘9È4RDù…i…8šRÍ\Vjer˜š_pé´9…—†Ü¦¾P¬)Dcˆ§3*’ÚñЦÈGþƒÈjªéˆ4Ûmþé%ú%’<fQêeq §B`âi°"ëÒÑi^êfM8D?lü†–Ú¨©FŽ4¼€|í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š–YÌʬÐÜš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ñ_æEìéÕŸÝ9Ô^5%1¸±î¦Úíâxæ#°ÎXìBXh•ÞFñ6c˜jŸÑŒjW­"5“VJ(.•jõR$"ò®„ôàOÒ§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Ýþ%áÒ­YÒ%à$ {³¶^ÖŸåj¡ž«"M.z÷À6pCÄ:€a×Ò-a [­Ã 2–«ˆ†9O&;X\rìîþ¦‚RBŽ:¤àh¶7èϯuè“™È ºšˆ_ï*CÝ a(ª¢×J¡j2 «m û«ÀúZ7"Ú’mLûÄÿ »ø^¬æf­Ÿ÷pšA͘e¨%†Û`öÍ®ÉÂÖv‹:…@•†lšº;£ƒ¬ƒS(…¥ÅywžÕvN…‚©(¢2F·Ä"87‰{[+ZáæúßJ¬ʲ&`ù™£°»âN"*Žp³ûä¿Rû$2ÛæIlÂCla78@ph/š}¯Ìfi¾üºWNÖYæ»WéÉDf'«û¢ƒØÝ6‹rìõ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#ºï^Õ){iÒ­R¡âd*µ*ÒÙZŸîTJó*íÛ²£þ|6<(6x(ý•†Ë™zu±i'_,IÙzwïßþã¦ö×ÎG7n+÷q¿þnÞáÙÇ÷£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& S쉹­†º)!¦¨ú€â,ÄÆÅ nŠ*ª=DÒä*§à†r‘ 4O4.Í™ª< Ì-!)-HS‰À#ÍTÓ‡LzžlJJoSM›Õ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ä:Hšožª«=Ë$Ñ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ûì‡AÌÂÆ`9nŠÊˆgþS8ÎVKª4άp&ÈäL¶Ë}óè:üYc¯qÅÚqBÚr$P±&ASþs¦Èt’Ÿ:UIòæ’&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Û¬«ù ˜rNòQÁ3Nv­Eüâ™wá\î Ô;¡a¸wS>Ç£¦‘¡õ%ïåu1®y ãÄ{íeÄÝŠÀù„ðœMÞyŸ< %¦-Ì—Pà3^ñã{uš´CìÈþˆ³ŽUvÜéi²HÅ÷nÄ÷ÝF†Õî×úU­6Y"¼ï&»8ýñàæ •òóªÊÓô¤®ÌM Gþ9Å yv*Yò÷}˜¡[ !•é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Ìϰ*Á¬Œ¦âª *» —´‹£~¥à °(…sšP_ÎÅ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°ãKž8WõØ~ yy y¹‘9’/™’3Y'ù‘;Y»äàT?›Ë““!9€?Y•OY“S“± W™“ •3Ù”+™•s•'™–Ÿ£ #4 ×p¥¡ tWkq·Ö|KÛô6óãVÂ>ä)7'â*¬>«±|£$ùI• J˜H£ÝÀKŠXQ» 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ÓýݱyÒ n= *ý Z`Ø¥‘>~ÝńԼ¶ÈöÁÞ#gi—6៶fži^áÁµ>È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ýúì¶,!Áuì~*Ô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˜’=3Aì˜Æo¡‹ÂØ"{Êø¡5ÒhŽ;êø?úäB ^ŽGö˜dKÙ$)n×±ý&PŠ Âƒž•[¥yÆyy¤˜’I ™¢&˜\~Ù%›f*„ÍiþÀ#œuò1ù¢‘{>égŸ€ÆÈ§ èŒÁÁ“¢?Ù8öÏ3òõ3“±f饘^úIùÔÐi³e*ꨤÂÄ4+Í ¨êånjÒ¬²ÖJë­¶æŠë®ºöÊ믾 ì°ÂK쮟Æú•Qæy¬±Ð>+m´ÔNkmµ²õC;ÿù$Ÿiàš„íµäŽkn¹èž«nºì‚ ±·î¼íÖKï¹yžÆÎ%¹ê½ö ðÀ·”"<ò­Ã§I£C¥¤F,1¦ïVYQ¨g¬±eþD›lZ©i—lòÉ(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ýiÞÁ'¿Zï +:Ür+˶óÔ· +±ñV_õmË~9÷“\<Šë~g^|~k}¬õDßÇ:ýúÕsþuåô.ºúÀçïÿήÑO¶¡œŽý¯i®‘þÏ»ŒwÀ³Ùjµ1_)“>Òál‚*^+ˆ¹Š`PyÌ{ßݽÌíg#La©žö*²øãy‡ uæ=ßÍ]I\$˜Â"í†Êš\ó,Ç@qqwöâ™¶? Þn‰PÌLiLÃOÙÇB‰âɧ’øi1fÔKÔ÷Å«ÑvOœ!oV¼‘!¯ŒŒó!þਲ਼ž0t¤#nHæ“*Ê˃y<Üø¼H”‰o/åƒcç–ÆùùOˆ™MÇ'?Ìl¨!YÌ"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[¹IOÒÒ—¦4èBO|z¢Á ÚNò¸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ˆLahŠa°^À…^ €W` ‡‰á.Hm(E1Q•3GÝÈ8½†5rÇWü<ç8l-ôzÜ@‚åÚP:ËÔŽ 4mCÌ ÝðþÑ Ý )9y ™ ¹ÙyË‘ùY‘éé9‘‰y‘ ¹‘xqÿø3# Ë ƒ) V \0]°U aÒç)ã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µNŠBBª{†&â2³!N[7cd˲S9é),Òvàâ7ûCiHò ±˜š¶õs*%¹‹;ð$] eúwʲP0÷‚3 %¥šLV´ ±¸Öº=³2Qeú#’kDsF†«( Geèêþª‚€Tµ[›ºZ»º¨ËºYÛº­Ë’Óû¹X€YE¹3¥ ª¶Dmäãú£3§4öhvò*.¼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š<½>QzžLÑÏ*Š¡µg²o<>J㸆93Sƒ¦IŸ»|4ÓÊ:ð`‚í©œðƒŸzÌLkjDxA°×š§+× °ˆž ìp½)Av!¿Š"–³R–)Þ|RE¸caEŠB¾ü¡*á ¸§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¡uÒÃ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—Ažus¬ {²@±uÛy¿±Ž7Èbv+ë`þ$!ßnkïH2j¹ë¦CçPª¹4):È^p›®–~ð6ŽÈt’ÉÐp’'°>Ú$÷ÎòÑ„-¤èíþ2ÑYgüE.¤*ý‚߇¥:É(oîg}©%0Ä˰2^êɧ·š,ÑÒHºvò³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\Oò ÁœÎ‰à!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ž„÷_»žë²+ß×uò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¥9AŠÌ^Sá٤׼=¥„ŒÆögÓàÉ[‘¡žÎÖpeÙjé…š¬ÜgØŸgCëèê¸ÖhÊ‚¸é¼{ÉæÔ»ÕæL&¹íž.o½Gö·o( 3¾Ÿ,`Joì ªŸÔ Æ7ñ¿Èí>\r G¼—âò ÇÜÏ9:ÜóÐßÛ*µÄKGnÕ¡¾ü_Ò[¿éuÙ-²‰öÚ'ç2õÏëÎÝ"vÓ ;commons-dbcp-commons-dbcp-2.7.0/src/site/resources/images/uml/getConnection.gif000066400000000000000000002406221352030664000275620ustar00rootroot00000000000000GIF89a¸¤÷- 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ÇòäHŠcœ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ÝøMìáŽý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Ë(·û•(iŠRº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Õº‡¬·؆)Õž mži¶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È’ •…#àûLOÞÃ5ÆŽ…mùÇÆAÖÏ.<#uh½p‰D]û°ÇJ°Ç”ã)Q‘|£!+ˆHb%šÌÝQ¤R¿ /H 6t·¡4šq‡¡¤à ;ùº*f’–w$Œ~ö‘˜u16ù!¹€ ÅjfÄüJ1ëØ’cj&?)ÍİC˜™C"%Š2iÌã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/\íð‡:Ô‘¦,¸Á ~°ˆAìÁ{ØÄ=±Š|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ÚÏ»ì‹:rŽwd¨„þ É­ô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®Ñyì°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ÜpŠfGpGP ˜‹º¸‹¼Ø‹¾ø‹˜XUSPŒG`e€fÀ~)q.ò;QKph KŒØ˜Ú¸Üg0p˜x€»Óa"EJwÄßpŠg 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˜‹YšÌÀ 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ò°˜¯vFEìà«÷º±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͘ÍpžJÆ?—]}Ñö]ØËß?»ß-áõ}ßÁß+âŒý¬Žýá 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€§&ꊞ9xNì¡Åð ™þ÷‚ètߦ~Ÿénoùýõ¿ù`õž¿÷–o÷ù¡ß÷ßz¥¸9ÛPóÔÊ'ag§Rögoìœ?Ä{Ö”ßö¨ïû“Oõr¯ù¢¿ñwú€¿û|è¿þ螟üÖlüªŸúÎ?Ä¥‰àu ­Ç0Mg–7ÏS0 îiìÂ_ýp_ü ¿öé_ùëßûQ¿üÀõ¼þqïþËÿþýþüöÿ¾^ ÏàÁ{ö ®_áˆMyçÏá¾ûö½ûçï·ãâ庅k`/x¿>)² É“!GŠ„R¥I–%²“`É›$[ê ™ò×L•;Uº¤¦JŸ=ƒÖä‰ÓhPxʪxc'ñß»oÞ¦<ó˜Ë(П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+­Nì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…ª¨Š<ùôžZŠšB˜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ºëà94fŽzÙ‰#" ¹°_¸í’[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”’»'?æoÌ#¨ÿŠèÃ| q…oÙÈצ:Å«|ÌŠèÀbþzœ¡“ èl_‡gJ0ö$§ýh&«YÝù¥1ƒ<^_¸¹¢4/s…ßYÑÛãÍiò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 # WÌ"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ÌGxžL ú‹OLàOú´M@€‡APÓ\=Lp„g Ï\ð„]”S:x#Š£=T PX„ÀkÑIì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¼PŽe¶Ë$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øƒž9ŽxЖ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<ønòÌ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+yrò=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°¬¥Û ¹QnÞ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å‡80Žy˜ë”ñ(€Sè€Y«¯ǯÒqôêv ˆþ|Õ€yäÊÓ¡]`ôÂZ<£ š•zÁ±»z˜×\â ÀDPPùkV®È®jE§I)*a]‰Q êd9ϱ‚tÆ•àB‚aC‰ ê×賊‘xÅ ádCH”â>}8ÌÁ#ž#ïuÆ]æl<ãYÓÉÆ[mì¹n§nGÉ(äþ08¼Òqh"3ˆM3ˆEh‹òô!‘ÃÞðŒQ‚iµˆƒ÷¹—’bCÌÃ1YdëxÐÄmbˆU¼árx…LɵÁrÐf‰ù:ŒBå¦7Þwˆ§Ðãé‡,ä.‡ÅŸÄ‹¿ÔdRr”Ü$'ÔŒ35‡Òªlëô·+<Ž/ éS†X})r/ÑÛ»Mài‚c³Õ!/}€|F‘ ³Á–XDÍ=êõ÷Aç3›¬‚iBWÁ ÀœIhU¥äÂ^DÅàÛ”Ì+ +˜Ûø•‚ ¤‹)¨Å×¥”×0 vJqGrhOþ8Ç„ Ø)V3ñFdB8ØÂwôœØ´"pÞ+¬`‹øÕ(¸HƒÀ‡xÛ,`^ì‘É-õY$(B 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¾©ƒŽ(¥&íoÞNºpg8\ç–v‡¤ÂJ0`21Ÿ›Eô©5•PqŽívȃ,äì–JmvFi¶>Kj “‚èñtjo:þh¥‚©<˜)„’‹oJª{ލÝâfÔZì^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ò°Hò»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ävŠ6øìº¨çˆú¯×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ÈNMì¶Õ’Ø>•­cKh¶µ-èl8jWóçY÷4L¦\‹>±´Lr» Ç’Ê£Ê0ÿ"«³k0G§²2o±1úÊôjqûCò kr”²°1&Sòô®3(P àÁ  XÄJ4HÐ`yð8ÂûåþÞ3Ž¿H Gì»}ÿÞíóÇÒ•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áØKìÊú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ÇWòGG•àl×ú.ê—´x§õNí-ÃRùh-[¼zÌØ¦¬*‘J¶RA쾃¥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£GžV`Þ©(íØ| Â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‚QUìóŸÄc$F1 ¸Ñ7½ ¨/qÉòø˜ pEKkÃÍSà ²/LòVøØÃù4i€äƒŸ#8™­T’[acžQ©\œ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ˆ”‹€$ð zì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_| {*?üÔ"}Ú»Pì.§ÂšœGiÁAêùÖ2¸ZLl-æ”Ñz,7†­ðè…ײó¼½tGC*Ò/È“«ÝÁL¤l«%5?»ÊÕ'SHnã3ùµ¯rÕ«X%E×Áê•5oéÔFQiŠùs„Þ!! YH€ë]NGª•’xEwM¬+¨ò*ZPt@MÌ«OÌ—Àþ¯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¿ð”`uÒ^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ídŠcÞ¡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–×›W9šuù Ù™¢%º)ØX¡q9”AŽ%³%òôÖá®A Æ9òž¹Í™›Ýv.Z£µù&ãÙÂgPþù¢'Z ·Ù¢þ¯Ùɰ"Œ!ã)´øôADYH¤€Smí¦:‡½\Á9žC 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ìˆ €Áš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òÙÈvÇÂW 0eÍŒ«ÑÔ_?~ýú•üwŽÝ¶Íj쌛³nƒÂà2 ›þp AÉÁsç‰<¸Lfä‚á#JvÞÊ<Ã/»öì¿¶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ÓiÌÈ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çYÒœž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¬4šMf2“ãºä"·%êàÈ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Ç"ânì]5²…ww>g#òæÁYÃÅ?Þ!?î¡îaw!4ލððëîŒÈˆòƒ–8?˜‰ØZñ1YbˆqŽr‡‘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šÕçìàƒå˜ž#qždÓX“º¹~qzh~:¡ä©œÊ"ü"‰š©ý9ªT1Œé§Žj›Úª¶Zµ¢›»Úª½g©£ ž½}«†« ù‰‚Âêª1U¬°6¾©H:›³¬™Ú¬šz«0ø~'Ñ j­Ùú­(6Šz€Ð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ˆbšw+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ÈIÌ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º;æyÞæ—né™^é•NÔµ½~üÁ] Õx>ê¥mê°Mê©~eíDÕP9TÑèN<±À}苎è·në¹þÕ-Zåƒ!媾çoÞçÁNìeÞç|}Ží‘‚š¶èzݸ^ëÑ®èÒNëÓÎÕ8ÌÛ.BÁ‰^ìznìÂî.þÕòxPNÞÉáp"êžîëîîéïí~"ó¾îìï÷Žïù®ïñ~"Ê`ïÿ¾ï/ðßî_ïÏPïÏ U°þÛàÈáÉÆàïïnïOðï ðóžîÇðÿÎñ!¯ï!Oïê~ðìÎñüNòëÎ Æ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Š ¾sò-¡?†ÿ:þKèÑâH’%Kd±‘áGYš„SæLšßl¢²æNž=}þ¸ò"ȃ7EšTiЖ;&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š•>[ iÞ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#*QŠJjÍì)º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ŠôjŠlD[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® ¶;÷ãÖý·Ã]Ö¼»„ÐÀ¥»GìÎþ]ö®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 ¿LKeòˆ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Ã:ÜjwÌ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ƒ-@6A6ueòÆ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%ÀcKòžiå—€¨ c¬îôÎ9$ˆ)>¶âqµIÌÍ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&~gŽe÷·-¨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РEoÞLÚjÕµ½Ñ~í÷7ÔœeÃöîϸ#7ŽZ›Ž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ã唯DaÌêÀ÷™€}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—تvÞú+w妬pQѲdAÙr¤m\aOLVC(%²¹¯¢5c(AÉ iô)<H×1EAzË[%Ë"þ)'$¤¿)¤]\eHgBA«¥Ä·ŠåHÂ’ƒQ³›Å\ŸúPDŽJX ½ï@ã; €;’¸¾¸ˆU‹&p¹<¬ɘÅt‰ùŽ™•êRœ¦Ò[¹éÖ¶¦2|›z_‰t#aqY™â9êÙŘTŽÉ'=I’ÀÎ*@UË¢SS^¹¯}eóëc„¨ÁM6Œ•UБȖ¼ÍΤZ{ÁãdÚÃŒ¨l¾z“ßAk,dŠ U'±,ÈYÞG• =m'É®ozƒ\l&gMóÜ,‰:qéг5½çV§;Oóz26y>¸Óœy–ø¨5IWs6ò܈þ¦«~E̹+ëäáÎÖÞ06%ý@Ì|“·´¥Eò.@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ö^ö®÷͇“ï\éŒ$#ß×VÞúrÕ?ʵŒÇì10DrÇ&ì>ذQäg¢  ñ\ƒ ß 0‘ ÈP~c í¬ôZ.þ›N×e!x)1Šv{Ú#AMqšuxTâ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‹èOì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–#9šc:¢ã:ž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êä&|0žq-QÉJyœ£AOø+ŠÄ%ç>ùàH$çau…"qÐ3²å^„‹¼X ²iawbJ„cùÊö¥UZa¥9†[váÏÅ%ÛNÞ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Ä”KŠm îÔl³êÕA©³-D_Y›Qkp›`XL¢X­_¡e§äþÑ2Oj[¼—lýHĤýU»¾¹üƒÚ^Ò ­å&ŒÜëejkÁ)fÉéôu+âÖ~xcÙb’V+¶¾ÃÌrCùYÀZúävÄù´Ôå’­Kò¼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ùÊDNìzþ‰hCyÌ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=^ÃIòžµ 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-[ ¾s쀼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Òë|˜Ù­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²ÂÙ±*õJkò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ï†nÞ'üÛ·åΡ?—ú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ÙyÒ/™-ÍDMkþÔòâ4¶1Ï»Qh¤GDæaËkÕòƒ¨Ô>ø½/}ì³"¥XÅ÷‘o(h©a̶Õ=©°L|å+ãõ$?ø±qh#N‹u£¸±ñjóK͉öw c¥MoòŠ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ÚË™± º8ŽB±|õ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·ÆºþŽwì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#ƒæ.oò¤Ê¨>{ðÏóÂ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Õ,<‹ iòóÀ­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–Ž‘Ç†®˜Þ¡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Ð~qTŽG5 Ê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è„Ò¤_Ü¡SòCVdy[«Ð¼$U$».ˆ% ¶Û^SíÚÎDægj¥c/35¾ÑÓLã2%2dji‡¶!î,ØgîµîŒ¥g^”“†¦gÈ•¶¸ç3gì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–þ¦•„YÒF¥­Ø.ë uˆ×ðǺ˜RÅvŒ°ä„쯠¡â¤nc‡CêÞAš-lý®Rìv›ù¸êº¢ì8ךj-‚ògù¼aÆ@è´–ù×Dø Ý9w“¿‰qþµØ—«Ù[И™]¶¼‚ÄŲZíÐíècšM:¥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þž/sžu’ÃõkÅú…-Y€i#“Ñ¥µ›ÙÊ`[­È¥U ´¦_HÆÅF†Böü°á^dÃëtè¼iŒ¢ŽØ¡´—Ì¿ó"šÞá²GM·(‘ÈÁ)JÁJÏ<¼á&t64öðw¢KìP©ÃêŒeE40‹_æ„Xn]nÒŒ²-äc;œŒ[‰²ø±_|qù÷‹9Ü5©*†É8%!ÜÁÂu `c¥â0œ0¾Áq`ýÍhÒØïá|ÂhÀCž|¿³VÜ–²'üCà *uÌ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Òþà£OàG$„á§Ü,ÊÞ·¥ÎùÿAÊÞ,Àû“†ß=äïÞ>ˤ5øu¡Ôø}¿÷¿ýåÿýÝ?þé?ø­¼üª3Î/'÷ œl{ÇîŸÁþ*\Ȱ¡Ã‡#JœHqbBƒïf4øm›“CŠI²¤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ÿ°£;«´;öÄcŠe¤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¡PuEžf*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?þ¼ûuì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†ŒnÞœ‚.ŽøäŽ—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ž%!ô#AÒå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|øÖµFŠ6©éýÐ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…¤Îf4EÒ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ÓÛŒ*D3OžYŠH8RàFnGþgA3#5õ‰5Æ#w‹$/uBFÌ¡J3'ácÉòœtÊÌžüä–&5àwí­“^Ö²m g8/Ñûn»=+™—¸VÌæg¸Øä 4!hî¦5”î¶¹l&xÉóvò•«<åR –ZbžFÒü†1Wy ëâÁ£äæ1$è¼F®˜m!bÖJÊ—Îr·ü†MgúË£Nõ©[åUǺαõ -Ô +OËžŠ”‘‚ ,pê`3äyÉ'2Æ“‚VšÒh/Lƒ2ŽSÜè4ÑãM^†|¤Ïìð0Ò{b2m(’ uû5Ž8©„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Ì÷HPoòè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¾£HŽh¼Ç«7€Û«2¸†Y)¬Hʘ•¢¸kP{Ч'¬aê½c¹Ö«±/,‘©ÒeZÐ ¦¦¶B<ÄDœMò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æ(Tò2£á)*Í)ŸÍÞxÏì•ÏWݸØk« ÐþºúŸ±RÜFBþ$ZÇßÞáŽØ:(á.·á#Þå©Ãå Žå®å7ÒåwÜb^å^Î:-·å•S@qŽ:u>9ü=æw>ç]ÎÜ Çj:E‹½r@Ùá»hÎh(azAN×~§…þG->´q—ãm!…iÞþ“Ì­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†Cšu9lañ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Øfž9Ó«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•êèÜ©¿,¦ísì©]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äþnžv›‚„­‘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~æiŽfj¾fkÎfjÆRÖº‚¨ì2G̰„ ‹Yΰ|"KgSgwngxFŠužç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ìž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²jiÌ^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åÅ·ˆï&~sò.!ÆŒ7rìþèñ#È"5¾ûÆââE‚#W²lùño)œéò&Nþj,Ùâ>Qz³b3'Ò¤J—ôy¡ÐwÛŒ2­jõ*Ö„5cÝùï×ûhþK 5+Ú´jU–-ëäÛQ0e"4»ö.^¬(ß9d—2nÞÀ‚Eî›XìÝB”m½nì˜#ß‹ÒÚN,Ëø1æý•Zy§?¾3“F[rô̳¥­Î½8V(ÙÕͪ~WôiԲܨÊî½Ôéf²¶yû.Ž9t؃[ej5îHà„Rh`…úÆÍ;H|ó~)&!†%’xâ…(ƧÒ;ìDÃA^Õ÷/ eÒˆªÕè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 ¬5š5Yì0ªcv 6­Šyqk[^jbŠq[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´ì mì(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Ò¹NTšASw9Ä‚ ¯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ºZžfn(÷†ˆÒ·Þ:©¦µ,Ý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Å dŠpÙ"ù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ïoòÜ–«‚-§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þFCŠUwì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‹)ˆ"éˆ*©…2iŠŠh“®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æËØ %yìã]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Ü·NÌ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/¯ŬʊØ"Ë £º“–&ï´Õ×Ó~sòk0!vÌ?ÏB˜_ü«a[„Ø`ŸŽRv :s*ñ¦ö±£¾He‹g¨åý…™f–k~ÙæœqÞù"­â†¿2Š™è›gÖùhžWVÚå¤^ú馡†Ú'nžxç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˜Ašp„(,!¸„Œá>£ƒà Y¨BÖ‡ ¼¡s8ÃöЃ¤ÉÚp²Â îЇFL"DʬKlòÉ@”ÄDò‹Ktâ³ØÄ.Zì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'¹üÁŽlAžòMì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%¸UžFlM á‰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‡ƒbsòÏ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æ!–­ ?"qŠaÆþ/ 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ùþÞHŠ5'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“"ðÅÁ Õìºô“Sì$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€¶ ’ìEvži¸].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#Yì(ħ*,Åé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’]BXžZM8&Jï81XV%ÙDàƒh9„×;‹­˜ •iþWÓZìñ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ŽþOÒŠ÷±• ©ã:ï\ÐqÉZ LÞ^âºL\ÒþIó[ (°î¡)ª\wîæmÎÖõÉ* «lô†Î…ÖÅÉô)PŒÆÉôÀ‰Á™ª¿ûZ›\cì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¿ÌŇ/ÏLše§s‰N€GÑàäHHC»Œèn€óY³˜5m#&¤úa¥òV–oi†Fl\R¾ñ¾¦­i8Š)ž÷¤:}ŽA3kâMÊ%«­¡Î‹ÜñP»vxã[27~#/Ì}NŽE¤_K&Ȱ#n¦|™CHª=Q> YÌíÐV›<µÌ…ja}¸FF³e _ФV`Ãop ’õ³$N0‡)Ê„– Yþ8æI“`ÅL Ñ ¥v¿Nf(–ÊZƘJŽ í~2cb.wB@w½c ÚâoÞ†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< ÉeÒÓ›u’È%Ciz`z›<‰BCÑ—;nJSsÎ4!5¥)Q]’ÓJ3_­*Q…Z¢¢µ7ÌôˆRÏÉÔüÔ%Òç7’þ€#‡@ (Þ¸Âo£+†mÙË$¢Öʘ,®ísIéIHbF¢ÇäÌZ{’™(L­¹ú‰“òÑqZŠIßvô÷8ºV ŒÞ H%6±î ^™ Ö¸6.­"z‹ñ"6pƒIqà(Ř~¾6µîl cRËAÀ¡5& ™ml7xÛ·Ôµ¦-îBvëÚà6D¶ÅzÔX©ÇõØîÅAÒ½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Æ%Uò?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Í‘…MŠB«[ß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ž¦EzaYI8ršWOd0D ±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…’ù" ù^Œ–’‰›¼“†:©ý]ûUšG"Rx^³œ?D€=¢™Šù ~Ù;Q¹D•¾©,ý¥ÿ.›‰‹,I€{‰›>¡Y&Ç›^™ÿ‚“äI›DS/™p—„Ñ™oo [ DKM””li„t²š4ù,®~Ò-‰'¹hgM]9œ-¡›±¹i x–/$œéI4š¢Ù\Ê©Ÿ¢¦‡®×0-ѹ´XBò 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‘'´;¶©È¦‰IÞ€#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ÖYšzI ‚„ˆN9Õc DKê ÈÔ¯ìÖÿÀƒ±̃Æ7rYé?‰£áßGŽ7Ð:Ô@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¢EEštè;›ÿ¸½ô¦T¥U­^ÅšU+Ðwï¾9¡ºUìX²e±2ýú-ìÎa;…;¶«¾š £ÆÅ›×¬Û®dØ­ó§Ï­^ÂE¡zcºojÎÂxßÝôù.&Ó8™z•ÙXóf«’eêlÛÔó`Î¥M—µl±OÈï´ì[ölÚµm߯[÷nÞ½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ˆ]Cì¦~Š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‹[kŠx1—ù£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•‹¹{ú3šf2L› »ôŽ7nq|áDÍTþ‡9”ŽÅ‚ñ”ÂÌØR¦tû £uEY%‹¦¼šÊ7:¦ÀnUIZÎëæÔÎÝt?íÓ„zg:@BÕ,ƒDf´žÃ¢4€2ý©NÔ±~ 0gµž;ç ™±–o4ÌÇ„Å)Șƒ¬<1kØð¦"µš'vuë:M)×MÍcw­I^ÑÊצ|씈}þ×Ìõ&êVÞ¼ñØx,IÚéRÙ.מÖʪJ± tvÚ=&©ß`$k±";ä#o¡i1†¬™.“dCÍ)5ÏMEWƒnºfœ´SUÙÞI‹xd®l÷øA@Í„ƒCÈàí¤3¢剓"šþ£ÂS1ªä {>^žÿì‰x›B^‡âd`éMì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¶ì@‹À¤CžmµŸê1 ú£ã#¹q:v0$ó¸&¶&4 ¶¹¢Ý!œ]Úž¸‘éˆÂTÂ#ü U·ÏÛ©–ê£üàA ‚® ‚:™® 9ÀŸ|’½ÙC9›É¦EÔ£ô&[Ä£:]“¾s!¦9¢·a4¢Ÿ‘ <©)«xÅZþ”Ũ©1[\±]t›N DbŠV<½À‘8šQÄ"Û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‚„%™¯°*©KAÌÁlNL¥N蜗êdLÂ\WÌAÑ’Pu£ÁÖæ)éÒÜkÓZÒ V*G'Ø Œwho1B½O.j›ž ²ùð’¦;µŠ™#aµÑȖʸKIó 9±ˆ‹‘„E®PUž¬±dÙ~ÏáКå * ¡É k`ËWòIØ'ŠFð1#…Ç PvTj*ñŒØFÓw ÕxØ€LÖ£ýÍŠýþ@$€åQuÑ$¯ mÅ1âã¹ •´p­i=kYÒ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Õ-#ÁͦµNÞòÞküMד$k‚-P—(39¤³Àp.A`Tûë2{¥Žñ£ŽA=$à(g+fxž÷]gv¶Iwn‹zŽgï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‚+ÐeŠÌ’Ð]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ðeò»: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ÛVòñ–ÛŸ™7Û©–Žö0[èØü(ut¦™ˆ°íв™Â]J“&DÂ$4‡ibJKª-I¥M1}()ŽtBƒ/ÂdWxžJ´”FUº‰ˆŸx¦T'иøIÏøÖØx‡÷Ÿt¨ÌB¨´-éo¸vZ­"õgöÌœÍv¬|ps¿Àîs –›W–ä‰b`@Œ°›ÝH¿t?Ñ?÷ëþX‰ìS*Ê>º%Å#-ø»|‰mH¨ýY+öá<¼¯³¿O´— ´O¡±ä²·Ïpòì+(¶|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¿š4Kò Á*”§ï›þë¡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«êBnÞ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²þÊ1ŠvbÐ"náûÜ‘dxýáCw- ²3~™ä»‡7/ç‘¥ýÐYãVCý˜x#…Dà{#É} bDRtÍtDÜpsE\þ”¶ÎL ež‘XbR›™Õ„f&²Ø"ZûÌŠ.ÒX£?nmÁ D†X£•öN X™eÒ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œ@@…oŽIAI"(œÉäQP‰›@v¾µÉo")`7.h Är‘YbcùPHmC49Ò†¸ø%ùPˆ?úÑ2¬“‡“‰>Ôñ!ž¸²‡Q¥(ÏÆ¯Ãò ¥ì‡ iBKVÒo°œ¡iþAËOÞR”¤4åMŒƒ1£¤z:$øip‘š4Ò mf+Œ=ÁÆ7÷NmLC+Ô"Ï ¤:blGîŒÊTþFŸ`hžiÉF¦¹Q0v$A< Š-Í…É\›‹dd“hì¡6Lˆ+é~9£DQG?(ÇŽCZË¢3±Vüæ!s¤õ+œ?2ºÑŽž !ÿ°–µ`(Q“ú¥Â¤èJ/ÚRžíù€)I^;8•rˆrÔgæ$' @2µE=aOì¢ %ÉÌä~Û±ª‰œ‰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¹(ÊNdLì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²Ó·™ÜbòeDpƒÙ&×Å Ycù­˜@8ÇX£SŠOÇ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ÞdŠ1™LÄRk”„[½X ŠÍTˆ"Ém”ÒA™Šœ’y)5É\Ü$d¦…šWJ^ÀXN mh ÞÒÇ„ê(Z%‡užbrL!‚ôh»hb ÝŽ’êÏÇ”ƒ™GxéYÜ#Œ˜†D¡²éLX’U©•þp”R:ŒL+%[7J†FùR> „3lé¹’À„Îß=ê[ÅØœJ[¯aêà`•#qTDÖ¥%Nç?(êÈÔ‡ŸVêpÑD=_ªª…HzGš7”§ž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Œ¼nìþò+ß¼ÃpŒx}ŒdðÄndÚŽL¸Cq¥MØi ™–¤mJlÈ’Îd¯6 LÕ9¤ÎîXL^Ø_¢ì7‚Ú£ÙÑ0 „4p ¤±ÉÕ,­ž.Y‹ÆÕ½‚DHÕOBHÔ‡€¼®p {È ûDBh”4°ƒ™išd<„ÚŽ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ùyÞ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ÚÔ¹óä»oVÞôç/(O£GŽ|gÅ[ÑCÿ9E:u¥>ªW]JŪ0 ;commons-dbcp-commons-dbcp-2.7.0/src/site/resources/images/uml/prepareStatement.gif000066400000000000000000001363231352030664000303100ustar00rootroot00000000000000GIF89aî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›Bewò$»}UYf|µ+Ô¯RÃz v!ÁíòÛ¨A·G3®Ó˜” Ý±xËêUxr`ÆŒ÷ýó[òß»“ýÿ|2/ÙÇŽ#ï•,Õî¾ÀãúkìöŸ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ÑeÒ_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 ¦ŒUÌãg˜G=ú1{…ù` òŽ£´ãF‰‹"µ¢•D6²(dd"¹’£€$ñû6c—E*Ò‘’Œä$EiÈPšr”Œ|ä)I™Ê®ò•ªåg>“Éöƒ Õ`%,]‰Ê^F2–¬ô%$…IÌ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ÌaŽ1ô³†Þ ‚þ–¿Ìæ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Áwò×€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~§yšG§À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У؇ópŽJ©”„Ù–ŠY˜–(ntšSwt^H†É™o©j§lô@‰W 70 ·¡¦ŠI|ÄšS'—â6J§š»i‘¡µÐšö@lÐ ¿ögQ€“Qí ˜¾ttXjª‰ºþ©›ÙÉ›Þ)—ªYšJ'žà)šªÙÀ šÏæ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Û»?ûpšHš{‹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¬º*—®[AŽm•몽¦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üá։ʪÜ+hiìM²@Ë*™æð´=›Ùjñl0”í­»ÓLþ¶ 0Ëä× º  ±àã®6Á@Pœ\¼BK ×{ÛzmÞšѹ† 0ËGëÂY7œÙÌYTb¾‡çøÖqª­»#¿´oÐíл¬ËúûƵ𸠭Âñ0|+¼¼ô`%nÞý 혽`ᨪ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ö‚¦GìX¼!°¢gÏwðæd› oN/=׋÷Zx­®µŒ¸ŽË@ñâöpÍS_]¸ð{ÈÞ“ ¬}lwôDŸi-jT\±(ðáǵüùgŸÒ‘¢˜«²úå—ýè)–¡Äûå¼Áˆ¼xæñŽz¾Z¥´_Ì»À¤cŽ8z’³ÇÂâVùÊ8zž¹Å+­Fg oþ* ü§ÚùƪÓ~ɪ¶¡öÓ/zYe0õH)„I"AÅ"‹>ñ%\,KE†~‘‰’?$ÑÄ.?*éC®DpI«’“nþÒ„UPIìHHQ©-Nöh„’BdZÌNþè15ç‘äËUâCNB4ñ²"NvjLNð°§’?8ñ£“‘&éC“Iü0…¬œ$ê^œÜ—^Ä¡¢Çv¢`©$qŒ‡zhéê+Š‹žÝ ˜§Å àŽ  X\€jq²¡lmÍŸ§^ƒ*(”‘•Ôl{²«xž1nY*úãq ©$œ´ ÑÄK$™$zü@aeA:Y¤<òÀ£’B8.œD&A+’ºð­¤DÂá$Dò؈HáHIX¡BPùÔRÁ…’GÐ+Í´¡hç¿(Ò ÷µØþfÛJ]¬~±…UñJ 1Lòøƒ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—tŽnÎ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”JPŠR\±þˆÑ O"…žN¢´j¡‡Ot…U+3äg ¡\¬b<\b"èT<Ìx çˆpä!_¢Çøð‡<œ"yYbö@°8*!ÁjEgÏøOœ2cyMѨ¡ºx¡OÜŒE—™÷2{”"<œ&‚ú5{ðÁô]á¦óЉyäÁHŽa ™‘B¯ÐC•+ÁŠ<ó{ÕÖ.måN¼”†À“îX+ÕÔ”qµ}œ±µB–¡Rv¨Â›vqÌÊÙÞcõh@é&µÎÎÚõôãÕ }å}]ÝÜQþ‘a€°OÞ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%AŠañ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œÄÐÅÝ¡¨…öÜßUCìqßßõ5_~U@ëªÒ¾¬0œÕøÉ©€X¡\§›áQ¬RØ(±ŽÌ`àõà$[MÇ]AŠF( ^ŸÕ ,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 ©‘ÄŠSEš9hø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Õ€Fnì¼Æë=zìÇnìýlgN`g¶O ûeqy‡ UX¡, þsì$£y^Ë~lÂìÔÎßÊnìÕ~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ôÄ#=bšf2’ÄØ¤"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{æ9owÌ¥ì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?ÕÐOÞ²2ï>'QZõ<â!ïøÐ?^ô‘éSŸDÉHf˜ÙêN?zÔ—¾ö¤¿=íqø­²®V¡EÐaøÑϾø²?¾êq_üFÃà ‡a}î£oüäKùûЇçµløž«Ɇö¸gODŠ0?Ì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„9Žc&’ã;Æã&ö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 ²!"öaìá¤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„rì̾,ÎÆ¬Ï-͆ìÇ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œãñlòR/ñVoð*¯ð^j6"]J/ž!EŠoø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ñðgoòÞ±çq G ¸ª/¥–oŸo³±ýº± Gïòò®Î â± 2!¯!§±æ%*ðÕ\©˜Á2¨'WM'Øpˆ(C…(‡²){2*£2)—²'¯2ØÎ*³²*·ò,GÏ'ßr+C …².Û²8 RÀžyz/'²!žáþ$çpÀlì’°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¾úóÔ;œÃnôk™?Àöƒ!Vì›vÿœýðïß@„ 6tøbD‰)Fôç¯Bxÿ6ö[þ¯Ý¿s +–4yòŸ?†ü†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Ÿ;oò‰·G9F÷®1çtåÐÁ—ï.á>~VÙ󛊴fpÒ…«ö›:\~~ýkÝj\ØOþáÛ@¶úº+¥}؇+ìA… Zì5êì1ª&Û5„bg6;¬,!G³¨‹ü!@›ÖQé ͪPFƒcç€ ÜÑ¡¯ÀBè¢íÇŠðƒ¨¯†’lë¡%rÈ&¥lž¡¾9²Ç)•Ô’É,·\O'ït#0°áÖч#³Š\“Mòê¢ë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Ó¼èŠ‰íø†8žaúÇ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ëØïAšZ(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;–¶š @˜×<&ªTžò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€ ´À¤(yìØ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'”?€ÅRòq¢oW~nÃRŽ1å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›•*iòYÒ[7B˜ªD»v z ¾ÀÐÍ“Œ†ÊÌŠÒÊ€A<ƒÒüÐl2æ/'‘Þ:pï%!;Õ0×f÷_ø&B,ráþrU7ePc%Â0PH;\Iç<“¥rùnWOKCOÒ#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ï†Vò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,¬­(éSì© ò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„ŽwŽTh¡¶ü²6èwYÒκäò¢Æ¶û~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ÅüU1žXì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Ô—’6shŽòÞœÚÑ/7`¾ç¸o’÷»¯w6· NX}»Å‰ËJ³=ÍsúÞ »òÎùM n1·ЂuµYh6èy#Zt,÷¶Ë™N’öÎÜÞוö½FZu«W1ŠRþ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·ÕÀ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”‡··mò‡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ÊÚ(†€jyìæUD²gLXVµ³»ec®âh/ÙÐ×ãÁ¿Û¼ÿû ,ÀLÀlÀŒÀ ÀØð Ù€ \ÀÞ Í+ lÁþÁœ Ù0 ì ;p ܼŒ 5РذÁû›Àÿ+ÂÌÀÜÀ- Á3|Á5LÃì „!;P5€ ì³lÂ|wqFä? _`VctFV­[¯K‘[{ò»e‰Zk´±Ô«¹[@ñ/Pc,elþfŒÆg¬ÆiÌÆkìÆ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Ö=â>WoÒ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ïøÙ:¶È*pì`¼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ŸÒ:è®oÌ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¦yŠf£!â§^Çî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¡KŠqr’Û¤;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þOšZF6Õ¨I kX‡êT‘ˆ)üaŠAŧϓڴ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ÍvAÌc“j¹¾d>J~u‹æÁvvZh~ : :Üd. Ý«‚ùùЙZ 5«W%+YìÎ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¨…°Jxhšz €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ÁLhŠp H‚ÔÏÍÝDW¤QÜ<ˆ¦´~\þ vtQö¤‚ΕÌüÜÄþ,ÊV´ÊõFª”Ò¤J(•<ežÒ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¤Ž#Wì¤>€=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¡—¨Pìe‰°™ b¬5Ô¸õõ^œÃÚ9%+͘+«0›ºÊº˜x%Ïš^é…°a+1î2`ƯQ³~+½£ ?¹õЫ£PAì£~­¯þØÝ¾Ý¾ÝøÅN•($–S †Üv˜ Àƒp¢œ_ua²+þÒQ×õLïmxy<…Gw¹Üèž8áÅ\êí°êͨ¬jŠIIÞ_%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ýLò#/¤ÀÐÑu†Ñ"ÕGí¿ €pÖÊön?•Oûõ;)m'ÇÒ WLm¥RÌ1ñ÷+? u[b?ñ5§s9góð~,-('ˆH®’îjä…¨q¾BÞìVÞºöËéƒ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¡²bnÞ'Oì¤x¢æŽŠ5®PAaÇŽf*jǪ̈ÁÙôáÁŒóÚiØoŠ5|¯˜­[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ãþÙž Oò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 ]þeÒŽw°ö(7ƒQ•G í’E¬V¾{”ðŽ÷tµkÑûÝõ~—(î…¯àäK8ï2ÖFQ\"r{šÅ‰ÄuŸqÿ]䮵·Y žVõ°Î’`‘ê‡ «QWTZ=QAªp}¨‹\P¢É7ªÐ‹ä(":n‹pt¢¹%GÙpB2WdçøFÊFŽuµÅ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œÝówò,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 TbŠK•Ô—ÖÐ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#ôì™VšUß 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œ×ýfoÞÌ>„p¶IéÐí™Jorà?`]ÈÔÏN9þÞ"jþ$8Z§Wú¢bO"^kÒà<öN=ª”T‚ÝLDDÌP‰•ˆ_ˆ† ‰edÞL¨nòƒ‡]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 nž8£ÅÉÍ×Y××Zzõé› w´ƒ›ÜþÔz!¹i¬Î„5 ÃRé+å>g4âÐÎP_[>hH æÆüËUº£NìKDx¤Yi*‰'Y±¡î‹Tx)e>£’d*ÎY›XO®jIŸ†*;´C´ê?8À?Ìk™²V®¦éQ­–)½æ«™ÞºÎ©3 ;ü*}Y¡Ey&R:azET²¦KW&Lÿ`Ö³æáy>Aú5¥¤º&î–}ôRšTÔ¦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 ’òÙ ~?|ƒº%kmòÕ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ß¼ÞqšjÁ"§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„@`ÄWoÞ…ã'©·Ò×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ƒ _wòÀ[‚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„ýæmš7o×Þ¸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=úûô†ý°×ÿCìú¶ÂÚ/γà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¨,ÅJOŽru« mÊU3ÖTA•*í#guâ)“ŒÄdqiîÖôE·òã+Ø’+[þr8§ùÍ›o! õ:=Uz‘•Mñ‰5ö¡“ÖédÍ@É7T“àIEí8Hp] €ªX4ª•îC ÚY©º’×=‰t“™YŠRÕ¢‰t£‘àN…§}¤îtH<§h¬||-lù62»pŒyÅ <û*Ã7òC'8xG•[•)Úð†àA¶< !Øu«(^b&ÓÀHè”y݉zÖ±&ñp+# VÈn8»¯,‰‡Iò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>’oÒèŽ{œïùŽ$Ãð ™¼æ¬!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èrvòdŒ~ô‰'ÃÍQ|òþ¾ÂÈ0~ƒ r¬;²á¤ª@ ¼à)ÀlÀ 1²=Ýó=á3>ås>és>;Z ¤*Ȇpì…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ÿ·Aò$ƒ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€2ŽY†þ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¦ÏŸ@EÒ$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ý‚ëYÒ`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ƒ¨<³/¡6žP3½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šiÒ×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,¹<©ähò,—ž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Ž>ÚfšjÝ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Ê'Ä qHAì 鑊œ÷ݸ°üÜ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ªAyÞ0Bn@zþûgoã”#æWÌØ¡ùACòN4´&1v¥'h¥ZJD¢á äBjR2Øž4›aä \å0g±¤L*¤6Ä)§kŠKÉÙ¡ß \`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åòŒtŽGaʦ£4Á£ð›" ¤Bg9ZÎÔ¡{ÊžÁKbèéªá(æF_K*¤i’!oBôÃnVo1v)W3?ÌZA¼¥rCœ„qÑù€æFˆ0Bem*@õ‚Òê` Ô ƒ\U¿xŠE b¬Â«Yÿ•gWê¬`ÔøÆtÄahÜÅo­Ëq0lÇ'ÌÇðûÇ€|3peœ\Ȇ|Ȉ¬8x¬T~œÈŽüÈÉb”„,É–l!;commons-dbcp-commons-dbcp-2.7.0/src/site/resources/profile.jacoco000066400000000000000000000016611352030664000250500ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT 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-commons-dbcp-2.7.0/src/site/site.xml000066400000000000000000000063621352030664000217070ustar00rootroot00000000000000 Commons DBCP /images/dbcp-logo-white.png /index.html commons-dbcp-commons-dbcp-2.7.0/src/site/xdoc/000077500000000000000000000000001352030664000211475ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/site/xdoc/building.xml000066400000000000000000000042221352030664000234660ustar00rootroot00000000000000 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".

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

commons-dbcp-commons-dbcp-2.7.0/src/site/xdoc/configuration.xml000066400000000000000000000435401352030664000245460ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/src/site/xdoc/download_dbcp.xml000066400000000000000000000333661352030664000245030ustar00rootroot00000000000000 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 SHA256 hash (*.sha256 checksum files).

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

commons-dbcp2-2.7.0-bin.tar.gz sha256 pgp
commons-dbcp2-2.7.0-bin.zip sha256 pgp
commons-dbcp2-2.7.0-src.tar.gz sha256 pgp
commons-dbcp2-2.7.0-src.zip sha256 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${commons.release.4.binary.suffix}.tar.gz sha256 pgp
commons-dbcp-1.3${commons.release.4.binary.suffix}.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-commons-dbcp-2.7.0/src/site/xdoc/guide/000077500000000000000000000000001352030664000222445ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/site/xdoc/guide/classdiagrams.xml000066400000000000000000000026511352030664000256070ustar00rootroot00000000000000 Class Diagrams Commons Documentation Team
commons-dbcp-commons-dbcp-2.7.0/src/site/xdoc/guide/index.xml000066400000000000000000000024251352030664000241000ustar00rootroot00000000000000 Developers Guide Commons Documentation Team
commons-dbcp-commons-dbcp-2.7.0/src/site/xdoc/guide/jndi-howto.xml000066400000000000000000000102231352030664000250460ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/src/site/xdoc/guide/sequencediagrams.xml000066400000000000000000000024731352030664000263140ustar00rootroot00000000000000 Sequence Diagrams Commons Documentation Team
commons-dbcp-commons-dbcp-2.7.0/src/site/xdoc/index.xml000066400000000000000000000112111352030664000227740ustar00rootroot00000000000000 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 package relies on code in the commons-pool2 package to provide the underlying object pool mechanisms that it utilizes.

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

  • DBCP 2.7.0 compiles and runs under Java 8 only (JDBC 4.2)
  • DBCP 2.6.0 compiles and runs under Java 8 only (JDBC 4.2)
  • DBCP 2.5.0 compiles and runs under Java 8 only (JDBC 4.2)
  • DBCP 2.4.0 compiles and runs under Java 7 only (JDBC 4.1)
  • DBCP 1.4 compiles and runs under Java 6 only (JDBC 4)
  • DBCP 1.3 compiles and runs under Java 1.4-5.0 only (JDBC 3)

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-commons-dbcp-2.7.0/src/site/xdoc/issue-tracking.xml000066400000000000000000000133411352030664000246230ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/src/site/xdoc/mail-lists.xml000066400000000000000000000225211352030664000237510ustar00rootroot00000000000000 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 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 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 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 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 markmail.org
old.nabble.com
www.mail-archive.com
news.gmane.org
commons-dbcp-commons-dbcp-2.7.0/src/site/xdoc/release-notes-1.1.xml000066400000000000000000000447761352030664000247560ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/src/site/xdoc/release-notes-1.2.1.xml000066400000000000000000000044551352030664000251040ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/src/site/xdoc/release-notes-1.2.xml000066400000000000000000000204211352030664000247340ustar00rootroot00000000000000 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-commons-dbcp-2.7.0/src/test/000077500000000000000000000000001352030664000202255ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/test/java/000077500000000000000000000000001352030664000211465ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/000077500000000000000000000000001352030664000217355ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/000077500000000000000000000000001352030664000231565ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/000077500000000000000000000000001352030664000246315ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/000077500000000000000000000000001352030664000256235ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/StackMessageLog.java000066400000000000000000000073351352030664000315120ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 Stack messageStack = new Stack<>(); private static Lock lock = new ReentrantLock(); 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 StringBuffer buf = new StringBuffer(); 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(); } } /** * @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; } /** * 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 void clear() { lock.lock(); try { messageStack.clear(); } finally { lock.unlock(); } } public static boolean isEmpty() { return messageStack.isEmpty(); } /** * Obtains an exclusive lock on the log. */ public static void lock() { lock.lock(); } /** * Relinquishes exclusive lock on the log. */ public static void unLock() { try { lock.unlock(); } catch (final IllegalMonitorStateException ex) { // ignore } } } TestAbandonedBasicDataSource.java000066400000000000000000000325651352030664000340520ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.Connection; import java.sql.CallableStatement; 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; @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)); } // ---------- Abandoned Test ----------- @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()); 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); } /** * 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()) {} } } /** * 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 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 } } /** * 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); } /** * 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()); } private void createStatement(final Connection conn) throws Exception{ final PreparedStatement ps = conn.prepareStatement(""); Assertions.assertNotNull(ps); } /** * 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); } /** * 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 con.lastUsed has been updated and then resets it to 0 */ private void assertAndReset(final DelegatingConnection con) { assertTrue(con.getLastUsed() > 0); con.setLastUsed(0); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java000066400000000000000000001054421352030664000323300ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.lang.management.ManagementFactory; 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 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.Test; /** * TestSuite for BasicDataSource */ public class TestBasicDataSource extends TestConnectionPool { @Override protected Connection getConnection() throws Exception { return ds.getConnection(); } protected BasicDataSource ds = null; 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"); } @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(new String[] { "SELECT 1", "SELECT 2"})); ds.setDriverClassLoader(new TesterClassLoader()); ds.setJmxName("org.apache.commons.dbcp2:name=test"); } protected BasicDataSource createDataSource() throws Exception { return new BasicDataSource(); } @Override @AfterEach public void tearDown() throws Exception { super.tearDown(); ds.close(); ds = null; } @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 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 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(); } @Override @Test public void testPooling() throws Exception { // this also needs access to the underlying connection ds.setAccessToUnderlyingConnectionAllowed(true); super.testPooling(); } @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); } @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 testEmptyValidationQuery() throws Exception { assertNotNull(ds.getValidationQuery()); ds.setValidationQuery(""); assertNull(ds.getValidationQuery()); ds.setValidationQuery(" "); assertNull(ds.getValidationQuery()); } @Test public void testInvalidValidationQuery() { ds.setValidationQuery("invalid"); try (Connection c = ds.getConnection()) { fail("expected SQLException"); } catch (final SQLException e) { if (e.toString().indexOf("invalid") < 0) { fail("expected detailed error message"); } } } @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().indexOf("timeout") < 0) { fail("expected timeout error message"); } } } @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 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 testEmptyInitConnectionSql() throws Exception { ds.setConnectionInitSqls(Arrays.asList(new String[]{"", " "})); assertNotNull(ds.getConnectionInitSqls()); assertEquals(0, ds.getConnectionInitSqls().size()); ds.setConnectionInitSqls(null); assertNotNull(ds.getConnectionInitSqls()); assertEquals(0, ds.getConnectionInitSqls().size()); } @Test public void testInvalidConnectionInitSql() { try { ds.setConnectionInitSqls(Arrays.asList(new String[]{"SELECT 1","invalid"})); try (Connection c = ds.getConnection()) {} fail("expected SQLException"); } catch (final SQLException e) { if (e.toString().indexOf("invalid") < 0) { fail("expected detailed error message"); } } } @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 testDefaultCatalog() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { c[i] = getConnection(); assertTrue(c[i] != null); 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(); assertTrue(c[i] != null); assertEquals(CATALOG, c[i].getCatalog()); } for (final Connection element : c) { element.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 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()); } // 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()); } /** * 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(); } } /** * 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()); } /** * 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(); } /** * Bugzilla Bug 29832: Broken behaviour 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 } } @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(); } } } } /** * 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); } /** * 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())); } /** * 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()); } @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(); } } @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(); } /** * 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()); } /** * 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()); } /** * 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-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(Boolean.valueOf(original), Boolean.valueOf(ds.getConnectionPool().getLogAbandoned())); } /** * 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(); } } /** * 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 AtomicInteger connectionRequestCount = new AtomicInteger(0); public TesterConnRequestCountDriver() { // DBCP expects an explicit no-arg constructor } @Override public Connection connect(final String url, final Properties info) throws SQLException { connectionRequestCount.incrementAndGet(); return super.connect(url, info); } @Override public boolean acceptsURL(final String url) throws SQLException { return CONNECT_STRING.startsWith(url); } public static int getConnectionRequestCount() { return connectionRequestCount.get(); } public static void initConnRequestCount() { connectionRequestCount.set(0); } } /** * 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 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); } @Override public boolean acceptsURL(final String url) throws SQLException { return url.startsWith(CONNECT_STRING); } } TestBasicDataSourceFactory.java000066400000000000000000000242651352030664000336040ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 { @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(); } } @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(); } } 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("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; } 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()); 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 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()); } } TestBasicDataSourceMXBean.java000066400000000000000000000121761352030664000333050ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 { /** * Tests the interface defined default method. */ @Test public void testDefaultSchema() { assertNull(bean.getDefaultSchema()); } private final BasicDataSourceMXBean bean = new BasicDataSourceMXBean() { @Override public boolean isPoolPreparedStatements() { return false; } @Override public boolean isClosed() { return false; } @Override public boolean isAccessToUnderlyingConnectionAllowed() { return false; } @Override public int getValidationQueryTimeout() { return 0; } @Override public String getValidationQuery() { return null; } @Override public String getUsername() { return null; } @Override public String getUrl() { return null; } @Override public long getTimeBetweenEvictionRunsMillis() { return 0; } @Override public boolean getTestWhileIdle() { return false; } @Override public boolean getTestOnCreate() { return false; } @Override public boolean getTestOnBorrow() { return false; } @Override public long getSoftMinEvictableIdleTimeMillis() { return 0; } @Override public int getRemoveAbandonedTimeout() { return 0; } @Override public boolean getRemoveAbandonedOnMaintenance() { return false; } @Override public boolean getRemoveAbandonedOnBorrow() { return false; } @Override public String getPassword() { return null; } @Override public int getNumTestsPerEvictionRun() { return 0; } @Override public int getNumIdle() { return 0; } @Override public int getNumActive() { return 0; } @Override public int getMinIdle() { return 0; } @Override public long getMinEvictableIdleTimeMillis() { return 0; } @Override public long getMaxWaitMillis() { return 0; } @Override public int getMaxTotal() { return 0; } @Override public int getMaxOpenPreparedStatements() { return 0; } @Override public int getMaxIdle() { return 0; } @Override public long getMaxConnLifetimeMillis() { return 0; } @Override public boolean getLogExpiredConnections() { return false; } @Override public boolean getLogAbandoned() { return false; } @Override public boolean getLifo() { return false; } @Override public int getInitialSize() { return 0; } @Override public boolean getFastFailValidation() { return false; } @Override public String getDriverClassName() { return null; } @Override public String[] getDisconnectionSqlCodesAsArray() { return null; } @Override public int getDefaultTransactionIsolation() { return 0; } @Override public Boolean getDefaultReadOnly() { return null; } @Override public String getDefaultCatalog() { return null; } @Override public Boolean getDefaultAutoCommit() { return null; } @Override public String[] getConnectionInitSqlsAsArray() { return null; } @Override public boolean getCacheState() { return false; } @Override public boolean getAbandonedUsageTracking() { return false; } }; } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestConnectionPool.java000066400000000000000000001104061352030664000322610ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.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; 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.assertTrue; import static org.junit.jupiter.api.Assertions.fail; // 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 { @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; } } } protected abstract Connection getConnection() throws Exception; protected int getMaxTotal() { return 10; } protected long getMaxWaitMillis() { return 100L; } /** Connections opened during the course of a test */ protected Stack connections = new Stack<>(); /** Acquire a connection and push it onto the connections stack */ protected Connection newConnection() throws Exception { final Connection connection = getConnection(); connections.push(connection); return connection; } // ----------- Utility Methods --------------------------------- 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; } // ----------- tests --------------------------------- @Test public void testClearWarnings() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { c[i] = newConnection(); assertTrue(c[i] != null); // 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 testIsClosed() throws Exception { for(int i=0;i) c[i]).getInnermostDelegate(); } else { for (int j = 0; j <= i; j++) { c[j].close(); } return; // skip this test } } // 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(); assertTrue(underCon != null, "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(); } } @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(); } /** "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 testThreaded() { final TestThread[] threads = new TestThread[getMaxTotal()]; for(int i=0;i 0){ System.out.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"); } } private static int currentThreadCount = 0; private static final String DONE = "Done"; 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 created; // 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 = 0; private int connHash = 0; // 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); } public PoolTest(final ThreadGroup threadGroup, final int connHoldTime, final boolean isStopOnException, final int numStatements) { this(threadGroup, connHoldTime, isStopOnException, false, numStatements); } 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); created = timeStamp(); this.numStatements = numStatements; } public void start(){ thread.start(); } @Override public void run() { started = timeStamp(); try { while (isRun) { loops++; state = "Getting Connection"; preconnected = timeStamp(); final Connection conn = getConnection(); connHash = System.identityHashCode(((DelegatingConnection)conn).getInnermostDelegate()); connected = timeStamp(); 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 = timeStamp(); 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 = timeStamp(); } } public void stop() { isRun = false; } public Thread getThread() { return thread; } } long timeStamp() { return System.currentTimeMillis();// JVM 1.5+ System.nanoTime() / 1000000; } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestConstants.java000066400000000000000000000031021352030664000312760ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.junit.jupiter.api.Test; /** * Tests for Constants. */ public class TestConstants { @Test public void testConstants() { assertNotNull(new Constants()); assertEquals(",connectionpool=", Constants.JMX_CONNECTION_POOL_BASE_EXT); assertEquals("connections", Constants.JMX_CONNECTION_POOL_PREFIX); assertEquals(",connectionpool=connections,connection=", Constants.JMX_CONNECTION_BASE_EXT); assertEquals(",connectionpool=connections,connection=", Constants.JMX_STATEMENT_POOL_BASE_EXT); assertEquals(",statementpool=statements", Constants.JMX_STATEMENT_POOL_PREFIX); } } TestDataSourceConnectionFactory.java000066400000000000000000000076051352030664000346610ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.logging.Logger; import javax.sql.DataSource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test for DataSourceConnectionFactory. */ public class TestDataSourceConnectionFactory { private DataSource datasource; private DataSourceConnectionFactory factory; @BeforeEach public void setUp() { datasource = new TestDataSource(); factory = new DataSourceConnectionFactory(datasource); } @Test public void testDefaultValues() throws SQLException { final Connection conn = factory.createConnection(); assertNull(((TesterConnection) conn).getUserName()); } @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 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()); } private static class TestDataSource implements DataSource { @Override public PrintWriter getLogWriter() throws SQLException { return null; } @Override public void setLogWriter(final PrintWriter out) throws SQLException { } @Override public void setLoginTimeout(final int seconds) throws SQLException { } @Override public int getLoginTimeout() throws SQLException { return 0; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; } @Override public T unwrap(final Class iface) throws SQLException { return null; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { return false; } @Override public Connection getConnection() throws SQLException { return new TesterConnection(null, null); } @Override public Connection getConnection(final String username, final String password) throws SQLException { return new TesterConnection(username, password); } } } TestDelegatingCallableStatement.java000066400000000000000000001032631352030664000346240ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 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.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 = null; private DelegatingCallableStatement delegate = null; private CallableStatement obj = null; @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 testExecuteQueryReturnsNull() throws Exception { final TesterCallableStatement delegateStmt = new TesterCallableStatement(conn,"null"); obj = new DelegatingCallableStatement(new DelegatingConnection(conn),delegateStmt); assertNull(obj.executeQuery()); } @Test public void testExecuteQueryReturnsNotNull() throws Exception { final TesterCallableStatement delegateStmt = new TesterCallableStatement(conn,"select * from foo"); obj = new DelegatingCallableStatement(new DelegatingConnection(conn),delegateStmt); assertTrue(null != obj.executeQuery()); } @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 testGetArrayString() throws Exception { try { delegate.getArray("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getArray("foo"); } @Test public void testGetArrayInteger() throws Exception { try { delegate.getArray(1); } catch (final SQLException e) { } verify(obj, times(1)).getArray(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 testGetBigDecimalInteger() throws Exception { try { delegate.getBigDecimal(1); } catch (final SQLException e) { } verify(obj, times(1)).getBigDecimal(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 testGetByteString() throws Exception { try { delegate.getByte("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getByte("foo"); } @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 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 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 testGetDateInteger() throws Exception { try { delegate.getDate(1); } catch (final SQLException e) { } verify(obj, times(1)).getDate(1); } @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 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 testGetFloatString() throws Exception { try { delegate.getFloat("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getFloat("foo"); } @Test public void testGetFloatInteger() throws Exception { try { delegate.getFloat(1); } catch (final SQLException e) { } verify(obj, times(1)).getFloat(1); } @Test public void testGetIntString() throws Exception { try { delegate.getInt("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getInt("foo"); } @Test public void testGetIntInteger() throws Exception { try { delegate.getInt(1); } catch (final SQLException e) { } verify(obj, times(1)).getInt(1); } @Test public void testGetLongString() throws Exception { try { delegate.getLong("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getLong("foo"); } @Test public void testGetLongInteger() throws Exception { try { delegate.getLong(1); } catch (final SQLException e) { } verify(obj, times(1)).getLong(1); } @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 testGetNClobString() throws Exception { try { delegate.getNClob("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getNClob("foo"); } @Test public void testGetNClobInteger() throws Exception { try { delegate.getNClob(1); } catch (final SQLException e) { } verify(obj, times(1)).getNClob(1); } @Test public void testGetNStringString() throws Exception { try { delegate.getNString("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getNString("foo"); } @Test public void testGetNStringInteger() throws Exception { try { delegate.getNString(1); } catch (final SQLException e) { } verify(obj, times(1)).getNString(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 testGetObjectStringClass() throws Exception { try { delegate.getObject("foo", Object.class); } catch (final SQLException e) { } verify(obj, times(1)).getObject("foo", 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 testGetObjectInteger() throws Exception { try { delegate.getObject(1); } catch (final SQLException e) { } verify(obj, times(1)).getObject(1); } @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 testGetSQLXMLString() throws Exception { try { delegate.getSQLXML("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getSQLXML("foo"); } @Test public void testGetSQLXMLInteger() throws Exception { try { delegate.getSQLXML(1); } catch (final SQLException e) { } verify(obj, times(1)).getSQLXML(1); } @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 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 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 testGetTimeInteger() throws Exception { try { delegate.getTime(1); } catch (final SQLException e) { } verify(obj, times(1)).getTime(1); } @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 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 testGetTimestampString() throws Exception { try { delegate.getTimestamp("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getTimestamp("foo"); } @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 testGetTimestampInteger() throws Exception { try { delegate.getTimestamp(1); } catch (final SQLException e) { } verify(obj, times(1)).getTimestamp(1); } @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 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 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 testRegisterOutParameterStringIntegerString() throws Exception { try { delegate.registerOutParameter("foo", 1, "foo"); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter("foo", 1, "foo"); } @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 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 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 testRegisterOutParameterIntegerIntegerString() throws Exception { try { delegate.registerOutParameter(1, 1, "foo"); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter(1, 1, "foo"); } @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 testRegisterOutParameterIntegerInteger() throws Exception { try { delegate.registerOutParameter(1, 1); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter(1, 1); } @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 testRegisterOutParameterStringIntegerInteger() throws Exception { try { delegate.registerOutParameter("foo", 1, 1); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter("foo", 1, 1); } @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 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 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 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 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 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 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 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 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 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 testSetBooleanStringBoolean() throws Exception { try { delegate.setBoolean("foo", Boolean.TRUE); } catch (final SQLException e) { } verify(obj, times(1)).setBoolean("foo", Boolean.TRUE); } @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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 testSetObjectStringObject() throws Exception { try { delegate.setObject("foo", System.err); } catch (final SQLException e) { } verify(obj, times(1)).setObject("foo", System.err); } @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 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 testSetShortStringShort() throws Exception { try { delegate.setShort("foo", (short) 1); } catch (final SQLException e) { } verify(obj, times(1)).setShort("foo", (short) 1); } @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 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 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 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 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(); } }commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestDelegatingConnection.java000066400000000000000000000161151352030664000334150ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 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 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); assertTrue(s.length() > 0); } @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 (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 (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 (SQLException e) { Assertions.assertTrue(e instanceof SQLExceptionList); Assertions.assertEquals(1, ((SQLExceptionList) e).getCauseList().size()); } finally { testerStatement.setSqlExceptionOnClose(false); } } } TestDelegatingDatabaseMetaData.java000066400000000000000000001340211352030664000343410ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 = null; private DelegatingDatabaseMetaData delegate = null; private DatabaseMetaData obj = null; @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 testGetDelegate() throws Exception { assertEquals(obj ,delegate.getDelegate()); } @Test /* JDBC_4_ANT_KEY_BEGIN */ public void testCheckOpen() throws Exception { delegate = new DelegatingDatabaseMetaData(conn, conn.getMetaData()); final ResultSet rst = delegate.getSchemas(); assertTrue(!rst.isClosed()); conn.close(); assertTrue(rst.isClosed()); } /* JDBC_4_ANT_KEY_END */ @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 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 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 testGetCatalogs() throws Exception { try { delegate.getCatalogs(); } catch (final SQLException e) {} verify(obj, times(1)).getCatalogs(); } @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 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 testGetProcedureTerm() throws Exception { try { delegate.getProcedureTerm(); } catch (final SQLException e) {} verify(obj, times(1)).getProcedureTerm(); } @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 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 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 testGetSchemaTerm() throws Exception { try { delegate.getSchemaTerm(); } catch (final SQLException e) {} verify(obj, times(1)).getSchemaTerm(); } @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 testGetSchemas() throws Exception { try { delegate.getSchemas(); } catch (final SQLException e) {} verify(obj, times(1)).getSchemas(); } @Test public void testGetSearchStringEscape() throws Exception { try { delegate.getSearchStringEscape(); } catch (final SQLException e) {} verify(obj, times(1)).getSearchStringEscape(); } @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 testGetTableTypes() throws Exception { try { delegate.getTableTypes(); } catch (final SQLException e) {} verify(obj, times(1)).getTableTypes(); } @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 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 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 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 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 testSupportsConvertIntegerInteger() throws Exception { try { delegate.supportsConvert(1,1); } catch (final SQLException e) {} verify(obj, times(1)).supportsConvert(1,1); } @Test public void testSupportsConvert() throws Exception { try { delegate.supportsConvert(); } catch (final SQLException e) {} verify(obj, times(1)).supportsConvert(); } @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.java000066400000000000000000000427541352030664000346760ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 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.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 = null; private DelegatingConnection connection = null; private PreparedStatement obj = null; private DelegatingPreparedStatement delegate = null; @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 testExecuteQueryReturnsNull() throws Exception { obj = new TesterPreparedStatement(testerConn,"null"); delegate = new DelegatingPreparedStatement(connection,obj); assertNull(delegate.executeQuery()); } @Test public void testExecuteQueryReturnsNotNull() throws Exception { obj = new TesterPreparedStatement(testerConn,"select * from foo"); delegate = new DelegatingPreparedStatement(connection,obj); assertTrue(null != delegate.executeQuery()); } @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 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 testExecuteUpdate() throws Exception { try { delegate.executeUpdate(); } catch (final SQLException e) {} verify(obj, times(1)).executeUpdate(); } @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 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 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 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 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 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 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 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 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 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 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 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 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 testSetNullIntegerIntegerString() throws Exception { try { delegate.setNull(1,1,"foo"); } catch (final SQLException e) {} verify(obj, times(1)).setNull(1,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 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 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 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 testSetObjectIntegerObject() throws Exception { try { delegate.setObject(1,System.err); } catch (final SQLException e) {} verify(obj, times(1)).setObject(1,System.err); } @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 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 testSetShortIntegerShort() throws Exception { try { delegate.setShort(1,(short) 1); } catch (final SQLException e) {} verify(obj, times(1)).setShort(1,(short) 1); } @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 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); } @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); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestDelegatingResultSet.java000066400000000000000000001464371352030664000332630ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 testAbsolutes() throws Exception { try { delegate.absolute(1); } catch (final SQLException e) { } verify(rs, times(1)).absolute(1); } @Test public void testAbsoluteInteger() 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"); } // 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); } // 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 testGetBigDecimalInteger() throws Exception { try { delegate.getBigDecimal(1); } catch (final SQLException e) { } verify(rs, times(1)).getBigDecimal(1); } @Test public void testGetBigDecimalString() throws Exception { try { delegate.getBigDecimal("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getBigDecimal("foo"); } @Test public void testGetBinaryStreamString() throws Exception { try { delegate.getBinaryStream("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getBinaryStream("foo"); } @Test public void testGetBinaryStreamInteger() throws Exception { try { delegate.getBinaryStream(1); } catch (final SQLException e) { } verify(rs, times(1)).getBinaryStream(1); } @Test public void testGetBlobString() throws Exception { try { delegate.getBlob("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getBlob("foo"); } @Test public void testGetBlobInteger() throws Exception { try { delegate.getBlob(1); } catch (final SQLException e) { } verify(rs, times(1)).getBlob(1); } @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 testGetByteString() throws Exception { try { delegate.getByte("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getByte("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 testGetCharacterStreamString() throws Exception { try { delegate.getCharacterStream("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getCharacterStream("foo"); } @Test public void testGetCharacterStreamInteger() throws Exception { try { delegate.getCharacterStream(1); } catch (final SQLException e) { } verify(rs, times(1)).getCharacterStream(1); } @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 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 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 testGetDoubleString() throws Exception { try { delegate.getDouble("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getDouble("foo"); } @Test public void testGetDoubleInteger() throws Exception { try { delegate.getDouble(1); } catch (final SQLException e) { } verify(rs, times(1)).getDouble(1); } @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 testGetFloatString() throws Exception { try { delegate.getFloat("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getFloat("foo"); } @Test public void testGetFloatInteger() throws Exception { try { delegate.getFloat(1); } catch (final SQLException e) { } verify(rs, times(1)).getFloat(1); } @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 testGetNCharacterStreamString() throws Exception { try { delegate.getNCharacterStream("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getNCharacterStream("foo"); } @Test public void testGetNCharacterStreamInteger() throws Exception { try { delegate.getNCharacterStream(1); } catch (final SQLException e) { } verify(rs, times(1)).getNCharacterStream(1); } @Test public void testGetNClobString() throws Exception { try { delegate.getNClob("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getNClob("foo"); } @Test public void testGetNClobInteger() throws Exception { try { delegate.getNClob(1); } catch (final SQLException e) { } verify(rs, times(1)).getNClob(1); } @Test public void testGetNStringString() throws Exception { try { delegate.getNString("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getNString("foo"); } @Test public void testGetNStringInteger() throws Exception { try { delegate.getNString(1); } catch (final SQLException e) { } verify(rs, times(1)).getNString(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 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 testGetObjectInteger() throws Exception { try { delegate.getObject(1); } catch (final SQLException e) { } verify(rs, times(1)).getObject(1); } @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 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 testGetRowIdString() throws Exception { try { delegate.getRowId("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getRowId("foo"); } @Test public void testGetRowIdInteger() throws Exception { try { delegate.getRowId(1); } catch (final SQLException e) { } verify(rs, times(1)).getRowId(1); } @Test public void testGetSQLXMLString() throws Exception { try { delegate.getSQLXML("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getSQLXML("foo"); } @Test public void testGetSQLXMLInteger() throws Exception { try { delegate.getSQLXML(1); } catch (final SQLException e) { } verify(rs, times(1)).getSQLXML(1); } @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"); } /** * 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 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 testGetTimestampString() throws Exception { try { delegate.getTimestamp("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getTimestamp("foo"); } @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 testGetTimestampInteger() throws Exception { try { delegate.getTimestamp(1); } catch (final SQLException e) { } verify(rs, times(1)).getTimestamp(1); } @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 testGetType() throws Exception { try { delegate.getType(); } catch (final SQLException e) { } verify(rs, times(1)).getType(); } @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 testGetUnicodeStreamString() throws Exception { try { delegate.getUnicodeStream("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getUnicodeStream("foo"); } @Test public void testGetUnicodeStreamInteger() throws Exception { try { delegate.getUnicodeStream(1); } catch (final SQLException e) { } verify(rs, times(1)).getUnicodeStream(1); } @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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 testUpdateByteStringByte() throws Exception { try { delegate.updateByte("foo", (byte) 1); } catch (final SQLException e) { } verify(rs, times(1)).updateByte("foo", (byte) 1); } @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 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 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 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 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 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 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 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 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 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 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 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 testUpdateFloatStringFloat() throws Exception { try { delegate.updateFloat("foo", 1.0f); } catch (final SQLException e) { } verify(rs, times(1)).updateFloat("foo", 1.0f); } @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 testUpdateIntStringInteger() throws Exception { try { delegate.updateInt("foo", 1); } catch (final SQLException e) { } verify(rs, times(1)).updateInt("foo", 1); } @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 testUpdateLongStringLong() throws Exception { try { delegate.updateLong("foo", 1l); } catch (final SQLException e) { } verify(rs, times(1)).updateLong("foo", 1l); } @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 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 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 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 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 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 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 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 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 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 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 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 testUpdateObjectIntegerObject() throws Exception { try { delegate.updateObject(1, System.err); } catch (final SQLException e) { } verify(rs, times(1)).updateObject(1, System.err); } @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); } // 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); } // 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 testUpdateObjectStringObject() throws Exception { try { delegate.updateObject("foo", System.err); } catch (final SQLException e) { } verify(rs, times(1)).updateObject("foo", System.err); } @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 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 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 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 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 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 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 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 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 testWasNull() throws Exception { try { delegate.wasNull(); } catch (final SQLException e) { } verify(rs, times(1)).wasNull(); } @Test public void testToString() { final String toString = delegate.toString(); assertTrue(toString.contains("DelegatingResultSet")); assertTrue(toString.contains("Mock for ResultSet")); } @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)); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestDelegatingStatement.java000066400000000000000000000455101352030664000332630ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.ResultSet; 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 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 testCloseOnCompletion() throws Exception { try { delegatingStatement.closeOnCompletion(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).closeOnCompletion(); } @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.java000066400000000000000000000034571352030664000340630ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 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")); } @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()); } } TestDriverManagerConnectionFactory.java000066400000000000000000000153201352030664000353460ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 String KEY_JDBC_DRIVERS = "jdbc.drivers"; @BeforeAll public static void beforeClass() { System.setProperty(KEY_JDBC_DRIVERS, "org.apache.commons.dbcp2.TesterDriver"); } @AfterAll public static void afterClass() { System.clearProperty(KEY_JDBC_DRIVERS); } @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 testDriverManagerInitWithCredentials() throws Exception { testDriverManagerInit(false); } @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 } @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 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 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.put("user", "foo"); properties.put("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]); } } } private static final class ConnectionThread implements Runnable { private final DataSource ds; private volatile boolean result = true; private ConnectionThread(final DataSource ds) { this.ds = ds; } @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; } } } } public boolean getResult() { return result; } @Override public String toString() { return "ConnectionThread [ds=" + ds + ", result=" + result + "]"; } } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestJndi.java000066400000000000000000000110451352030664000302130ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.SharedPoolDataSource; import org.apache.commons.dbcp2.datasources.PerUserPoolDataSource; 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 = null; /** * Test BasicDatasource bind and lookup * * @throws Exception */ @Test public void testBasicDataSourceBind() throws Exception { final BasicDataSource dataSource = new BasicDataSource(); checkBind(dataSource); } /** * Test SharedPoolDataSource bind and lookup * * @throws Exception */ @Test public void testSharedPoolDataSourceBind() throws Exception { final SharedPoolDataSource dataSource = new SharedPoolDataSource(); checkBind(dataSource); } /** * Test PerUserPoolDataSource bind and lookup * * @throws Exception */ @Test public void testPerUserPoolDataSourceBind() throws Exception { final PerUserPoolDataSource dataSource = new PerUserPoolDataSource(); checkBind(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); } /** * 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(); } /** * 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); } /** * 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; } /** * 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()); final InitialContext ctx = new InitialContext(environment); return ctx; } } TestLifetimeExceededException.java000066400000000000000000000027421352030664000343200ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 testLifetimeExceededExceptionNoMessage() { final LifetimeExceededException exception = new LifetimeExceededException(); assertNull(exception.getMessage()); } @Test public void testLifetimeExceededException() { final LifetimeExceededException exception = new LifetimeExceededException("car"); assertEquals("car", exception.getMessage()); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestListException.java000066400000000000000000000034541352030664000321260ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 testNulls() { final ListException list = new ListException(null, null); assertNull(list.getMessage()); assertNull(list.getExceptionList()); } @Test public void testExceptionList() { @SuppressWarnings("unchecked") final List exceptions = Arrays.asList(new Throwable[] {new NullPointerException(), new RuntimeException()}); final ListException list = new ListException("Internal Error", exceptions); assertEquals("Internal Error", list.getMessage()); assertArrayEquals(exceptions.toArray(), list.getExceptionList().toArray()); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java000066400000000000000000000345701352030664000310570ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 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 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 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 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 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 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); assertTrue(pStmtKey.equals(pStmtKey)); assertFalse(pStmtKey.equals(null)); assertFalse(pStmtKey.equals(new Object())); assertFalse(pStmtKey.equals(new PStmtKey("SELECT 2", "catalog", "public", java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT))); assertFalse(pStmtKey.equals(new PStmtKey("SELECT 1", "anothercatalog", "public", java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT))); assertFalse(pStmtKey.equals(new PStmtKey("SELECT 1", "catalog", "private", java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT))); assertFalse(pStmtKey.equals(new PStmtKey("SELECT 1", "catalog", "public", java.sql.ResultSet.TYPE_SCROLL_SENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT))); assertFalse(pStmtKey.equals(new PStmtKey("SELECT 1", "catalog", "public", java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_UPDATABLE, StatementType.CALLABLE_STATEMENT))); assertFalse(pStmtKey.equals(new PStmtKey("SELECT 1", "catalog", "public", java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY, StatementType.PREPARED_STATEMENT))); assertTrue(pStmtKey.equals(new PStmtKey("SELECT 1", "catalog", "public", java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.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 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-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestPStmtPooling.java000066400000000000000000000230311352030664000317240ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.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.Statement; import java.sql.SQLException; 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 { @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); } } /** * 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(); PreparedStatement stmt1 = null; final Connection conn = ds.getConnection(); 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 assertTrue(!stmt2.isClosed()); stmt2.executeQuery(); // wrapped PPS needs to work here - pre DBCP-414 fix this throws conn2.close(); assertTrue(stmt1.isClosed()); assertTrue(stmt2.isClosed()); } private PoolablePreparedStatement getPoolablePreparedStatement(Statement s) { while (s != null) { if (s instanceof PoolablePreparedStatement) { return (PoolablePreparedStatement) s; } if (s instanceof DelegatingPreparedStatement) { s = ((DelegatingPreparedStatement) s).getDelegate(); } else { return null; } } return null; } 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); } @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(); } @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(); } } TestPStmtPoolingBasicDataSource.java000066400000000000000000000223421352030664000345660ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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); } @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); assertTrue(stmt1 != stmt2); // go over the maxOpen limit PreparedStatement stmt3 = null; 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 stmt3 = conn.prepareStatement("select 'c' from dual"); assertNotNull(stmt3); assertTrue(stmt3 != stmt1); assertTrue(stmt3 != stmt2); // normal reuse of statement stmt1.close(); try (final PreparedStatement stmt4 = conn.prepareStatement("select 'a' from dual")) { assertNotNull(stmt4); } } /** * 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(); } // 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 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(); final Connection conn2 = conn1; 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); } @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 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); } } TestParallelCreationWithNoIdle.java000066400000000000000000000126641352030664000344300ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; 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 static org.junit.jupiter.api.Assertions.assertEquals; /** * Test if the pooling if no idle objects are used */ public class TestParallelCreationWithNoIdle { protected BasicDataSource ds = null; 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"); } @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(new String[] { "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(); } class TestThread extends Thread { 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 } } } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestPoolableConnection.java000066400000000000000000000164531352030664000331140ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 = null; @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 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"); } // 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"); } @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 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"); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestPoolingConnection.java000066400000000000000000000171631352030664000327650ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.assertArrayEquals; 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 = null; @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 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 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()); } @Test public void testPrepareStatementWithColumnIndexes() throws Exception { final String sql = "select 'a' from dual"; final int[] columnIndexes = new int[]{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[] = new String[]{"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 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()); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestPoolingDataSource.java000066400000000000000000000167301352030664000327170ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.sql.Connection; 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 { @Override protected Connection getConnection() throws Exception { return ds.getConnection(); } protected PoolingDataSource ds = null; private GenericObjectPool pool = null; @BeforeEach public void setUp() throws Exception { final Properties props = new Properties(); props.setProperty("user", "userName"); props.setProperty("password", "password"); final PoolableConnectionFactory factory = new PoolableConnectionFactory( new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", props), 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 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(); } } /* * JIRA: DBCP-198 */ @Test public void testPoolGuardConnectionWrapperEqualsReflexive() throws Exception { final Connection con = ds.getConnection(); final Connection con2 = con; assertTrue(con2.equals(con)); assertTrue(con.equals(con2)); con.close(); } @Test public void testPoolGuardConnectionWrapperEqualsFail() throws Exception { final Connection con1 = ds.getConnection(); final Connection con2 = ds.getConnection(); assertFalse(con1.equals(con2)); con1.close(); con2.close(); } @Test public void testPoolGuardConnectionWrapperEqualsNull() throws Exception { final Connection con1 = ds.getConnection(); final Connection con2 = null; assertFalse(con1.equals(con2)); con1.close(); } @Test public void testPoolGuardConnectionWrapperEqualsType() throws Exception { final Connection con1 = ds.getConnection(); final Integer con2 = Integer.valueOf(0); assertFalse(con1.equals(con2)); con1.close(); } @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); assertFalse(con2.equals(con)); assertTrue(con.innermostDelegateEquals(con2.getInnermostDelegate())); assertTrue(con2.innermostDelegateEquals(inner)); assertFalse(con.equals(con2)); } /** * 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 props = new Properties(); props.setProperty("user", "userName"); props.setProperty("password", "password"); final PoolableConnectionFactory f = new PoolableConnectionFactory( new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", props), 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); assertTrue(f.getPool().equals(p)); ds.getConnection(); } @Test public void testClose() throws Exception { final Properties props = new Properties(); props.setProperty("user", "userName"); props.setProperty("password", "password"); final PoolableConnectionFactory f = new PoolableConnectionFactory( new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", props), 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()); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestPoolingDriver.java000066400000000000000000000230361352030664000321150ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.PrintWriter; 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 { @Override protected Connection getConnection() throws Exception { return DriverManager.getConnection("jdbc:apache:commons:dbcp:test"); } private PoolingDriver driver = null; @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); } /** "https://issues.apache.org/bugzilla/show_bug.cgi?id=28912" */ @Test public void testReportedBug28912() throws Exception { final Connection conn1 = getConnection(); assertNotNull(conn1); assertFalse(conn1.isClosed()); conn1.close(); final Connection conn2 = getConnection(); assertNotNull(conn2); assertTrue(conn1.isClosed()); assertFalse(conn2.isClosed()); // should be able to call close multiple times with no effect conn1.close(); assertTrue(conn1.isClosed()); assertFalse(conn2.isClosed()); } /** "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 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(), "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); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestSQLExceptionList.java000066400000000000000000000027511352030664000325050ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.SQLTransientException; import java.util.Collections; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class TestSQLExceptionList { @Test public void testCause() { final SQLTransientException cause = new SQLTransientException(); final List list = Collections.singletonList(cause); final SQLExceptionList sqlExceptionList = new SQLExceptionList(list); Assertions.assertEquals(cause, sqlExceptionList.getCause()); Assertions.assertEquals(list, sqlExceptionList.getCauseList()); sqlExceptionList.printStackTrace(); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TestUtils.java000066400000000000000000000017541352030664000304350ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TesterCallableStatement.java000066400000000000000000000423331352030664000332460ustar00rootroot00000000000000/** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.Ref; import java.sql.SQLException; import java.sql.SQLType; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; import java.util.Map; import java.sql.NClob; import java.sql.RowId; import java.sql.SQLXML; /** * 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-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TesterClassLoader.java000066400000000000000000000026771352030664000320650ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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<>(); @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; } public boolean didLoad(final String className) { return loadedClasses.contains(className); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TesterConnection.java000066400000000000000000000302561352030664000317620ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; import java.util.Map; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.NClob; import java.sql.SQLClientInfoException; import java.sql.SQLXML; import java.sql.Struct; 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 _autoCommit = true; protected int _transactionIsolation = 1; protected DatabaseMetaData _metaData = new TesterDatabaseMetaData(); protected String _catalog; protected String schema; protected Map> _typeMap; protected boolean _readOnly; protected SQLWarning warnings; protected 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 { throw new SQLException("Not implemented."); } 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; } @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 columnIndexes[]) throws SQLException { return new TesterPreparedStatement(this, sql, columnIndexes); } @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 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"); } } @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(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."); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TesterConnectionFactory.java000066400000000000000000000047451352030664000333160ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 { Connection conn = driver.connect(connectionString, properties); doSomething(conn); return conn; } private void doSomething(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() + " [" + String.valueOf(driver) + ";" + String.valueOf(connectionString) + ";" + String.valueOf(properties) + "]"; } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TesterDatabaseMetaData.java000066400000000000000000000544541352030664000327760ustar00rootroot00000000000000/** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 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 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 String getCatalogSeparator() throws SQLException { return null; } @Override public String getCatalogTerm() throws SQLException { return null; } @Override public ResultSet getCatalogs() 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 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 String getProcedureTerm() throws SQLException { return null; } @Override public ResultSet getProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern) throws SQLException { return null; } @Override public int getResultSetHoldability() throws SQLException { return 0; } @Override public String getSQLKeywords() throws SQLException { return null; } @Override public int getSQLStateType() throws SQLException { return 0; } @Override public String getSchemaTerm() throws SQLException { return null; } @Override public ResultSet getSchemas() throws SQLException { return new TesterResultSet(null); } @Override public String getSearchStringEscape() throws SQLException { return null; } @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 getTableTypes() 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 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 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 supportsANSI92EntryLevelSQL() throws SQLException { return false; } @Override public boolean supportsANSI92FullSQL() throws SQLException { return false; } @Override public boolean supportsANSI92IntermediateSQL() throws SQLException { return false; } @Override public boolean supportsAlterTableWithAddColumn() throws SQLException { return false; } @Override public boolean supportsAlterTableWithDropColumn() 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 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 boolean updatesAreDetected(final int type) throws SQLException { return false; } @Override public boolean usesLocalFilePerTable() throws SQLException { return false; } @Override public boolean usesLocalFiles() throws SQLException { return false; } /* JDBC_4_ANT_KEY_BEGIN */ @Override public boolean isWrapperFor(final Class iface) throws SQLException { return false; } @Override public T unwrap(final Class iface) throws SQLException { return null; } @Override public RowIdLifetime getRowIdLifetime() throws SQLException { return null; } @Override public ResultSet getSchemas(final String catalog, final String schemaPattern) throws SQLException { return null; } @Override public boolean autoCommitFailureClosesAllResultSets() throws SQLException { return false; } @Override public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { return false; } @Override public ResultSet getClientInfoProperties() 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; } /* JDBC_4_ANT_KEY_END */ @Override public ResultSet getPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException { return null; } @Override public boolean generatedKeyAlwaysReturned() throws SQLException { return false; } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TesterDriver.java000066400000000000000000000114711352030664000311140ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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"); } /** * 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("user"); password = info.getProperty("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 boolean jdbcCompliant() { return true; } @Override public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) { return new DriverPropertyInfo[0]; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } 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; } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TesterPreparedStatement.java000066400000000000000000000370501352030664000333110ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.math.BigDecimal; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.SQLType; import java.util.Calendar; import java.io.InputStream; import java.io.Reader; import java.sql.NClob; import java.sql.RowId; import java.sql.SQLXML; /** * A dummy {@link PreparedStatement}, for testing purposes. */ public class TesterPreparedStatement extends TesterStatement implements PreparedStatement { private final ResultSetMetaData _resultSetMetaData = null; private String _sql = null; private String _catalog = null; private int _autoGeneratedKeys = 1; private int[] _columnIndexes = null; private String[] _columnNames = null; 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 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 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 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; } else if (_queryTimeout > 0 && _queryTimeout < 5) { // Simulate timeout if queryTimout is set to less than 5 seconds throw new SQLException("query timeout"); } else { 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-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TesterResultSet.java000066400000000000000000001002071352030664000316070ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.math.BigDecimal; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.SQLType; import java.sql.SQLWarning; import java.sql.Statement; import java.util.Calendar; import java.util.Map; import java.io.InputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.sql.NClob; import java.sql.RowId; import java.sql.SQLXML; /** * 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 = null; protected int _currentRow = -1; protected Statement _statement = null; protected int _rowsLeft = 2; protected boolean _open = true; protected boolean _sqlExceptionOnClose = false; 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(); try { return columnName.getBytes("UTF-8"); } catch (final UnsupportedEncodingException e) { // Impossible. JVMs are required to support UTF-8 return null; } } @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; } if(--_rowsLeft > 0) { return true; } return false; } @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-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TesterStatement.java000066400000000000000000000256311352030664000316300ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 Connection _connection; protected boolean _open = true; protected long _rowsUpdated = 1; protected 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-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/TesterUtils.java000066400000000000000000000026051352030664000307600ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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 { private TesterUtils() { // Utility class - hide default constructor } /** * 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); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/cpdsadapter/000077500000000000000000000000001352030664000301155ustar00rootroot00000000000000TestDriverAdapterCPDS.java000066400000000000000000000316461352030664000347610ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.util.Properties; 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 javax.naming.NamingException; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.sql.DataSource; 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 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); } /** * JIRA: DBCP-245 */ @Test public void testIncorrectPassword() throws Exception { pcds.getPooledConnection("u2", "p2").close(); try { // Use bad password pcds.getPooledConnection("u1", "zlsafjk"); fail("Able to retrieve connection with incorrect password"); } catch (final SQLException e1) { // should fail } // Use good password pcds.getPooledConnection("u1", "p1").close(); try { pcds.getPooledConnection("u1", "x"); fail("Able to retrieve connection with incorrect password"); } catch (final SQLException e) { if (!e.getMessage().startsWith("x is not the correct password")) { throw e; } // else the exception was expected } // Make sure we can still use our good password. pcds.getPooledConnection("u1", "p1").close(); } @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 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 testSetUserNull() throws Exception { pcds.setUser("Alice"); assertEquals("Alice", pcds.getUser()); pcds.setUser(null); assertEquals(null, pcds.getUser()); } @Test public void testSetUserNullWithConnectionProperties() throws Exception { pcds.setConnectionProperties(new Properties()); pcds.setUser("Alice"); assertEquals("Alice", pcds.getUser()); pcds.setUser(null); assertEquals(null, pcds.getUser()); } @Test public void testSetPasswordNull() throws Exception { pcds.setPassword("Secret"); assertEquals("Secret", pcds.getPassword()); pcds.setPassword((char[]) null); assertEquals(null, 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 testSetPasswordNullWithConnectionProperties() throws Exception { pcds.setConnectionProperties(new Properties()); pcds.setPassword("Secret"); assertEquals("Secret", pcds.getPassword()); pcds.setPassword((char[]) null); assertEquals(null, pcds.getPassword()); } /** * JIRA: DBCP-442 */ @Test public void testNullValidationQuery() throws Exception { try (final SharedPoolDataSource spds = new SharedPoolDataSource()) { spds.setConnectionPoolDataSource(pcds); spds.setDefaultTestOnBorrow(true); try (final Connection c = spds.getConnection()) { // close right away } } } // https://issues.apache.org/jira/browse/DBCP-376 @Test public void testDbcp367() throws Exception { final ThreadDbcp367[] threads = new ThreadDbcp367[200]; pcds.setPoolPreparedStatements(true); pcds.setMaxPreparedStatements(-1); pcds.setAccessToUnderlyingConnectionAllowed(true); try (final SharedPoolDataSource spds = new SharedPoolDataSource()) { spds.setConnectionPoolDataSource(pcds); spds.setMaxTotal(threads.length + 10); spds.setDefaultMaxWaitMillis(-1); spds.setDefaultMaxIdle(10); spds.setDefaultAutoCommit(Boolean.FALSE); spds.setValidationQuery("SELECT 1"); spds.setDefaultTimeBetweenEvictionRunsMillis(10000); spds.setDefaultNumTestsPerEvictionRun(-1); spds.setDefaultTestWhileIdle(true); spds.setDefaultTestOnBorrow(true); spds.setDefaultTestOnReturn(false); for (int i = 0; i < threads.length; i++) { threads[i] = new ThreadDbcp367(spds); threads[i].start(); } for (int i = 0; i < threads.length; i++) { threads[i].join(); Assertions.assertFalse(threads[i].isFailed(), "Thread " + i + " has failed"); } } } private static class ThreadDbcp367 extends Thread { private final DataSource ds; private volatile boolean failed = false; public ThreadDbcp367(final DataSource ds) { this.ds = ds; } @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(); } } public boolean isFailed() { return failed; } } @Test public void testGetParentLogger() { assertThrows(SQLFeatureNotSupportedException.class, pcds::getParentLogger); } @Test public void testGetReference() throws NamingException { final Reference ref = pcds.getReference(); assertEquals(pcds.getDriver(), ref.get("driver").getContent()); assertEquals(pcds.getDescription(), ref.get("description").getContent()); } @Test public void testGettersAndSetters() { pcds.setUser("foo"); assertEquals("foo", pcds.getUser()); pcds.setPassword("bar"); assertEquals("bar", pcds.getPassword()); pcds.setPassword(new char[] {'a', 'b'}); assertArrayEquals(new char[] {'a', 'b'}, pcds.getPasswordCharArray()); final PrintWriter pw = new PrintWriter(System.err); pcds.setLogWriter(pw); assertEquals(pw, pcds.getLogWriter()); pcds.setLoginTimeout(10); assertEquals(10, pcds.getLoginTimeout()); pcds.setMaxIdle(100); assertEquals(100, pcds.getMaxIdle()); pcds.setTimeBetweenEvictionRunsMillis(100); assertEquals(100, pcds.getTimeBetweenEvictionRunsMillis()); pcds.setNumTestsPerEvictionRun(1); assertEquals(1, pcds.getNumTestsPerEvictionRun()); pcds.setMinEvictableIdleTimeMillis(11); assertEquals(11, pcds.getMinEvictableIdleTimeMillis()); pcds.setDescription("jo"); assertEquals("jo", pcds.getDescription()); } @Test public void testGetObjectInstanceNull() throws Exception { final Object o = pcds.getObjectInstance(null, null, null, null); assertNull(o); } @Test public void testGetObjectInstance() throws Exception { final Reference ref = pcds.getReference(); final Object o = pcds.getObjectInstance(ref, null, null, null); assertEquals(pcds.getDriver(), ((DriverAdapterCPDS) o).getDriver()); } @Test public void testGetObjectInstanceChangeDescription() throws Exception { final Reference ref = pcds.getReference(); for (int i = 0; i < ref.size(); i++) { if (ref.get(i).getType().equals("description")) { ref.remove(i); break; } } ref.add(new StringRefAddr("description", "anything")); final Object o = pcds.getObjectInstance(ref, null, null, null); assertEquals(pcds.getDescription(), ((DriverAdapterCPDS) o).getDescription()); } @Test public void 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-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/datasources/000077500000000000000000000000001352030664000301405ustar00rootroot00000000000000ConnectionPoolDataSourceProxy.java000066400000000000000000000060101352030664000366670ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 = null; 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(); } /** * Return a TesterPooledConnection with notifyOnClose turned on */ @Override public PooledConnection getPooledConnection() throws SQLException { return wrapPooledConnection(delegate.getPooledConnection()); } /** * Return 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); } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { return Jdbc41Bridge.getParentLogger(delegate); } /** * Create a TesterPooledConnection with notifyOnClose turned on */ protected PooledConnection wrapPooledConnection(final PooledConnection pc) { final PooledConnectionProxy tpc = new PooledConnectionProxy(pc); tpc.setNotifyOnClose(true); return tpc; } } PooledConnectionProxy.java000066400000000000000000000111431352030664000352300ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.Collection; import java.util.EventListener; import java.util.Vector; 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 = null; /** * ConnectionEventListeners */ private final Vector eventListeners = new Vector<>(); /** * True means we will (dubiously) notify listeners with a * ConnectionClosed event when this (i.e. the PooledConnection itself) * is closed */ private boolean notifyOnClose = false; public PooledConnectionProxy(final PooledConnection pooledConnection) { this.delegate = pooledConnection; pooledConnection.addConnectionEventListener(this); } /** * If notifyOnClose is on, notify listeners */ @Override public void close() throws SQLException { delegate.close(); if (isNotifyOnClose()) { notifyListeners(); } } @Override public Connection getConnection() throws SQLException { return delegate.getConnection(); } /** * Remove event listeners. */ @Override public void removeConnectionEventListener(final ConnectionEventListener listener) { eventListeners.remove(listener); } /* JDBC_4_ANT_KEY_BEGIN */ @Override public void removeStatementEventListener(final StatementEventListener listener) { eventListeners.remove(listener); } /* JDBC_4_ANT_KEY_END */ public boolean isNotifyOnClose() { return notifyOnClose; } public void setNotifyOnClose(final boolean notifyOnClose) { this.notifyOnClose = 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); } } /** * Add event listeners. */ @Override public void addConnectionEventListener(final ConnectionEventListener listener) { if (!eventListeners.contains(listener)) { eventListeners.add(listener); } } /* JDBC_4_ANT_KEY_BEGIN */ @Override public void addStatementEventListener(final StatementEventListener listener) { if (!eventListeners.contains(listener)) { eventListeners.add(listener); } } /* JDBC_4_ANT_KEY_END */ /** * 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); } } /** * Generate a connection error event */ public void throwConnectionError() { final ConnectionEvent event = new ConnectionEvent(this); connectionErrorOccurred(event); } /** * Expose listeners */ public Collection getListeners() { return eventListeners; } } TestCPDSConnectionFactory.java000066400000000000000000000147351352030664000356770ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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 = null; @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 * * 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", Integer.valueOf(10)); ds.setPerUserMaxWaitMillis("userName", Long.valueOf(50)); ds.setPerUserMaxIdle("userName", Integer.valueOf(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(); } /** * 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(); assertTrue(!pcon3.equals(pcon1)); // better not get baddie back assertTrue(!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()); } @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-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(); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/datasources/TestFactory.java000066400000000000000000000043241352030664000332550ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.java000066400000000000000000000246551352030664000357700ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.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 DriverAdapterCPDS pcds; private SharedPoolDataSource spds; 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"; @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(); } /** * 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(); } private static class ThrowOnSetupDefaultsDataSource extends SharedPoolDataSource { private static final long serialVersionUID = -448025812063133259L; ThrowOnSetupDefaultsDataSource() { super(); } @Override protected void setupDefaults(final Connection connection, final String userName) throws SQLException { throw new SQLException("bang!"); } } @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 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()); } @Test public void testJndiNullProperties() { assertThrows(NullPointerException.class, () -> spds.setJndiEnvironment(null)); } @Test public void testJndiPropertiesNotInitialized() { assertNull(spds.getJndiEnvironment("name")); spds.setJndiEnvironment("name", "king"); assertEquals("king", spds.getJndiEnvironment("name")); } @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 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 testLoginTimeout() { spds.setLoginTimeout(10); assertEquals(10, spds.getLoginTimeout()); } @Test public void testLogWriterAutoInitialized() { assertNotNull(spds.getLogWriter()); } @Test public void testLogWriter() { spds.setLogWriter(new PrintWriter(System.out)); assertNotNull(spds.getLogWriter()); } @Test public void testValidationQuery() { assertNull(spds.getValidationQuery()); spds.setValidationQuery("anything"); assertEquals("anything", spds.getValidationQuery()); } @Test public void testValidationQueryWithConnectionCalled() throws SQLException { spds.getConnection(); assertNull(spds.getValidationQuery()); assertThrows(IllegalStateException.class, () -> spds.setValidationQuery("anything")); } @Test public void testValidationQueryTimeout() { assertEquals(-1, spds.getValidationQueryTimeout()); spds.setValidationQueryTimeout(10); assertEquals(10, spds.getValidationQueryTimeout()); } @Test public void testRollbackAfterValidation() { assertFalse(spds.isRollbackAfterValidation()); spds.setRollbackAfterValidation(true); assertEquals(true, spds.isRollbackAfterValidation()); } @Test public void testRollbackAfterValidationWithConnectionCalled() throws SQLException { spds.getConnection(); assertFalse(spds.isRollbackAfterValidation()); assertThrows(IllegalStateException.class, () -> spds.setRollbackAfterValidation(true)); } @Test public void testMaxConnLifetimeMillis() { assertEquals(-1, spds.getMaxConnLifetimeMillis()); spds.setMaxConnLifetimeMillis(10); assertEquals(10, spds.getMaxConnLifetimeMillis()); } @Test public void testDefaultReadOnly() { spds.setDefaultReadOnly(true); assertTrue(spds.isDefaultReadOnly()); spds.setDefaultReadOnly(false); assertFalse(spds.isDefaultReadOnly()); } @Test public void testDefaultTestOnCreate() { spds.setDefaultTestOnCreate(false); assertFalse(spds.getDefaultTestOnCreate()); spds.setDefaultTestOnCreate(true); assertTrue(spds.getDefaultTestOnCreate()); } @Test public void testDefaultSoftMinEvictableIdleTimeMillis() { spds.setDefaultSoftMinEvictableIdleTimeMillis(10); assertEquals(10, spds.getDefaultSoftMinEvictableIdleTimeMillis()); } @Test public void testDefaultMinIdle() { spds.setDefaultMinIdle(10); assertEquals(10, spds.getDefaultMinIdle()); } @Test public void testDefaultLifo() { spds.setDefaultLifo(true); assertTrue(spds.getDefaultLifo()); spds.setDefaultLifo(false); assertFalse(spds.getDefaultLifo()); } @Test public void testDefaultEvictionPolicyClassName() { spds.setDefaultEvictionPolicyClassName(Object.class.getName()); assertEquals(Object.class.getName(), spds.getDefaultEvictionPolicyClassName()); } @Test public void testDefaultBlockWhenExhausted() { spds.setDefaultBlockWhenExhausted(true); assertTrue(spds.getDefaultBlockWhenExhausted()); spds.setDefaultBlockWhenExhausted(false); assertFalse(spds.getDefaultBlockWhenExhausted()); } @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); } } TestKeyedCPDSConnectionFactory.java000066400000000000000000000145371352030664000366610ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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 = null; @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 * * 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(); } /** * 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(); assertTrue(!pcon3.equals(pcon1)); // better not get baddie back assertTrue(!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(); } } TestPerUserPoolDataSource.java000066400000000000000000002067121352030664000357660ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.assertNotNull; 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; @Override protected Connection getConnection() throws SQLException { return ds.getConnection(user,"bar"); } private DataSource ds; @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, Integer.valueOf(getMaxTotal())); tds.setPerUserMaxWaitMillis(user, Long.valueOf(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(); } /** * Switching 'u1 to 'u2' and 'p1' to 'p2' will * exhibit the bug detailed in * https://issues.apache.org/bugzilla/show_bug.cgi?id=18905 */ @Test public void testIncorrectPassword() throws Exception { // Use bad password try (Connection c = ds.getConnection("u1", "zlsafjk");){ 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(user, "bar").close(); try (Connection c = ds.getConnection("foob", "ar")) { fail("Should have caused an SQLException"); } catch (final SQLException expected) { } try (Connection c = ds.getConnection(user, "baz")){ fail("Should have generated SQLException"); } catch (final SQLException expected) { } } @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(); } @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 testClosingWithUserName() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; // open the maximum connections for (int i=0; i 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 initialized before. */ @Test public void testPerUserBlockWhenExhaustedMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map 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. 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. */ @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. * 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. * 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")); } // -- per user default auto commit @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 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); assertEquals(null, ds.getPerUserDefaultAutoCommit("key")); assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit("anonymous")); } @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 assertEquals(null, ds.getPerUserDefaultAutoCommit("missingkey")); } @Test public void testPerUserDefaultAutoCommitWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultAutoCommit(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit(user)); } @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 testPerUserDefaultAutoCommitWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultAutoCommit("whatismyuseragain?", Boolean.FALSE); // TODO this is not consistent with the other methods assertEquals(null, ds.getPerUserDefaultAutoCommit("missingkey")); } // -- per user default read only @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 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); assertEquals(null, ds.getPerUserDefaultReadOnly("key")); assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly("anonymous")); } @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 assertEquals(null, ds.getPerUserDefaultReadOnly("missingkey")); } @Test public void testPerUserDefaultReadOnlyWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultReadOnly(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly(user)); } @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 testPerUserDefaultReadOnlyWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultReadOnly("whatismyuseragain?", Boolean.FALSE); // TODO this is not consistent with the other methods assertEquals(null, ds.getPerUserDefaultReadOnly("missingkey")); } // -- per user default transaction isolation @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 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 assertEquals(null, ds.getPerUserDefaultTransactionIsolation("key")); assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation("anonymous")); } @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 assertEquals(null, ds.getPerUserDefaultTransactionIsolation("missingkey")); } @Test public void testPerUserDefaultTransactionIsolationWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultTransactionIsolation(user, 0); assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation(user)); } @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 testPerUserDefaultTransactionIsolationWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultTransactionIsolation("whatismyuseragain?", 0); // TODO this is not consistent with the other methods assertEquals(null, ds.getPerUserDefaultTransactionIsolation("missingkey")); } // -- per user eviction policy class name @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 testPerUserEvictionPolicyClassNameMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", "bar"); ds.setPerUserEvictionPolicyClassName(values); assertEquals("bar", ds.getPerUserEvictionPolicyClassName("key")); values = new HashMap<>(); values.put("anonymous", "bar"); ds.setPerUserEvictionPolicyClassName(values); assertEquals(ds.getDefaultEvictionPolicyClassName(), ds.getPerUserEvictionPolicyClassName("key")); assertEquals("bar", ds.getPerUserEvictionPolicyClassName("anonymous")); } @Test public void 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 testPerUserEvictionPolicyClassNameWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserEvictionPolicyClassName(user, "bar"); assertEquals("bar", ds.getPerUserEvictionPolicyClassName(user)); } @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 testPerUserEvictionPolicyClassNameWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserEvictionPolicyClassName("whatismyuseragain?", "bar"); assertEquals(ds.getDefaultEvictionPolicyClassName(), ds.getPerUserEvictionPolicyClassName("missingkey")); } // -- per user lifo @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 testPerUserLifoMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserLifo(values); assertEquals(Boolean.FALSE, ds.getPerUserLifo("key")); values = new HashMap<>(); values.put("anonymous", Boolean.FALSE); ds.setPerUserLifo(values); assertEquals(ds.getDefaultLifo(), ds.getPerUserLifo("key")); assertEquals(Boolean.FALSE, ds.getPerUserLifo("anonymous")); } @Test public void 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 testPerUserLifoWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserLifo(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserLifo(user)); } @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 testPerUserLifoWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserLifo("whatismyuseragain?", Boolean.FALSE); assertEquals(ds.getDefaultLifo(), ds.getPerUserLifo("missingkey")); } // -- per user max idle @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 testPerUserMaxIdleMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserMaxIdle(values); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle("key")); values = new HashMap<>(); values.put("anonymous", 0); ds.setPerUserMaxIdle(values); assertEquals((Integer) ds.getDefaultMaxIdle(), (Integer) ds.getPerUserMaxIdle("key")); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle("anonymous")); } @Test public void 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 testPerUserMaxIdleWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxIdle(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle(user)); } @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 testPerUserMaxIdleWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxIdle("whatismyuseragain?", 0); assertEquals((Integer) ds.getDefaultMaxIdle(), (Integer) ds.getPerUserMaxIdle("missingkey")); } // -- per user max total @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 testPerUserMaxTotalMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserMaxTotal(values); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal("key")); values = new HashMap<>(); values.put("anonymous", 0); ds.setPerUserMaxTotal(values); assertEquals((Integer) ds.getDefaultMaxTotal(), (Integer) ds.getPerUserMaxTotal("key")); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal("anonymous")); } @Test public void 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 testPerUserMaxTotalWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxTotal(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal(user)); } @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 testPerUserMaxTotalWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxTotal("whatismyuseragain?", 0); assertEquals((Integer) ds.getDefaultMaxTotal(), (Integer) ds.getPerUserMaxTotal("missingkey")); } // -- per user max wait millis @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 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")); } @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 testPerUserMaxWaitMillisWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxWaitMillis(user, 0l); assertEquals(0l, ds.getPerUserMaxWaitMillis(user)); } @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 testPerUserMaxWaitMillisWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxWaitMillis("whatismyuseragain?", 0l); assertEquals(ds.getDefaultMaxWaitMillis(), ds.getPerUserMaxWaitMillis("missingkey")); } // -- per user min evictable idle time millis @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 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 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 testPerUserMinEvictableIdleTimeMillisWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMinEvictableIdleTimeMillis(user, 0l); assertEquals(0l, ds.getPerUserMinEvictableIdleTimeMillis(user)); } @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 testPerUserMinEvictableIdleTimeMillisWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMinEvictableIdleTimeMillis("whatismyuseragain?", 0l); assertEquals(ds.getDefaultMinEvictableIdleTimeMillis(), ds.getPerUserMinEvictableIdleTimeMillis("missingkey")); } // -- per user min idle @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 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 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 testPerUserMinIdleWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMinIdle(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle(user)); } @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 testPerUserMinIdleWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMinIdle("whatismyuseragain?", 0); assertEquals((Integer) ds.getDefaultMinIdle(), (Integer) ds.getPerUserMinIdle("missingkey")); } // -- per user num tests per eviction run @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 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 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 testPerUserNumTestsPerEvictionRunWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserNumTestsPerEvictionRun(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun(user)); } @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 testPerUserNumTestsPerEvictionRunWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserNumTestsPerEvictionRun("whatismyuseragain?", 0); assertEquals((Integer) ds.getDefaultNumTestsPerEvictionRun(), (Integer) ds.getPerUserNumTestsPerEvictionRun("missingkey")); } // -- per user soft min evictable idle time millis @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 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 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 testPerUserSoftMinEvictableIdleTimeMillisWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserSoftMinEvictableIdleTimeMillis(user, 0l); assertEquals(0l, ds.getPerUserSoftMinEvictableIdleTimeMillis(user)); } @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 testPerUserSoftMinEvictableIdleTimeMillisWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserSoftMinEvictableIdleTimeMillis("whatismyuseragain?", 0l); assertEquals(ds.getDefaultSoftMinEvictableIdleTimeMillis(), ds.getPerUserSoftMinEvictableIdleTimeMillis("missingkey")); } // -- per user test on borrow @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 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 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 testPerUserTestOnBorrowWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnBorrow(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow(user)); } @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 testPerUserTestOnBorrowWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnBorrow("whatismyuseragain?", Boolean.FALSE); assertEquals(ds.getDefaultTestOnBorrow(), ds.getPerUserTestOnBorrow("missingkey")); } // -- per user test on create @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 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 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 testPerUserTestOnCreateWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnCreate(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate(user)); } @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 testPerUserTestOnCreateWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnCreate("whatismyuseragain?", Boolean.FALSE); assertEquals(ds.getDefaultTestOnCreate(), ds.getPerUserTestOnCreate("missingkey")); } // -- per user test on return @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 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 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 testPerUserTestOnReturnWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnReturn(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn(user)); } @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 testPerUserTestOnReturnWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnReturn("whatismyuseragain?", Boolean.FALSE); assertEquals(ds.getDefaultTestOnReturn(), ds.getPerUserTestOnReturn("missingkey")); } // -- per user test while idle @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 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 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 testPerUserTestWhileIdleWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestWhileIdle(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle(user)); } @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 testPerUserTestWhileIdleWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestWhileIdle("whatismyuseragain?", Boolean.FALSE); assertEquals(ds.getDefaultTestWhileIdle(), ds.getPerUserTestWhileIdle("missingkey")); } // -- per user time between eviction runs millis @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 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 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 testPerUserTimeBetweenEvictionRunsMillisWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTimeBetweenEvictionRunsMillis(user, 0l); assertEquals(0l, ds.getPerUserTimeBetweenEvictionRunsMillis(user)); } @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 testPerUserTimeBetweenEvictionRunsMillisWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTimeBetweenEvictionRunsMillis("whatismyuseragain?", 0l); assertEquals(ds.getDefaultTimeBetweenEvictionRunsMillis(), ds.getPerUserTimeBetweenEvictionRunsMillis("missingkey")); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/datasources/TestPoolKey.java000066400000000000000000000044451352030664000332340ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF 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.java000066400000000000000000000617601352030664000356110ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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 { @Override protected Connection getConnection() throws Exception { return ds.getConnection("foo","bar"); } private DriverAdapterCPDS pcds; private DataSource ds; @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; } /** * 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 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(); } @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 testClosingWithUserName() 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(new Runnable() { @Override public void run() { for (final SharedPoolDataSource dataSource : dataSources) { dataSource.setDataSourceName("a"); } } }); final Thread t2 = new Thread(new Runnable() { @Override public void run() { 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 } } } TestUserPassKey.java000066400000000000000000000052411352030664000340040ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import org.apache.commons.dbcp2.Utils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests for UserPassKey. * @since 2.5.0 */ public class TestUserPassKey { private UserPassKey userPassKey; private UserPassKey anotherUserPassKey; @BeforeEach public void setUp() { userPassKey = new UserPassKey("user", "pass"); anotherUserPassKey = new UserPassKey((String) null, ""); } @Test public void testGettersAndSetters() { assertEquals("user", userPassKey.getUsername()); assertEquals("pass", userPassKey.getPassword()); assertTrue(Arrays.equals(Utils.toCharArray("pass"), userPassKey.getPasswordCharArray())); } @Test public void testEquals() { assertEquals(new UserPassKey("user"), new UserPassKey("user", (char[]) null)); assertEquals(userPassKey, userPassKey); assertNotEquals(userPassKey, null); assertNotEquals(userPassKey, new Object()); assertNotEquals(new UserPassKey(null), userPassKey); assertEquals(new UserPassKey(null), new UserPassKey(null)); assertNotEquals(new UserPassKey("user", "pass"), new UserPassKey("foo", "pass")); } @Test public void testHashcode() { assertEquals(userPassKey.hashCode(), new UserPassKey("user", "pass").hashCode()); assertNotEquals(userPassKey.hashCode(), anotherUserPassKey.hashCode()); } @Test public void testToString() { assertEquals(userPassKey.toString(), new UserPassKey("user", "pass").toString()); assertNotEquals(userPassKey.toString(), anotherUserPassKey.toString()); } } commons-dbcp-commons-dbcp-2.7.0/src/test/java/org/apache/commons/dbcp2/managed/000077500000000000000000000000001352030664000272175ustar00rootroot00000000000000TestBasicManagedDataSource.java000066400000000000000000000246701352030664000351250ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple; import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionSynchronizationRegistryImple; import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.dbcp2.TestBasicDataSource; import org.apache.geronimo.transaction.manager.TransactionManagerImpl; import org.h2.Driver; import org.h2.jdbcx.JdbcDataSource; import org.junit.jupiter.api.Test; import javax.sql.XADataSource; import javax.transaction.Synchronization; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.xa.XAException; import java.sql.Connection; import java.sql.SQLException; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; /** * TestSuite for BasicManagedDataSource */ public class TestBasicManagedDataSource extends TestBasicDataSource { @Override protected BasicDataSource createDataSource() throws Exception { final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource(); basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); return basicManagedDataSource; } /** * JIRA: DBCP-294 * Verify that PoolableConnections created by BasicManagedDataSource unregister themselves * when reallyClosed. */ @Test public void testReallyClose() throws Exception { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver"); basicManagedDataSource.setUsername("userName"); basicManagedDataSource.setPassword("password"); basicManagedDataSource.setMaxIdle(1); // Create two connections final ManagedConnection conn = (ManagedConnection) basicManagedDataSource.getConnection(); assertNotNull(basicManagedDataSource.getTransactionRegistry().getXAResource(conn)); final ManagedConnection conn2 = (ManagedConnection) basicManagedDataSource.getConnection(); conn2.close(); // Return one connection to the pool conn.close(); // No room at the inn - this will trigger reallyClose(), which should unregister try { basicManagedDataSource.getTransactionRegistry().getXAResource(conn); fail("Expecting SQLException - XAResources orphaned"); } catch (final SQLException ex) { // expected } conn2.close(); } } @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()); } } @Test public void testTransactionManagerNotSet() throws SQLException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { assertThrows(SQLException.class, basicManagedDataSource::createConnectionFactory); } } @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 testCreateXaDataSourceNewInstance() throws SQLException, XAException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setXADataSource(JdbcDataSource.class.getCanonicalName()); basicManagedDataSource.setDriverClassName(Driver.class.getName()); basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); assertNotNull(basicManagedDataSource.createConnectionFactory()); } } @Test public void testCreateXaDataSourceNoInstanceSetAndNoDataSource() throws SQLException, XAException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver"); basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); assertNotNull(basicManagedDataSource.createConnectionFactory()); } } @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 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 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()); } } @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 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()); } } } } @Override public void afterCompletion(final int i) { } }); tm.commit(); } } } TestConnectionWithNarayana.java000066400000000000000000000212631352030664000352550ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 String PAYLOAD; private static final String DROP_STMT = "DROP TABLE TEST_DATA"; static { final StringBuffer sb = new StringBuffer(); sb.append("Start"); sb.append("payload"); for (int i = 0; i < 10000; i++) { sb.append("..."); sb.append(String.valueOf(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(); } } } @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()); } @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()); } } @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(); } } }TestDataSourceXAConnectionFactory.java000066400000000000000000000077251352030664000365110ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 { protected BasicManagedDataSource bmds; public 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); } /** * Delegates everything to the BasicDataSource (ds field), except for * getXAConnection which creates a BasicXAConnection. */ public class XADataSourceHandle implements InvocationHandler { @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 Integer.valueOf(System.identityHashCode(proxy)); } if (methodName.equals("equals")) { return Boolean.valueOf(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 XAConnection getXAConnection() throws SQLException { return new TesterBasicXAConnection(ds.getConnection(), closeCounter); } } /** * 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.java000066400000000000000000000452001352030664000336770ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 Connection conn; private LocalXAConnectionFactory.LocalXAResource resource; @BeforeEach public void setUp() { conn = new TestConnection(); resource = new LocalXAConnectionFactory.LocalXAResource(conn); } @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 testIsSame() { assertTrue(resource.isSameRM(resource)); assertFalse(resource.isSameRM(new LocalXAConnectionFactory.LocalXAResource(conn))); } @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 testStartNoFlagResumeButDifferentXid() throws XAException { resource.start(new TestXid(), XAResource.TMNOFLAGS); assertThrows(XAException.class, () -> resource.start(new TestXid(), XAResource.TMRESUME)); } @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 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 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)); } @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 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 testForget() throws XAException { final Xid xid = new TestXid(); resource.start(xid, XAResource.TMNOFLAGS); resource.forget(xid); assertNull(resource.getXid()); } @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()); } /** * 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()); } /** * 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 testStartFailsWhenCannotSetAutoCommit() { final Xid xid = new TestXid(); ((TestConnection) conn).throwWhenSetAutoCommit = true; assertThrows(XAException.class, () -> resource.start(xid, XAResource.TMNOFLAGS)); } @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 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 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 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 testRollbackMissingXid() { assertThrows(NullPointerException.class, () -> resource.rollback(null)); } @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 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); } private static class TestConnection implements Connection { public boolean throwWhenGetAutoCommit = false; public boolean throwWhenSetAutoCommit = false; boolean autoCommit = false; boolean readOnly = false; public boolean committed = false; public boolean rolledback = false; public boolean closed = false; @Override public T unwrap(final Class iface) throws SQLException { return null; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { return false; } @Override public Statement createStatement() throws SQLException { return null; } @Override public PreparedStatement prepareStatement(final String sql) throws SQLException { return null; } @Override public CallableStatement prepareCall(final String sql) throws SQLException { return null; } @Override public String nativeSQL(final String sql) throws SQLException { return null; } @Override public void setAutoCommit(final boolean autoCommit) throws SQLException { if (throwWhenSetAutoCommit) { throw new SQLException(); } this.autoCommit = autoCommit; } @Override public boolean getAutoCommit() throws SQLException { if (throwWhenGetAutoCommit) { throw new SQLException(); } return autoCommit; } @Override public void commit() throws SQLException { committed = true; } @Override public void rollback() throws SQLException { rolledback = true; } @Override public void close() throws SQLException { closed = true; } @Override public boolean isClosed() throws SQLException { return closed; } @Override public DatabaseMetaData getMetaData() throws SQLException { return null; } @Override public void setReadOnly(final boolean readOnly) throws SQLException { this.readOnly = readOnly; } @Override public boolean isReadOnly() throws SQLException { return readOnly; } @Override public void setCatalog(final String catalog) throws SQLException { } @Override public String getCatalog() throws SQLException { return null; } @Override public void setTransactionIsolation(final int level) throws SQLException { } @Override public int getTransactionIsolation() throws SQLException { return 0; } @Override public SQLWarning getWarnings() throws SQLException { return null; } @Override public void clearWarnings() throws SQLException { } @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(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) throws SQLException { return null; } @Override public Map> getTypeMap() throws SQLException { return null; } @Override public void setTypeMap(final Map> map) throws SQLException { } @Override public void setHoldability(final int holdability) throws SQLException { } @Override public int getHoldability() throws SQLException { return 0; } @Override public Savepoint setSavepoint() throws SQLException { return null; } @Override public Savepoint setSavepoint(final String name) throws SQLException { return null; } @Override public void rollback(final Savepoint savepoint) throws SQLException { } @Override public void releaseSavepoint(final Savepoint savepoint) throws SQLException { } @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) 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 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, final int autoGeneratedKeys) 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 Clob createClob() throws SQLException { return null; } @Override public Blob createBlob() throws SQLException { return null; } @Override public NClob createNClob() throws SQLException { return null; } @Override public SQLXML createSQLXML() throws SQLException { return null; } @Override public boolean isValid(final int timeout) throws SQLException { return false; } @Override public void setClientInfo(final String name, final String value) throws SQLClientInfoException { } @Override public void setClientInfo(final Properties properties) throws SQLClientInfoException { } @Override public String getClientInfo(final String name) throws SQLException { return null; } @Override public Properties getClientInfo() throws SQLException { return null; } @Override public Array createArrayOf(final String typeName, final Object[] elements) throws SQLException { return null; } @Override public Struct createStruct(final String typeName, final Object[] attributes) throws SQLException { return null; } @Override public void setSchema(final String schema) throws SQLException { } @Override public String getSchema() throws SQLException { return null; } @Override public void abort(final Executor executor) throws SQLException { } @Override public void setNetworkTimeout(final Executor executor, final int milliseconds) throws SQLException { } @Override public int getNetworkTimeout() throws SQLException { return 0; } } private static class TestXid implements Xid { @Override public byte[] getBranchQualifier() { return null; } @Override public int getFormatId() { return 0; } @Override public byte[] getGlobalTransactionId() { return null; } } } TestManagedConnection.java000066400000000000000000000166541352030664000342330ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.*; 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.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 { protected PoolingDataSource ds = null; private GenericObjectPool pool = null; protected TransactionManager transactionManager; @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("user", "userName"); properties.setProperty("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(); } public Connection getConnection() throws Exception { return ds.getConnection(); } @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()); } 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(); } } } 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; } } } /** * Transaction that always fails enlistResource. */ private 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 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(); } @Override public synchronized boolean enlistResource(final XAResource xaRes) { return false; } } } TestManagedDataSource.java000066400000000000000000000255751352030664000341700ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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 org.apache.commons.dbcp2.ConnectionFactory; 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; import javax.transaction.TransactionManager; import java.sql.Connection; import java.util.Properties; /** * TestSuite for ManagedDataSource without a transaction in progress. */ public class TestManagedDataSource extends TestConnectionPool { @Override protected Connection getConnection() throws Exception { return ds.getConnection(); } protected PoolingDataSource ds = null; protected GenericObjectPool pool = null; protected TransactionManager transactionManager; @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("user", "userName"); properties.setProperty("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(); } /** * 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(); assertFalse(connectionA.equals(connectionB)); assertFalse(connectionB.equals(connectionA)); assertFalse(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate())); assertFalse(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate())); connectionA.close(); connectionB.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 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 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(); } } /* * JIRA: DBCP-198 */ @Test public void testManagedConnectionEqualsReflexive() throws Exception { final Connection con = ds.getConnection(); final Connection con2 = con; assertTrue(con2.equals(con)); assertTrue(con.equals(con2)); con.close(); } @Test public void testManagedConnectionEqualsFail() throws Exception { final Connection con1 = ds.getConnection(); final Connection con2 = ds.getConnection(); assertFalse(con1.equals(con2)); con1.close(); con2.close(); } @Test public void testManagedConnectionEqualsNull() throws Exception { final Connection con1 = ds.getConnection(); final Connection con2 = null; assertFalse(con1.equals(con2)); con1.close(); } @Test public void testManagedConnectionEqualsType() throws Exception { final Connection con1 = ds.getConnection(); final Integer con2 = Integer.valueOf(0); assertFalse(con1.equals(con2)); con1.close(); } @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); assertFalse(con2.equals(con)); assertTrue(con.innermostDelegateEquals(con2.getInnermostDelegate())); assertTrue(con2.innermostDelegateEquals(inner)); assertFalse(con.equals(con2)); } @Test public void testNestedConnections() throws Exception { transactionManager.begin(); Connection c1 = null; Connection c2 = null; c1 = newConnection(); c2 = newConnection(); transactionManager.commit(); c1.close(); c2.close(); } @Test public void testTransactionRegistryNotInitialized() throws Exception { try (ManagedDataSource ds = new ManagedDataSource<>(pool, null)) { assertThrows(IllegalStateException.class, ds::getConnection); } } @Test public void testSetTransactionRegistryAlreadySet() { final ManagedDataSource managed = (ManagedDataSource) ds; assertThrows(IllegalStateException.class, () -> managed.setTransactionRegistry(null)); } @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)); } } } TestManagedDataSourceInTx.java000066400000000000000000000377571352030664000350000ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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 { @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(); } /** * @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 testNestedConnections() { // Not supported } @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 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 beforeCompletion() { // empty } @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"); } } }); connection.close(); transactionManager.commit(); } @Test public void testDoubleReturn() throws Exception { transactionManager.getTransaction().registerSynchronization(new Synchronization() { private ManagedConnection conn; @Override public void beforeCompletion() { try { conn = (ManagedConnection) ds.getConnection(); assertNotNull(conn); } catch (final SQLException e) { fail("Could not get connection"); } } @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()); } }); 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()); } @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 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(); } @Override @Test public void testSharedConnection() throws Exception { final DelegatingConnection connectionA = (DelegatingConnection) newConnection(); final DelegatingConnection connectionB = (DelegatingConnection) newConnection(); assertFalse(connectionA.equals(connectionB)); assertFalse(connectionB.equals(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 assertFalse(connectionA.equals(connectionB)); assertFalse(connectionB.equals(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 assertFalse(connectionA.equals(connectionB)); assertFalse(connectionB.equals(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 assertFalse(connectionA.equals(connectionB)); assertFalse(connectionB.equals(connectionA)); assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate())); assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate())); connectionA.close(); connectionB.close(); } @Test public void testCloseInTransaction() throws Exception { final DelegatingConnection connectionA = (DelegatingConnection) newConnection(); final DelegatingConnection connectionB = (DelegatingConnection) newConnection(); assertFalse(connectionA.equals(connectionB)); assertFalse(connectionB.equals(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"); } @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(); } @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(); } @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(); } // 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 @Test public void testConnectionReturnOnCommit() throws Exception { // override with no-op test return; } } TestPoolableManagedConnection.java000066400000000000000000000135611352030664000357030ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.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("user", "userName"); properties.setProperty("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.java000066400000000000000000000271331352030664000350460ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.dbcp2.DelegatingConnection; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.TesterClassLoader; 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; import javax.sql.XAConnection; import javax.sql.XADataSource; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.InvalidTransactionException; 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 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 static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; public class TestSynchronizationOrder { private boolean transactionManagerRegistered; private boolean transactionSynchronizationRegistryRegistered; private TransactionManager transactionManager; private TransactionSynchronizationRegistry transactionSynchronizationRegistry; private XADataSource xads; private BasicManagedDataSource bmds; private BasicDataSource bds; @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); } } } @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); } } } @AfterEach public void tearDown() throws SQLException { bds.close(); bmds.close(); } @BeforeEach public void setup() { transactionManager = new TransactionManager() { @Override public void begin() throws NotSupportedException, SystemException { } @Override public void commit() throws HeuristicMixedException, HeuristicRollbackException, IllegalStateException, RollbackException, SecurityException, SystemException { } @Override public int getStatus() throws SystemException { return 0; } @Override public Transaction getTransaction() throws SystemException { return new Transaction() { @Override public void commit() throws HeuristicMixedException, HeuristicRollbackException, RollbackException, SecurityException, SystemException { } @Override public boolean delistResource(final XAResource xaResource, final int i) throws IllegalStateException, SystemException { return false; } @Override public boolean enlistResource(final XAResource xaResource) throws IllegalStateException, RollbackException, SystemException { // Called and used return true; } @Override public int getStatus() throws SystemException { return 0; } @Override public void registerSynchronization(final Synchronization synchronization) throws IllegalStateException, RollbackException, SystemException { transactionManagerRegistered = true; } @Override public void rollback() throws IllegalStateException, SystemException { } @Override public void setRollbackOnly() throws IllegalStateException, SystemException { } }; } @Override public void resume(final Transaction transaction) throws IllegalStateException, InvalidTransactionException, SystemException { } @Override public void rollback() throws IllegalStateException, SecurityException, SystemException { } @Override public void setRollbackOnly() throws IllegalStateException, SystemException { } @Override public void setTransactionTimeout(final int i) throws SystemException { } @Override public Transaction suspend() throws SystemException { return null; } }; transactionSynchronizationRegistry = new TransactionSynchronizationRegistry() { @Override public Object getResource(final Object o) { 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 o, final Object o1) { } @Override public void registerInterposedSynchronization(final Synchronization synchronization) { transactionSynchronizationRegistryRegistered = true; } @Override public void setRollbackOnly() { } }; 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(new String[]{"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() { @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 Integer.valueOf(System.identityHashCode(proxy)); } if (methodName.equals("equals")) { return Boolean.valueOf(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(); } } protected XAConnection getXAConnection() throws SQLException { return new TesterBasicXAConnection(bds.getConnection(), closeCounter); } }; xads = (XADataSource) Proxy.newProxyInstance( TestSynchronizationOrder.class.getClassLoader(), new Class[]{XADataSource.class}, handle); bmds.setXaDataSourceInstance(xads); } } TestTransactionContext.java000066400000000000000000000053241352030664000345010ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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.sql.SQLException; import javax.transaction.xa.XAResource; import org.junit.jupiter.api.Test; import org.apache.geronimo.transaction.manager.TransactionManagerImpl; import org.apache.geronimo.transaction.manager.TransactionImpl; import static org.junit.jupiter.api.Assertions.assertThrows; /** * TestSuite for TransactionContext */ public class TestTransactionContext { /** * 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)); } } } /** * Transaction that always fails enlistResource. */ private class UncooperativeTransaction extends TransactionImpl { public UncooperativeTransaction() { super(null, null); } @Override public synchronized boolean enlistResource(final XAResource xaRes) { return false; } } } TesterBasicXAConnection.java000066400000000000000000000157671352030664000345040ustar00rootroot00000000000000commons-dbcp-commons-dbcp-2.7.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 { public Connection conn; public ConnectionHandle handle; public List listeners = new LinkedList<>(); public AtomicInteger closeCounter; public TesterBasicXAConnection(final Connection conn, final AtomicInteger closeCounter) { this.conn = conn; this.closeCounter = closeCounter; } public TesterBasicXAConnection(final Connection conn) { this(conn, 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); final Connection proxy = (Connection) Proxy.newProxyInstance( getClass().getClassLoader(), new Class[] { Connection.class }, handle); return proxy; } protected void closeHandle() throws SQLException { handle.closeHandle(); if (!conn.getAutoCommit()) { try { conn.rollback(); } catch (final SQLException e) { e.printStackTrace(); } } handle = null; } @Override public void close() throws SQLException { if (handle != null) { closeHandle(); } try { conn.close(); if (closeCounter != null) { closeCounter.incrementAndGet(); } } finally { conn = null; } } @Override public XAResource getXAResource() throws SQLException { return new LocalXAConnectionFactory.LocalXAResource(conn); } @Override public void addConnectionEventListener( final ConnectionEventListener connectionEventListener) { listeners.add(connectionEventListener); } @Override public void removeConnectionEventListener( final ConnectionEventListener connectionEventListener) { listeners.remove(connectionEventListener); } @Override public void addStatementEventListener(final StatementEventListener listener) { throw new UnsupportedOperationException(); } @Override public void removeStatementEventListener(final StatementEventListener listener) { throw new UnsupportedOperationException(); } 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); } } /** * Delegates everything to a Connection, except for close() which just * notifies the parent XAConnection. */ public static class ConnectionHandle implements InvocationHandler { public Connection conn; public TesterBasicXAConnection xaconn; public ConnectionHandle(final Connection conn, final TesterBasicXAConnection xaconn) { this.conn = conn; this.xaconn = xaconn; } @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 Integer.valueOf(System.identityHashCode(proxy)); } if (methodName.equals("equals")) { return Boolean.valueOf(proxy == args[0]); } if (methodName.equals("isClosed")) { return Boolean.valueOf(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; } } protected Object close() throws SQLException { if (conn != null) { conn.clearWarnings(); conn = null; xaconn.handle = null; xaconn.notifyConnectionClosed(); } return null; } public void closeHandle() { conn = null; } } } commons-dbcp-commons-dbcp-2.7.0/test-jar.xml000066400000000000000000000164141352030664000207400ustar00rootroot00000000000000 Checking dependencies