commons-pool-1.6-src/build.xml100644 0 0 20135 11701070263 13555 0ustar 0 0 commons-pool-1.6-src/checkstyle.xml100644 0 0 6405 11701070263 14600 0ustar 0 0 commons-pool-1.6-src/findbugs-exclude-filter.xml100644 0 0 4433 11701070263 17154 0ustar 0 0 commons-pool-1.6-src/license-header.txt100644 0 0 1463 11701070262 15327 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ commons-pool-1.6-src/LICENSE.txt100644 0 0 26450 11701070262 13564 0ustar 0 0 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-pool-1.6-src/NOTICE.txt100644 0 0 262 11701070262 13414 0ustar 0 0 Apache Commons Pool Copyright 2001-2012 The Apache Software Foundation This product includes software developed by The Apache Software Foundation (http://www.apache.org/). commons-pool-1.6-src/pom.xml100644 0 0 24072 11701070306 13253 0ustar 0 0 org.apache.commons commons-parent 22 4.0.0 commons-pool commons-pool 1.6 Commons Pool 2001 Commons Object Pooling Library http://commons.apache.org/pool/ jira http://issues.apache.org/jira/browse/POOL scm:svn:http://svn.apache.org/repos/asf/commons/proper/pool/trunk scm:svn:https://svn.apache.org/repos/asf/commons/proper/pool/trunk http://svn.apache.org/viewvc/commons/proper/pool/trunk Morgan Delagrange morgand Geir Magnusson geirm Craig McClanahan craigmcc Rodney Waldhoff rwaldhoff David Weinrich dweinr1 Dirk Verbeeck dirkv Robert Burrell Donkin rdonkin Apache Software Foundation Sandy McArthur sandymac Apache Software Foundation Gary Gregory ggregory Apache Software Foundation Todd Carmichael toddc@concur.com junit junit 4.10 test UTF-8 UTF-8 1.5 1.5 pool 1.6 POOL 12310488 apache.website Apache Commons Site ${commons.deployment.protocol}://people.apache.org/www/commons.apache.org/${commons.componentid} org.apache.maven.plugins maven-site-plugin 3.0 org.apache.maven.wagon wagon-ssh 2.2 src/java src/test org.apache.maven.plugins maven-surefire-plugin **/Test*.java **/Test*$*.java org/apache/commons/pool/impl/TestSoftRefOutOfMemory.java maven-assembly-plugin src/assembly/bin.xml src/assembly/src.xml gnu org.apache.maven.plugins maven-source-plugin true true org.apache org.apache.maven.plugins maven-javadoc-plugin true org.apache org.apache.maven.plugins maven-changes-plugin 2.6 ${basedir}/src/changes/changes.xml %URL%/%ISSUE% src/template changes-report org.codehaus.mojo clirr-maven-plugin 2.3 1.5.7 info org.apache.maven.plugins maven-checkstyle-plugin 2.1 ${basedir}/checkstyle.xml false ${basedir}/license-header.txt org.codehaus.mojo findbugs-maven-plugin 2.3.3 Normal Default ${basedir}/findbugs-exclude-filter.xml org.codehaus.mojo cobertura-maven-plugin 2.5.1 org.apache.maven.plugins maven-pmd-plugin 2.5 1.5 org.codehaus.mojo taglist-maven-plugin 2.4 TODO NOPMD NOTE commons-pool-1.6-src/README.txt100644 0 0 142 11701070263 13366 0ustar 0 0 See http://commons.apache.org/pool/ for additional and up-to-date information on Commons Pool. commons-pool-1.6-src/RELEASE-NOTES.txt100644 0 0 765 11701070262 14411 0ustar 0 0 commons-pool-1.6 RELEASE NOTES This release adds support for Java 5 generics and therefore requires Java 5 for source compatibility. This release is binary compatible with 1.5.7. The only change in this version is: o Support Java 1.5 Generics in version 1.x. Issue: POOL-208. For complete information on commons-pool, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the commons-pool website: http://commons.apache.org/pool/ commons-pool-1.6-src/src/ 40755 0 0 0 11701070263 12405 5ustar 0 0 commons-pool-1.6-src/src/assembly/ 40755 0 0 0 11701070262 14223 5ustar 0 0 commons-pool-1.6-src/src/changes/ 40755 0 0 0 11701070263 14015 5ustar 0 0 commons-pool-1.6-src/src/java/ 40755 0 0 0 11701070262 13325 5ustar 0 0 commons-pool-1.6-src/src/java/org/ 40755 0 0 0 11701070262 14114 5ustar 0 0 commons-pool-1.6-src/src/java/org/apache/ 40755 0 0 0 11701070262 15335 5ustar 0 0 commons-pool-1.6-src/src/java/org/apache/commons/ 40755 0 0 0 11701070262 17010 5ustar 0 0 commons-pool-1.6-src/src/java/org/apache/commons/pool/ 40755 0 0 0 11701070263 17762 5ustar 0 0 commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/ 40755 0 0 0 11701070262 20722 5ustar 0 0 commons-pool-1.6-src/src/site/ 40755 0 0 0 11701070263 13351 5ustar 0 0 commons-pool-1.6-src/src/site/resources/ 40755 0 0 0 11701070263 15363 5ustar 0 0 commons-pool-1.6-src/src/site/resources/images/ 40755 0 0 0 11701070263 16630 5ustar 0 0 commons-pool-1.6-src/src/site/resources/images/uml/ 40755 0 0 0 11701070263 17425 5ustar 0 0 commons-pool-1.6-src/src/site/xdoc/ 40755 0 0 0 11701070263 14306 5ustar 0 0 commons-pool-1.6-src/src/site/xdoc/guide/ 40755 0 0 0 11701070263 15403 5ustar 0 0 commons-pool-1.6-src/src/template/ 40755 0 0 0 11701070263 14220 5ustar 0 0 commons-pool-1.6-src/src/test/ 40755 0 0 0 11701070262 13363 5ustar 0 0 commons-pool-1.6-src/src/test/org/ 40755 0 0 0 11701070262 14152 5ustar 0 0 commons-pool-1.6-src/src/test/org/apache/ 40755 0 0 0 11701070262 15373 5ustar 0 0 commons-pool-1.6-src/src/test/org/apache/commons/ 40755 0 0 0 11701070262 17046 5ustar 0 0 commons-pool-1.6-src/src/test/org/apache/commons/pool/ 40755 0 0 0 11701070262 20017 5ustar 0 0 commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/ 40755 0 0 0 11701070262 20760 5ustar 0 0 commons-pool-1.6-src/src/test/org/apache/commons/pool/performance/ 40755 0 0 0 11701070262 22320 5ustar 0 0 commons-pool-1.6-src/src/assembly/bin.xml100644 0 0 3135 11701070262 15614 0ustar 0 0 bin tar.gz zip false LICENSE.txt NOTICE.txt RELEASE-NOTES.txt target *.jar target/site/apidocs apidocs commons-pool-1.6-src/src/assembly/src.xml100644 0 0 3203 11701070262 15627 0ustar 0 0 src tar.gz zip ${project.artifactId}-${project.version}-src build.xml checkstyle.xml LICENSE.txt license-header.txt NOTICE.txt pom.xml README.txt RELEASE-NOTES.txt findbugs-exclude-filter.xml src commons-pool-1.6-src/src/changes/changes.xml100644 0 0 42466 11701070263 16300 0ustar 0 0 Commons Pool Changes Support Java 1.5 Generics in version 1.x. Awaken threads waiting on borrowObject when a pool has been closed and have them throw IllegalStateException. Prior to the fix for this issue, threads waiting in borrowObject when close was invoked on GOP or GKOP would block indefinitely. Corrected total internal processing counter update in destroy. Prior to the fix for this issue, clear(key) was leaking capacity associated with elements in the pool being cleared. Correctly handle an InterruptedException when waiting for an object from the pool. Only stop tracking objects for a key when there are no idle objects, no active objects and no objects being processed. Make BaseObjectPool.isClosed() public. Correct bug that could lead to inappropriate pool starvation when evict() and borrowObject() are called concurrently. Fix performance issues when object destruction has latency. In preparation for pool 2.0, deprecated direct access to protected fields and setFactory methods. In pool 2.0, pool object factories will be immutable. Made GenericKeyedObjectPool._minIdle volatile. Made the default context class loader for the eviction thread the same loader that loads the library to prevent memory leaks in multiple class loader environments. GenericKeyedObjectPool.destroy could use entrySet() rather than keySet() followed by get() GenericObjectPool and GenericKeyedObjectPool setFactory methods destroy idle instances in the pool by contract. Prior to the fix for this issue, newly set factories were being used to destroy idle instances, rather than the factories used to create them. The setFactory methods have also been deprecated, to be removed in version 2.0. ObjectPool classes can ignore Throwable. Added consistent handling for Throwables that are normally swallowed including always re-throwing certain Throwables (e.g. ThreadDeath). When waiting threads are interrupted, GOP, GKOP may leak capacity. Documentation for the close method in GenericObjectPool and GenericKeyedObjectPool incorrectly states that this method does not clear the pool. GenericObjectPool can block forever in borrowObject when the pool is exhausted and a newly created object fails validation. When borrowing an object if a new object is created but validate fails, the latch should not be returned to the queue as an exception will be thrown. Fix case where a thread could end up waiting indefinitely even if objects were available. Also fixes a couple of leaks in the internal processing object count that could lead to pool exhaustion. Handle the case where one key has reached maxActive but other keys have not. Prior to the fix for this issue, threads waiting on objects from keyed pools still having instances available could be blocked by a thread requesting an instance from an exhausted pool. Fix case where a thread could end up waiting indefinitely even if objects were available. Ensure that the GenericKeyedObjectPool idle object evictor does not visit the same instance more than once per eviction run. When exhausted action is set to WHEN_EXHAUSTED_BLOCK, maxwait is positive and client threads time out waiting for idle objects, capacity can be "leaked" from GenericObjectPools and GeneritCkeyedObjectPools. StackKeyedObjectPool.getNumActive() needs to be synchronized. Inconsistent synchronization in GenericObjectPool; constant fields should be final. GenericObjectPool not FIFO with respect to borrowing threads. _numActive > _maxActive under load Insufficient control over concurrent access to pooled objects by Evictor, client threads. Number of connections created has crossed more than maxActive. java.util.Timer in EvictionTimer does not recover from OutOfMemoryError in Evictor. Failed object creation may result in invalid active count in GKOP. Fixed constructor which was ignoring maxTotal parameter: GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) Changed StackKeyedObjectPool to discard stalest, not freshest, idle object when maxSleeping is reached. Allowed blocked threads in GenericObjectPool borrowObject to be interrupted. Fixes to address idle object eviction and LIFO/FIFO behavior reported in POOL-86. Made LIFO/FIFO behavior configurable for GenericObjectPool and GenericKeyedObjectPool, with default set back to LIFO (reverting to 1.2 behavior). Fixed GOP, GKOP evict method and added tests to ensure objects are visited in oldest-to-youngest order. Changed backing store for GOP, GKOP pools back to Commons Collections CursorableLinkedList (brought this class in, repackaged with package scope). Changed the default setting for Config.softMinEvictableIdleTimeMillis to GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS (was being incorrectly defaulted to DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS). Added a wrapper for the shared idle object eviction timer for all pools. The wrapper class wraps the Timer and keeps track of how many pools are using it. If no pools are using the timer, it is canceled. This prevents a thread being left running which, in application server environments, can lead to memory leaks and/or prevent applications from shutting down or reloading cleanly. Reduced synchronization in GenericObjectPool, GenericKeyedObjectPool. Factory method activations within synchronized blocks were causing performance problems in DBCP and other applications where factory methods could block. Fixes both POOL-93 and POOL-108. Made _testOnBorrow, _testOnReturn volatile and removed synchronization in associated getters and setters in GenericObjectPool, GenericKeyedObjectPool. Made getNumIdle synchronized in StackKeyedObjectPool. Fixed an error in the GenericKeyedObjectPool constructor that takes a Config instance as a parameter. The minIdle setting in the Config was being ignored by the constructor. Made behavior on instance validation failure consistent across pools, eliminating possible infinite loops in StackObjectPool, StackKeyedObjectPool, SoftReferenceObjectPool when factory fails to create valid objects. When no factory has been defined, addObject now throws IllegalStateExecption instead of NullPointerException for all pools. SoftReferenceObjectPool. Improved the accuracy of getNumIdle by "pruning" references to objects that have been garbage collected. GenericObjectPool, GenericKeyedObjectPool, SoftReferenceObjectPool, StackObjectPool. Eliminated IllegalStateExceptions when the following operations are attempted on a closed pool: getNumActive, getNumIdle, returnObject, invalidateObject. In each case, the operation is allowed to proceed, reporting the state of the pool that is being shut down, or destroying objects returning to the closed pool. StackObjectPool, SoftReferenceObjectPool, GenericKeyedObjectPool. Allowed borrowObject to continue (either examining additional idle instances or with makeObject) when an exception is encountered activating an idle object instead of propagating the exception to the client. Also made addObject propagate (not swallow) exceptions when passivating newly created instances. StackKeyedObjectPool. Added validation check for objects returned from borrowObject. BaseObjectPool, BaseKeyedObjectPool. Instead of throwing UnsupportedOperationException, the base class implementations of getNumIdle and getNumActive return negative values. The base implementation of close in BaseObjectPool no longer throws IllegalStateException when invoked on an already closed pool. A large number of bug fixes. See release notes for changes. GenericKeyedObjectPoolFactory Config Constructor is incorrect Not possible to extend GenericObjectPool.returnObject() without affecting addObject() A lot of corner cases were fixed Performance improvement by optimizing pool synchronization, the critical code paths were optimized by reducing pool synchronization but we also added more synchronization where needed New minIdle feature: the minimum number of objects allowed in the pool before the evictor thread (if active) spawns new objects. (Note no objects are created when: numActive + numIdle >= maxActive) New maxTotal feature: a cap on the total number of instances controlled by a pool. Only for GenericKeyedObjectPool where maxActive is a cap on the number of active instances from the pool (per key). UML Class and sequence diagrams See bugzilla for more changes No change log available. No change log available. commons-pool-1.6-src/src/java/org/apache/commons/pool/BaseKeyedObjectPool.java100644 0 0 13017 11701070263 24561 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * A simple base implementation of KeyedObjectPool. * Optional operations are implemented to either do nothing, return a value * indicating it is unsupported or throw {@link UnsupportedOperationException}. * * @param the type of keys in this pool * @param the type of objects held in this pool * * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public abstract class BaseKeyedObjectPool implements KeyedObjectPool { /** * {@inheritDoc} */ public abstract V borrowObject(K key) throws Exception; /** * {@inheritDoc} */ public abstract void returnObject(K key, V obj) throws Exception; /** *

Invalidates an object from the pool.

* *

By contract, obj must have been obtained * using {@link #borrowObject borrowObject} using a key that is * equivalent to the one used to borrow the Object in the first place.

* *

This method should be used when an object that has been borrowed * is determined (due to an exception or other problem) to be invalid.

* * @param key the key used to obtain the object * @param obj a {@link #borrowObject borrowed} instance to be returned. * @throws Exception */ public abstract void invalidateObject(K key, V obj) throws Exception; /** * Not supported in this base implementation. * Always throws an {@link UnsupportedOperationException}, * subclasses should override this behavior. * @param key ignored * @throws UnsupportedOperationException */ public void addObject(K key) throws Exception, UnsupportedOperationException { throw new UnsupportedOperationException(); } /** * Not supported in this base implementation. * @return a negative value. * @param key ignored */ public int getNumIdle(K key) throws UnsupportedOperationException { return -1; } /** * Not supported in this base implementation. * @return a negative value. * @param key ignored */ public int getNumActive(K key) throws UnsupportedOperationException { return -1; } /** * Not supported in this base implementation. * @return a negative value. */ public int getNumIdle() throws UnsupportedOperationException { return -1; } /** * Not supported in this base implementation. * @return a negative value. */ public int getNumActive() throws UnsupportedOperationException { return -1; } /** * Not supported in this base implementation. * @throws UnsupportedOperationException */ public void clear() throws Exception, UnsupportedOperationException { throw new UnsupportedOperationException(); } /** * Not supported in this base implementation. * @param key ignored * @throws UnsupportedOperationException */ public void clear(K key) throws Exception, UnsupportedOperationException { throw new UnsupportedOperationException(); } /** * Close this pool. * This affects the behavior of isClosed and assertOpen. */ public void close() throws Exception { closed = true; } /** * Not supported in this base implementation. * Always throws an {@link UnsupportedOperationException}, * subclasses should override this behavior. * @param factory the new KeyedPoolableObjectFactory * @deprecated to be removed in pool 2.0 */ @Deprecated public void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { throw new UnsupportedOperationException(); } /** * Has this pool instance been closed. * @return true when this pool has been closed. * @since Pool 1.4 */ protected final boolean isClosed() { return closed; } /** * Throws an IllegalStateException when this pool has been closed. * @throws IllegalStateException when this pool has been closed. * @see #isClosed() * @since Pool 1.4 */ protected final void assertOpen() throws IllegalStateException { if(isClosed()) { throw new IllegalStateException("Pool not open"); } } /** Whether or not the pool is close */ private volatile boolean closed = false; } commons-pool-1.6-src/src/java/org/apache/commons/pool/BaseKeyedPoolableObjectFactory.java100644 0 0 6152 11701070263 26717 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * A base implementation of KeyedPoolableObjectFactory. *

* All operations defined here are essentially no-op's. *

* * @param the type of keys in this pool * @param the type of objects held in this pool * * @see KeyedPoolableObjectFactory * * @author Rodney Waldhoff * @version $Revision: 1222388 $ $Date: 2011-12-22 13:28:27 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public abstract class BaseKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory { /** * Create an instance that can be served by the pool. * * @param key the key used when constructing the object * @return an instance that can be served by the pool */ public abstract V makeObject(K key) throws Exception; /** * Destroy an instance no longer needed by the pool. *

* The default implementation is a no-op. *

* * @param key the key used when selecting the instance * @param obj the instance to be destroyed */ public void destroyObject(K key, V obj) throws Exception { } /** * Ensures that the instance is safe to be returned by the pool. *

* The default implementation always returns true. *

* * @param key the key used when selecting the object * @param obj the instance to be validated * @return always true in the default implementation */ public boolean validateObject(K key, V obj) { return true; } /** * Reinitialize an instance to be returned by the pool. *

* The default implementation is a no-op. *

* * @param key the key used when selecting the object * @param obj the instance to be activated */ public void activateObject(K key, V obj) throws Exception { } /** * Uninitialize an instance to be returned to the idle object pool. *

* The default implementation is a no-op. *

* * @param key the key used when selecting the object * @param obj the instance to be passivated */ public void passivateObject(K key, V obj) throws Exception { } } commons-pool-1.6-src/src/java/org/apache/commons/pool/BaseObjectPool.java100644 0 0 11556 11701070263 23605 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * A simple base implementation of {@link ObjectPool}. * Optional operations are implemented to either do nothing, return a value * indicating it is unsupported or throw {@link UnsupportedOperationException}. * * @param the type of objects held in this pool * * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public abstract class BaseObjectPool implements ObjectPool { /** * Obtains an instance from the pool. * * @return an instance from the pool * @throws Exception if an instance cannot be obtained from the pool */ public abstract T borrowObject() throws Exception; /** * Returns an instance to the pool. * * @param obj instance to return to the pool */ public abstract void returnObject(T obj) throws Exception; /** *

Invalidates an object from the pool.

* *

By contract, obj must have been obtained * using {@link #borrowObject borrowObject}.

* *

This method should be used when an object that has been borrowed * is determined (due to an exception or other problem) to be invalid.

* * @param obj a {@link #borrowObject borrowed} instance to be disposed. * @throws Exception */ public abstract void invalidateObject(T obj) throws Exception; /** * Not supported in this base implementation. * @return a negative value. * * @throws UnsupportedOperationException */ public int getNumIdle() throws UnsupportedOperationException { return -1; } /** * Not supported in this base implementation. * @return a negative value. * * @throws UnsupportedOperationException */ public int getNumActive() throws UnsupportedOperationException { return -1; } /** * Not supported in this base implementation. * * @throws UnsupportedOperationException */ public void clear() throws Exception, UnsupportedOperationException { throw new UnsupportedOperationException(); } /** * Not supported in this base implementation. * Always throws an {@link UnsupportedOperationException}, * subclasses should override this behavior. * * @throws UnsupportedOperationException */ public void addObject() throws Exception, UnsupportedOperationException { throw new UnsupportedOperationException(); } /** * Close this pool. * This affects the behavior of isClosed and assertOpen. */ public void close() throws Exception { closed = true; } /** * Not supported in this base implementation. * Always throws an {@link UnsupportedOperationException}, * subclasses should override this behavior. * * @param factory the PoolableObjectFactory * @throws UnsupportedOperationException * @throws IllegalStateException * @deprecated to be removed in pool 2.0 */ @Deprecated public void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { throw new UnsupportedOperationException(); } /** * Has this pool instance been closed. * @return true when this pool has been closed. */ public final boolean isClosed() { return closed; } /** * Throws an IllegalStateException when this pool has been closed. * @throws IllegalStateException when this pool has been closed. * @see #isClosed() */ protected final void assertOpen() throws IllegalStateException { if (isClosed()) { throw new IllegalStateException("Pool not open"); } } /** Whether or not the pool is closed */ private volatile boolean closed = false; } commons-pool-1.6-src/src/java/org/apache/commons/pool/BasePoolableObjectFactory.java100644 0 0 4103 11701070263 25727 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * A base implementation of PoolableObjectFactory. *

* All operations defined here are essentially no-op's. * * @param the type of objects held in this pool * * @see PoolableObjectFactory * @see BaseKeyedPoolableObjectFactory * * @author Rodney Waldhoff * @version $Revision: 1222388 $ $Date: 2011-12-22 13:28:27 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public abstract class BasePoolableObjectFactory implements PoolableObjectFactory { /** * {@inheritDoc} */ public abstract T makeObject() throws Exception; /** * No-op. * * @param obj ignored */ public void destroyObject(T obj) throws Exception { } /** * This implementation always returns true. * * @param obj ignored * @return true */ public boolean validateObject(T obj) { return true; } /** * No-op. * * @param obj ignored */ public void activateObject(T obj) throws Exception { } /** * No-op. * * @param obj ignored */ public void passivateObject(T obj) throws Exception { } } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/CursorableLinkedList.java100644 0 0 141716 11701070262 26020 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.ref.WeakReference; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; /** *

* This class has been copied from Commons Collections, version 3.1 in order * to eliminate the dependency of pool on collections. It has package scope * to prevent its inclusion in the pool public API. The class declaration below * should *not* be changed to public. *

* * A doubly-linked list implementation of the {@link List} interface, * supporting a {@link ListIterator} that allows concurrent modifications * to the underlying list. *

* * Implements all of the optional {@link List} operations, the * stack/queue/dequeue operations available in {@link java.util.LinkedList} * and supports a {@link ListIterator} that allows concurrent modifications * to the underlying list (see {@link #cursor}). *

* Note that this implementation is not synchronized. * * @param the type of elements held in this collection * * @see java.util.LinkedList * * @version $Revision: 480452 $ $Date: 2006-11-29 00:45:14 -0700 (Wed, 29 Nov 2006) $ * * @author Rodney Waldhoff * @author Janek Bogucki * @author Simon Kitching */ class CursorableLinkedList implements List, Serializable { /** Ensure serialization compatibility */ private static final long serialVersionUID = 8836393098519411393L; //--- public methods --------------------------------------------- // CHECKSTYLE: stop all checks /** * Appends the specified element to the end of this list. * * @param o element to be appended to this list. * @return true */ public boolean add(E o) { insertListable(_head.prev(),null,o); return true; } /** * Inserts the specified element at the specified position in this list. * Shifts the element currently at that position (if any) and any subsequent * elements to the right (adds one to their indices). * * @param index index at which the specified element is to be inserted. * @param element element to be inserted. * * @throws ClassCastException if the class of the specified element * prevents it from being added to this list. * @throws IllegalArgumentException if some aspect of the specified * element prevents it from being added to this list. * @throws IndexOutOfBoundsException if the index is out of range * (index < 0 || index > size()). */ public void add(int index, E element) { if(index == _size) { add(element); } else { if(index < 0 || index > _size) { throw new IndexOutOfBoundsException(String.valueOf(index) + " < 0 or " + String.valueOf(index) + " > " + _size); } Listable succ = (isEmpty() ? null : getListableAt(index)); Listable pred = (null == succ ? null : succ.prev()); insertListable(pred,succ,element); } } /** * Appends all of the elements in the specified collection to the end of * this list, in the order that they are returned by the specified * {@link Collection}'s {@link Iterator}. The behavior of this operation is * unspecified if the specified collection is modified while * the operation is in progress. (Note that this will occur if the * specified collection is this list, and it's nonempty.) * * @param c collection whose elements are to be added to this list. * @return true if this list changed as a result of the call. * * @throws ClassCastException if the class of an element in the specified * collection prevents it from being added to this list. * @throws IllegalArgumentException if some aspect of an element in the * specified collection prevents it from being added to this * list. */ public boolean addAll(Collection c) { if(c.isEmpty()) { return false; } Iterator it = c.iterator(); while(it.hasNext()) { insertListable(_head.prev(),null,it.next()); } return true; } /** * Inserts all of the elements in the specified collection into this * list at the specified position. Shifts the element currently at * that position (if any) and any subsequent elements to the right * (increases their indices). The new elements will appear in this * list in the order that they are returned by the specified * {@link Collection}'s {@link Iterator}. The behavior of this operation is * unspecified if the specified collection is modified while the * operation is in progress. (Note that this will occur if the specified * collection is this list, and it's nonempty.) * * @param index index at which to insert first element from the specified * collection. * @param c elements to be inserted into this list. * @return true if this list changed as a result of the call. * * @throws ClassCastException if the class of one of elements of the * specified collection prevents it from being added to this * list. * @throws IllegalArgumentException if some aspect of one of elements of * the specified collection prevents it from being added to * this list. * @throws IndexOutOfBoundsException if the index is out of range (index * < 0 || index > size()). */ public boolean addAll(int index, Collection c) { if(c.isEmpty()) { return false; } else if(_size == index || _size == 0) { return addAll(c); } else { Listable succ = getListableAt(index); Listable pred = (null == succ) ? null : succ.prev(); Iterator it = c.iterator(); while(it.hasNext()) { pred = insertListable(pred,succ,it.next()); } return true; } } /** * Inserts the specified element at the beginning of this list. * (Equivalent to {@link #add(int,java.lang.Object) add(0,o)}). * * @param o element to be prepended to this list. * @return true */ public boolean addFirst(E o) { insertListable(null,_head.next(),o); return true; } /** * Inserts the specified element at the end of this list. * (Equivalent to {@link #add(java.lang.Object)}). * * @param o element to be appended to this list. * @return true */ public boolean addLast(E o) { insertListable(_head.prev(),null,o); return true; } /** * Removes all of the elements from this list. This * list will be empty after this call returns (unless * it throws an exception). */ public void clear() { /* // this is the quick way, but would force us // to break all the cursors _modCount++; _head.setNext(null); _head.setPrev(null); _size = 0; */ Iterator it = iterator(); while(it.hasNext()) { it.next(); it.remove(); } } /** * Returns true if this list contains the specified element. * More formally, returns true if and only if this list contains * at least one element e such that * (o==null ? e==null : o.equals(e)). * * @param o element whose presence in this list is to be tested. * @return true if this list contains the specified element. */ public boolean contains(Object o) { for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { if((null == o && null == elt.value()) || (o != null && o.equals(elt.value()))) { return true; } } return false; } /** * Returns true if this list contains all of the elements of the * specified collection. * * @param c collection to be checked for containment in this list. * @return true if this list contains all of the elements of the * specified collection. */ public boolean containsAll(Collection c) { Iterator it = c.iterator(); while(it.hasNext()) { if(!this.contains(it.next())) { return false; } } return true; } /** * Returns a {@link ListIterator} for iterating through the * elements of this list. Unlike {@link #iterator}, a cursor * is not bothered by concurrent modifications to the * underlying list. *

* Specifically, when elements are added to the list before or * after the cursor, the cursor simply picks them up automatically. * When the "current" (i.e., last returned by {@link ListIterator#next} * or {@link ListIterator#previous}) element of the list is removed, * the cursor automatically adjusts to the change (invalidating the * last returned value--i.e., it cannot be removed). *

* Note that the returned {@link ListIterator} does not support the * {@link ListIterator#nextIndex} and {@link ListIterator#previousIndex} * methods (they throw {@link UnsupportedOperationException} when invoked. *

* Historical Note: In previous versions of this class, the object * returned from this method was required to be explicitly closed. This * is no longer necessary. * * @see #cursor(int) * @see #listIterator() * @see CursorableLinkedList.Cursor */ public CursorableLinkedList.Cursor cursor() { return new Cursor(0); } /** * Returns a {@link ListIterator} for iterating through the * elements of this list, initialized such that * {@link ListIterator#next} will return the element at * the specified index (if any) and {@link ListIterator#previous} * will return the element immediately preceding it (if any). * Unlike {@link #iterator}, a cursor * is not bothered by concurrent modifications to the * underlying list. * * @see #cursor() * @see #listIterator(int) * @see CursorableLinkedList.Cursor * @throws IndexOutOfBoundsException if the index is out of range (index * < 0 || index > size()). */ public CursorableLinkedList.Cursor cursor(int i) { return new Cursor(i); } /** * Compares the specified object with this list for equality. Returns * true if and only if the specified object is also a list, both * lists have the same size, and all corresponding pairs of elements in * the two lists are equal. (Two elements e1 and * e2 are equal if (e1==null ? e2==null : * e1.equals(e2)).) In other words, two lists are defined to be * equal if they contain the same elements in the same order. This * definition ensures that the equals method works properly across * different implementations of the List interface. * * @param o the object to be compared for equality with this list. * @return true if the specified object is equal to this list. */ @Override public boolean equals(Object o) { if(o == this) { return true; } else if(!(o instanceof List)) { return false; } Iterator it = ((List)o).listIterator(); for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { if(!it.hasNext() || (null == elt.value() ? null != it.next() : !(elt.value().equals(it.next()))) ) { return false; } } return !it.hasNext(); } /** * Returns the element at the specified position in this list. * * @param index index of element to return. * @return the element at the specified position in this list. * * @throws IndexOutOfBoundsException if the index is out of range (index * < 0 || index >= size()). */ public E get(int index) { return getListableAt(index).value(); } /** * Returns the element at the beginning of this list. */ public E getFirst() { try { return _head.next().value(); } catch(NullPointerException e) { throw new NoSuchElementException(); } } /** * Returns the element at the end of this list. */ public E getLast() { try { return _head.prev().value(); } catch(NullPointerException e) { throw new NoSuchElementException(); } } /** * Returns the hash code value for this list. The hash code of a list * is defined to be the result of the following calculation: *

     *  hashCode = 1;
     *  Iterator i = list.iterator();
     *  while (i.hasNext()) {
     *      Object obj = i.next();
     *      hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
     *  }
     * 
* This ensures that list1.equals(list2) implies that * list1.hashCode()==list2.hashCode() for any two lists, * list1 and list2, as required by the general * contract of Object.hashCode. * * @return the hash code value for this list. * @see Object#hashCode() * @see Object#equals(Object) * @see #equals(Object) */ @Override public int hashCode() { int hash = 1; for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { hash = 31*hash + (null == elt.value() ? 0 : elt.value().hashCode()); } return hash; } /** * Returns the index in this list of the first occurrence of the specified * element, or -1 if this list does not contain this element. * More formally, returns the lowest index i such that * (o==null ? get(i)==null : o.equals(get(i))), * or -1 if there is no such index. * * @param o element to search for. * @return the index in this list of the first occurrence of the specified * element, or -1 if this list does not contain this element. */ public int indexOf(Object o) { int ndx = 0; // perform the null check outside of the loop to save checking every // single time through the loop. if (null == o) { for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { if (null == elt.value()) { return ndx; } ndx++; } } else { for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { if (o.equals(elt.value())) { return ndx; } ndx++; } } return -1; } /** * Returns true if this list contains no elements. * @return true if this list contains no elements. */ public boolean isEmpty() { return(0 == _size); } /** * Returns a fail-fast iterator. * @see List#iterator */ public Iterator iterator() { return listIterator(0); } /** * Returns the index in this list of the last occurrence of the specified * element, or -1 if this list does not contain this element. * More formally, returns the highest index i such that * (o==null ? get(i)==null : o.equals(get(i))), * or -1 if there is no such index. * * @param o element to search for. * @return the index in this list of the last occurrence of the specified * element, or -1 if this list does not contain this element. */ public int lastIndexOf(Object o) { int ndx = _size-1; // perform the null check outside of the loop to save checking every // single time through the loop. if (null == o) { for(Listable elt = _head.prev(), past = null; null != elt && past != _head.next(); elt = (past = elt).prev()) { if (null == elt.value()) { return ndx; } ndx--; } } else { for(Listable elt = _head.prev(), past = null; null != elt && past != _head.next(); elt = (past = elt).prev()) { if (o.equals(elt.value())) { return ndx; } ndx--; } } return -1; } /** * Returns a fail-fast ListIterator. * @see List#listIterator() */ public ListIterator listIterator() { return listIterator(0); } /** * Returns a fail-fast ListIterator. * @see List#listIterator(int) */ public ListIterator listIterator(int index) { if(index<0 || index > _size) { throw new IndexOutOfBoundsException(index + " < 0 or > " + _size); } return new ListIter(index); } /** * Removes the first occurrence in this list of the specified element. * If this list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index i * such that (o==null ? get(i)==null : o.equals(get(i))) (if * such an element exists). * * @param o element to be removed from this list, if present. * @return true if this list contained the specified element. */ public boolean remove(Object o) { for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { if(null == o && null == elt.value()) { removeListable(elt); return true; } else if(o != null && o.equals(elt.value())) { removeListable(elt); return true; } } return false; } /** * Removes the element at the specified position in this list (optional * operation). Shifts any subsequent elements to the left (subtracts one * from their indices). Returns the element that was removed from the * list. * * @param index the index of the element to removed. * @return the element previously at the specified position. * * @throws IndexOutOfBoundsException if the index is out of range (index * < 0 || index >= size()). */ public E remove(int index) { Listable elt = getListableAt(index); E ret = elt.value(); removeListable(elt); return ret; } /** * Removes from this list all the elements that are contained in the * specified collection. * * @param c collection that defines which elements will be removed from * this list. * @return true if this list changed as a result of the call. */ public boolean removeAll(Collection c) { if(0 == c.size() || 0 == _size) { return false; } else { boolean changed = false; Iterator it = iterator(); while(it.hasNext()) { if(c.contains(it.next())) { it.remove(); changed = true; } } return changed; } } /** * Removes the first element of this list, if any. */ public E removeFirst() { if(_head.next() != null) { E val = _head.next().value(); removeListable(_head.next()); return val; } else { throw new NoSuchElementException(); } } /** * Removes the last element of this list, if any. */ public E removeLast() { if(_head.prev() != null) { E val = _head.prev().value(); removeListable(_head.prev()); return val; } else { throw new NoSuchElementException(); } } /** * Retains only the elements in this list that are contained in the * specified collection. In other words, removes * from this list all the elements that are not contained in the specified * collection. * * @param c collection that defines which elements this set will retain. * * @return true if this list changed as a result of the call. */ public boolean retainAll(Collection c) { boolean changed = false; Iterator it = iterator(); while(it.hasNext()) { if(!c.contains(it.next())) { it.remove(); changed = true; } } return changed; } /** * Replaces the element at the specified position in this list with the * specified element. * * @param index index of element to replace. * @param element element to be stored at the specified position. * @return the element previously at the specified position. * * @throws ClassCastException if the class of the specified element * prevents it from being added to this list. * @throws IllegalArgumentException if some aspect of the specified * element prevents it from being added to this list. * @throws IndexOutOfBoundsException if the index is out of range * (index < 0 || index >= size()). */ public E set(int index, E element) { Listable elt = getListableAt(index); E val = elt.setValue(element); broadcastListableChanged(elt); return val; } /** * Returns the number of elements in this list. * @return the number of elements in this list. */ public int size() { return _size; } /** * Returns an array containing all of the elements in this list in proper * sequence. Obeys the general contract of the {@link Collection#toArray()} method. * * @return an array containing all of the elements in this list in proper * sequence. */ public Object[] toArray() { Object[] array = new Object[_size]; int i = 0; for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { array[i++] = elt.value(); } return array; } /** * Returns an array containing all of the elements in this list in proper * sequence; the runtime type of the returned array is that of the * specified array. Obeys the general contract of the * {@link Collection#toArray()} method. * * @param a the array into which the elements of this list are to * be stored, if it is big enough; otherwise, a new array of the * same runtime type is allocated for this purpose. * @return an array containing the elements of this list. * @exception ArrayStoreException * if the runtime type of the specified array * is not a supertype of the runtime type of every element in * this list. */ @SuppressWarnings("unchecked") public T[] toArray(T a[]) { if(a.length < _size) { a = (T[])Array.newInstance(a.getClass().getComponentType(), _size); } int i = 0; for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { a[i++] = (T) elt.value(); } if(a.length > _size) { a[_size] = null; // should we null out the rest of the array also? java.util.LinkedList doesn't } return a; } /** * Returns a {@link String} representation of this list, suitable for debugging. * @return a {@link String} representation of this list, suitable for debugging. */ @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("["); for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { if(_head.next() != elt) { buf.append(", "); } buf.append(elt.value()); } buf.append("]"); return buf.toString(); } /** * Returns a fail-fast sublist. * @see List#subList(int,int) */ public List subList(int i, int j) { if(i < 0 || j > _size || i > j) { throw new IndexOutOfBoundsException(); } else if(i == 0 && j == _size) { return this; } else { return new CursorableSubList(this,i,j); } } //--- protected methods ------------------------------------------ /** * Inserts a new value into my * list, after the specified before element, and before the * specified after element * * @return the newly created * {@link org.apache.commons.collections.CursorableLinkedList.Listable} */ protected Listable insertListable(Listable before, Listable after, E value) { _modCount++; _size++; Listable elt = new Listable(before,after,value); if(null != before) { before.setNext(elt); } else { _head.setNext(elt); } if(null != after) { after.setPrev(elt); } else { _head.setPrev(elt); } broadcastListableInserted(elt); return elt; } /** * Removes the given * {@link org.apache.commons.collections.CursorableLinkedList.Listable} * from my list. */ protected void removeListable(Listable elt) { _modCount++; _size--; if(_head.next() == elt) { _head.setNext(elt.next()); } if(null != elt.next()) { elt.next().setPrev(elt.prev()); } if(_head.prev() == elt) { _head.setPrev(elt.prev()); } if(null != elt.prev()) { elt.prev().setNext(elt.next()); } broadcastListableRemoved(elt); } /** * Returns the * {@link org.apache.commons.collections.CursorableLinkedList.Listable} * at the specified index. * * @throws IndexOutOfBoundsException if index is less than zero or * greater than or equal to the size of this list. */ protected Listable getListableAt(int index) { if(index < 0 || index >= _size) { throw new IndexOutOfBoundsException(String.valueOf(index) + " < 0 or " + String.valueOf(index) + " >= " + _size); } if(index <=_size/2) { Listable elt = _head.next(); for(int i = 0; i < index; i++) { elt = elt.next(); } return elt; } else { Listable elt = _head.prev(); for(int i = (_size-1); i > index; i--) { elt = elt.prev(); } return elt; } } /** * Registers a {@link CursorableLinkedList.Cursor} to be notified * of changes to this list. */ protected void registerCursor(Cursor cur) { // We take this opportunity to clean the _cursors list // of WeakReference objects to garbage-collected cursors. for (Iterator> it = _cursors.iterator(); it.hasNext(); ) { WeakReference ref = it.next(); if (ref.get() == null) { it.remove(); } } _cursors.add( new WeakReference(cur) ); } /** * Removes a {@link CursorableLinkedList.Cursor} from * the set of cursors to be notified of changes to this list. */ protected void unregisterCursor(Cursor cur) { for (Iterator> it = _cursors.iterator(); it.hasNext(); ) { WeakReference ref = it.next(); Cursor cursor = ref.get(); if (cursor == null) { // some other unrelated cursor object has been // garbage-collected; let's take the opportunity to // clean up the cursors list anyway.. it.remove(); } else if (cursor == cur) { ref.clear(); it.remove(); break; } } } /** * Informs all of my registered cursors that they are now * invalid. */ protected void invalidateCursors() { Iterator> it = _cursors.iterator(); while (it.hasNext()) { WeakReference ref = it.next(); Cursor cursor = ref.get(); if (cursor != null) { // cursor is null if object has been garbage-collected cursor.invalidate(); ref.clear(); } it.remove(); } } /** * Informs all of my registered cursors that the specified * element was changed. * @see #set(int,java.lang.Object) */ protected void broadcastListableChanged(Listable elt) { Iterator> it = _cursors.iterator(); while (it.hasNext()) { WeakReference ref = it.next(); Cursor cursor = ref.get(); if (cursor == null) { it.remove(); // clean up list } else { cursor.listableChanged(elt); } } } /** * Informs all of my registered cursors that the specified * element was just removed from my list. */ protected void broadcastListableRemoved(Listable elt) { Iterator> it = _cursors.iterator(); while (it.hasNext()) { WeakReference ref = it.next(); Cursor cursor = ref.get(); if (cursor == null) { it.remove(); // clean up list } else { cursor.listableRemoved(elt); } } } /** * Informs all of my registered cursors that the specified * element was just added to my list. */ protected void broadcastListableInserted(Listable elt) { Iterator> it = _cursors.iterator(); while (it.hasNext()) { WeakReference ref = it.next(); Cursor cursor = ref.get(); if (cursor == null) { it.remove(); // clean up list } else { cursor.listableInserted(elt); } } } private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeInt(_size); Listable cur = _head.next(); while (cur != null) { out.writeObject(cur.value()); cur = cur.next(); } } @SuppressWarnings("unchecked") private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); _size = 0; _modCount = 0; _cursors = new ArrayList>(); _head = new Listable(null,null,null); int size = in.readInt(); for (int i=0;i * _head.next() points to the first element in the list, * _head.prev() to the last. Note that it is possible for * _head.next().prev() and _head.prev().next() to be * non-null, as when I am a sublist for some larger list. * Use == _head.next() and == _head.prev() to determine * if a given * {@link org.apache.commons.collections.CursorableLinkedList.Listable} * is the first or last element in the list. */ protected transient Listable _head = new Listable(null,null,null); /** Tracks the number of structural modifications to me. */ protected transient int _modCount = 0; /** * A list of the currently {@link CursorableLinkedList.Cursor}s currently * open in this list. */ protected transient List> _cursors = new ArrayList>(); //--- inner classes ---------------------------------------------- static class Listable implements Serializable { private Listable _prev = null; private Listable _next = null; private E _val = null; Listable(Listable prev, Listable next, E val) { _prev = prev; _next = next; _val = val; } Listable next() { return _next; } Listable prev() { return _prev; } E value() { return _val; } void setNext(Listable next) { _next = next; } void setPrev(Listable prev) { _prev = prev; } E setValue(E val) { E temp = _val; _val = val; return temp; } } class ListIter implements ListIterator { Listable _cur = null; Listable _lastReturned = null; int _expectedModCount = _modCount; int _nextIndex = 0; ListIter(int index) { if(index == 0) { _cur = new Listable(null,_head.next(),null); _nextIndex = 0; } else if(index == _size) { _cur = new Listable(_head.prev(),null,null); _nextIndex = _size; } else { Listable temp = getListableAt(index); _cur = new Listable(temp.prev(),temp,null); _nextIndex = index; } } public E previous() { checkForComod(); if(!hasPrevious()) { throw new NoSuchElementException(); } else { E ret = _cur.prev().value(); _lastReturned = _cur.prev(); _cur.setNext(_cur.prev()); _cur.setPrev(_cur.prev().prev()); _nextIndex--; return ret; } } public boolean hasNext() { checkForComod(); return(null != _cur.next() && _cur.prev() != _head.prev()); } public E next() { checkForComod(); if(!hasNext()) { throw new NoSuchElementException(); } else { E ret = _cur.next().value(); _lastReturned = _cur.next(); _cur.setPrev(_cur.next()); _cur.setNext(_cur.next().next()); _nextIndex++; return ret; } } public int previousIndex() { checkForComod(); if(!hasPrevious()) { return -1; } return _nextIndex-1; } public boolean hasPrevious() { checkForComod(); return(null != _cur.prev() && _cur.next() != _head.next()); } public void set(E o) { checkForComod(); try { _lastReturned.setValue(o); } catch(NullPointerException e) { throw new IllegalStateException(); } } public int nextIndex() { checkForComod(); if(!hasNext()) { return size(); } return _nextIndex; } public void remove() { checkForComod(); if(null == _lastReturned) { throw new IllegalStateException(); } else { _cur.setNext(_lastReturned == _head.prev() ? null : _lastReturned.next()); _cur.setPrev(_lastReturned == _head.next() ? null : _lastReturned.prev()); removeListable(_lastReturned); _lastReturned = null; _nextIndex--; _expectedModCount++; } } public void add(E o) { checkForComod(); _cur.setPrev(insertListable(_cur.prev(),_cur.next(),o)); _lastReturned = null; _nextIndex++; _expectedModCount++; } protected void checkForComod() { if(_expectedModCount != _modCount) { throw new ConcurrentModificationException(); } } } public class Cursor extends ListIter implements ListIterator { boolean _valid = false; Cursor(int index) { super(index); _valid = true; registerCursor(this); } @Override public int previousIndex() { throw new UnsupportedOperationException(); } @Override public int nextIndex() { throw new UnsupportedOperationException(); } @Override public void add(E o) { checkForComod(); Listable elt = insertListable(_cur.prev(),_cur.next(),o); _cur.setPrev(elt); _cur.setNext(elt.next()); _lastReturned = null; _nextIndex++; _expectedModCount++; } protected void listableRemoved(Listable elt) { if(null == _head.prev()) { _cur.setNext(null); } else if(_cur.next() == elt) { _cur.setNext(elt.next()); } if(null == _head.next()) { _cur.setPrev(null); } else if(_cur.prev() == elt) { _cur.setPrev(elt.prev()); } if(_lastReturned == elt) { _lastReturned = null; } } protected void listableInserted(Listable elt) { if(null == _cur.next() && null == _cur.prev()) { _cur.setNext(elt); } else if(_cur.prev() == elt.prev()) { _cur.setNext(elt); } if(_cur.next() == elt.next()) { _cur.setPrev(elt); } if(_lastReturned == elt) { _lastReturned = null; } } protected void listableChanged(Listable elt) { if(_lastReturned == elt) { _lastReturned = null; } } @Override protected void checkForComod() { if(!_valid) { throw new ConcurrentModificationException(); } } protected void invalidate() { _valid = false; } /** * Mark this cursor as no longer being needed. Any resources * associated with this cursor are immediately released. * In previous versions of this class, it was mandatory to close * all cursor objects to avoid memory leaks. It is no longer * necessary to call this close method; an instance of this class * can now be treated exactly like a normal iterator. */ public void close() { if(_valid) { _valid = false; unregisterCursor(this); } } } } class CursorableSubList extends CursorableLinkedList implements List { //--- constructors ----------------------------------------------- CursorableSubList(CursorableLinkedList list, int from, int to) { if(0 > from || list.size() < to) { throw new IndexOutOfBoundsException(); } else if(from > to) { throw new IllegalArgumentException(); } _list = list; if(from < list.size()) { _head.setNext(_list.getListableAt(from)); _pre = (null == _head.next()) ? null : _head.next().prev(); } else { _pre = _list.getListableAt(from-1); } if(from == to) { _head.setNext(null); _head.setPrev(null); if(to < list.size()) { _post = _list.getListableAt(to); } else { _post = null; } } else { _head.setPrev(_list.getListableAt(to-1)); _post = _head.prev().next(); } _size = to - from; _modCount = _list._modCount; } //--- public methods ------------------------------------------ @Override public void clear() { checkForComod(); Iterator it = iterator(); while(it.hasNext()) { it.next(); it.remove(); } } @Override public Iterator iterator() { checkForComod(); return super.iterator(); } @Override public int size() { checkForComod(); return super.size(); } @Override public boolean isEmpty() { checkForComod(); return super.isEmpty(); } @Override public Object[] toArray() { checkForComod(); return super.toArray(); } @Override public T[] toArray(T a[]) { checkForComod(); return super.toArray(a); } @Override public boolean contains(Object o) { checkForComod(); return super.contains(o); } @Override public boolean remove(Object o) { checkForComod(); return super.remove(o); } @Override public E removeFirst() { checkForComod(); return super.removeFirst(); } @Override public E removeLast() { checkForComod(); return super.removeLast(); } @Override public boolean addAll(Collection c) { checkForComod(); return super.addAll(c); } @Override public boolean add(E o) { checkForComod(); return super.add(o); } @Override public boolean addFirst(E o) { checkForComod(); return super.addFirst(o); } @Override public boolean addLast(E o) { checkForComod(); return super.addLast(o); } @Override public boolean removeAll(Collection c) { checkForComod(); return super.removeAll(c); } @Override public boolean containsAll(Collection c) { checkForComod(); return super.containsAll(c); } @Override public boolean addAll(int index, Collection c) { checkForComod(); return super.addAll(index,c); } @Override public int hashCode() { checkForComod(); return super.hashCode(); } @Override public boolean retainAll(Collection c) { checkForComod(); return super.retainAll(c); } @Override public E set(int index, E element) { checkForComod(); return super.set(index,element); } @Override public boolean equals(Object o) { checkForComod(); return super.equals(o); } @Override public E get(int index) { checkForComod(); return super.get(index); } @Override public E getFirst() { checkForComod(); return super.getFirst(); } @Override public E getLast() { checkForComod(); return super.getLast(); } @Override public void add(int index, E element) { checkForComod(); super.add(index,element); } @Override public ListIterator listIterator(int index) { checkForComod(); return super.listIterator(index); } @Override public E remove(int index) { checkForComod(); return super.remove(index); } @Override public int indexOf(Object o) { checkForComod(); return super.indexOf(o); } @Override public int lastIndexOf(Object o) { checkForComod(); return super.lastIndexOf(o); } @Override public ListIterator listIterator() { checkForComod(); return super.listIterator(); } @Override public List subList(int fromIndex, int toIndex) { checkForComod(); return super.subList(fromIndex,toIndex); } //--- protected methods ------------------------------------------ /** * Inserts a new value into my * list, after the specified before element, and before the * specified after element * * @return the newly created {@link CursorableLinkedList.Listable} */ @Override protected Listable insertListable(Listable before, Listable after, E value) { _modCount++; _size++; Listable elt = _list.insertListable((null == before ? _pre : before), (null == after ? _post : after),value); if(null == _head.next()) { _head.setNext(elt); _head.setPrev(elt); } if(before == _head.prev()) { _head.setPrev(elt); } if(after == _head.next()) { _head.setNext(elt); } broadcastListableInserted(elt); return elt; } /** * Removes the given {@link CursorableLinkedList.Listable} from my list. */ @Override protected void removeListable(Listable elt) { _modCount++; _size--; if(_head.next() == elt && _head.prev() == elt) { _head.setNext(null); _head.setPrev(null); } if(_head.next() == elt) { _head.setNext(elt.next()); } if(_head.prev() == elt) { _head.setPrev(elt.prev()); } _list.removeListable(elt); broadcastListableRemoved(elt); } /** * Test to see if my underlying list has been modified * by some other process. If it has, throws a * {@link ConcurrentModificationException}, otherwise * quietly returns. * * @throws ConcurrentModificationException */ protected void checkForComod() throws ConcurrentModificationException { if(_modCount != _list._modCount) { throw new ConcurrentModificationException(); } } //--- protected attributes --------------------------------------- /** My underlying list */ protected CursorableLinkedList _list = null; /** The element in my underlying list preceding the first element in my list. */ protected Listable _pre = null; /** The element in my underlying list following the last element in my list. */ protected Listable _post = null; } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/EvictionTimer.java100644 0 0 10652 11701070262 24467 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Timer; import java.util.TimerTask; /** *

* Provides a shared idle object eviction timer for all pools. This class wraps * the standard {@link Timer} and keeps track of how many pools are using it. * If no pools are using the timer, it is canceled. This prevents a thread * being left running which, in application server environments, can lead to * memory leads and/or prevent applications from shutting down or reloading * cleanly. *

*

* This class has package scope to prevent its inclusion in the pool public API. * The class declaration below should *not* be changed to public. *

*/ class EvictionTimer { /** Timer instance */ private static Timer _timer; //@GuardedBy("this") /** Static usage count tracker */ private static int _usageCount; //@GuardedBy("this") /** Prevent instantiation */ private EvictionTimer() { // Hide the default constuctor } /** * Add the specified eviction task to the timer. Tasks that are added with a * call to this method *must* call {@link #cancel(TimerTask)} to cancel the * task to prevent memory and/or thread leaks in application server * environments. * @param task Task to be scheduled * @param delay Delay in milliseconds before task is executed * @param period Time in milliseconds between executions */ static synchronized void schedule(TimerTask task, long delay, long period) { if (null == _timer) { // Force the new Timer thread to be created with a context class // loader set to the class loader that loaded this library ClassLoader ccl = AccessController.doPrivileged( new PrivilegedGetTccl()); try { AccessController.doPrivileged(new PrivilegedSetTccl( EvictionTimer.class.getClassLoader())); _timer = new Timer(true); } finally { AccessController.doPrivileged(new PrivilegedSetTccl(ccl)); } } _usageCount++; _timer.schedule(task, delay, period); } /** * Remove the specified eviction task from the timer. * @param task Task to be scheduled */ static synchronized void cancel(TimerTask task) { task.cancel(); _usageCount--; if (_usageCount == 0) { _timer.cancel(); _timer = null; } } /** * {@link PrivilegedAction} used to get the ContextClassLoader */ private static class PrivilegedGetTccl implements PrivilegedAction { /** * {@inheritDoc} */ public ClassLoader run() { return Thread.currentThread().getContextClassLoader(); } } /** * {@link PrivilegedAction} used to set the ContextClassLoader */ private static class PrivilegedSetTccl implements PrivilegedAction { /** ClassLoader */ private final ClassLoader cl; /** * Create a new PrivilegedSetTccl using the given classloader * @param cl ClassLoader to use */ PrivilegedSetTccl(ClassLoader cl) { this.cl = cl; } /** * {@inheritDoc} */ public ClassLoader run() { Thread.currentThread().setContextClassLoader(cl); return null; } } } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java100644 0 0 353401 11701070262 26247 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Set; import java.util.TimerTask; import java.util.TreeMap; import org.apache.commons.pool.BaseKeyedObjectPool; import org.apache.commons.pool.KeyedObjectPool; import org.apache.commons.pool.KeyedPoolableObjectFactory; import org.apache.commons.pool.PoolUtils; /** * A configurable KeyedObjectPool implementation. *

* When coupled with the appropriate {@link KeyedPoolableObjectFactory}, * GenericKeyedObjectPool provides robust pooling functionality for * keyed objects. A GenericKeyedObjectPool can be viewed as a map * of pools, keyed on the (unique) key values provided to the * {@link #preparePool preparePool}, {@link #addObject addObject} or * {@link #borrowObject borrowObject} methods. Each time a new key value is * provided to one of these methods, a new pool is created under the given key * to be managed by the containing GenericKeyedObjectPool. *

*

A GenericKeyedObjectPool provides a number of configurable * parameters:

*
    *
  • * {@link #setMaxActive maxActive} controls the maximum number of objects * (per key) that can allocated by the pool (checked out to client threads, * or idle in the pool) at one time. When non-positive, there is no limit * to the number of objects per key. When {@link #setMaxActive maxActive} is * reached, the keyed pool is said to be exhausted. The default setting for * this parameter is 8. *
  • *
  • * {@link #setMaxTotal maxTotal} sets a global limit on the number of objects * that can be in circulation (active or idle) within the combined set of * pools. When non-positive, there is no limit to the total number of * objects in circulation. When {@link #setMaxTotal maxTotal} is exceeded, * all keyed pools are exhausted. When maxTotal is set to a * positive value and {@link #borrowObject borrowObject} is invoked * when at the limit with no idle instances available, an attempt is made to * create room by clearing the oldest 15% of the elements from the keyed * pools. The default setting for this parameter is -1 (no limit). *
  • *
  • * {@link #setMaxIdle maxIdle} controls the maximum number of objects that can * sit idle in the pool (per key) at any time. When negative, there * is no limit to the number of objects that may be idle per key. The * default setting for this parameter is 8. *
  • *
  • * {@link #setWhenExhaustedAction whenExhaustedAction} specifies the * behavior of the {@link #borrowObject borrowObject} method when a keyed * pool is exhausted: *
      *
    • * When {@link #setWhenExhaustedAction whenExhaustedAction} is * {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject borrowObject} will throw * a {@link NoSuchElementException} *
    • *
    • * When {@link #setWhenExhaustedAction whenExhaustedAction} is * {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject borrowObject} will create a new * object and return it (essentially making {@link #setMaxActive maxActive} * meaningless.) *
    • *
    • * When {@link #setWhenExhaustedAction whenExhaustedAction} * is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject borrowObject} will block * (invoke {@link Object#wait() wait} until a new or idle object is available. * If a positive {@link #setMaxWait maxWait} * value is supplied, the {@link #borrowObject borrowObject} will block for at * most that many milliseconds, after which a {@link NoSuchElementException} * will be thrown. If {@link #setMaxWait maxWait} is non-positive, * the {@link #borrowObject borrowObject} method will block indefinitely. *
    • *
    * The default whenExhaustedAction setting is * {@link #WHEN_EXHAUSTED_BLOCK}. *
  • *
  • * When {@link #setTestOnBorrow testOnBorrow} is set, the pool will * attempt to validate each object before it is returned from the * {@link #borrowObject borrowObject} method. (Using the provided factory's * {@link KeyedPoolableObjectFactory#validateObject validateObject} method.) * Objects that fail to validate will be dropped from the pool, and a * different object will be borrowed. The default setting for this parameter * is false. *
  • *
  • * When {@link #setTestOnReturn testOnReturn} is set, the pool will * attempt to validate each object before it is returned to the pool in the * {@link #returnObject returnObject} method. (Using the provided factory's * {@link KeyedPoolableObjectFactory#validateObject validateObject} * method.) Objects that fail to validate will be dropped from the pool. * The default setting for this parameter is false. *
  • *
*

* Optionally, one may configure the pool to examine and possibly evict objects * as they sit idle in the pool and to ensure that a minimum number of idle * objects is maintained for each key. This is performed by an * "idle object eviction" thread, which runs asynchronously. Caution should be * used when configuring this optional feature. Eviction runs contend with client * threads for access to objects in the pool, so if they run too frequently * performance issues may result. The idle object eviction thread may be * configured using the following attributes: *

    *
  • * {@link #setTimeBetweenEvictionRunsMillis timeBetweenEvictionRunsMillis} * indicates how long the eviction thread should sleep before "runs" of examining * idle objects. When non-positive, no eviction thread will be launched. The * default setting for this parameter is -1 (i.e., by default, idle object * eviction is disabled). *
  • *
  • * {@link #setMinEvictableIdleTimeMillis minEvictableIdleTimeMillis} * specifies the minimum amount of time that an object may sit idle in the * pool before it is eligible for eviction due to idle time. When * non-positive, no object will be dropped from the pool due to idle time * alone. This setting has no effect unless * timeBetweenEvictionRunsMillis > 0. The default setting * for this parameter is 30 minutes. *
  • *
  • * {@link #setTestWhileIdle testWhileIdle} indicates whether or not idle * objects should be validated using the factory's * {@link KeyedPoolableObjectFactory#validateObject validateObject} method * during idle object eviction runs. Objects that fail to validate will be * dropped from the pool. This setting has no effect unless * timeBetweenEvictionRunsMillis > 0. The default setting * for this parameter is false. *
  • *
  • * {@link #setMinIdle minIdle} sets a target value for the minimum number of * idle objects (per key) that should always be available. If this parameter * is set to a positive number and * timeBetweenEvictionRunsMillis > 0, each time the idle object * eviction thread runs, it will try to create enough idle instances so that * there will be minIdle idle instances available under each * key. This parameter is also used by {@link #preparePool preparePool} * if true is provided as that method's * populateImmediately parameter. The default setting for this * parameter is 0. *
  • *
*

* The pools can be configured to behave as LIFO queues with respect to idle * objects - always returning the most recently used object from the pool, * or as FIFO queues, where borrowObject always returns the oldest object * in the idle object pool. *

    *
  • * {@link #setLifo Lifo} * determines whether or not the pools return idle objects in * last-in-first-out order. The default setting for this parameter is * true. *
  • *
*

* GenericKeyedObjectPool is not usable without a {@link KeyedPoolableObjectFactory}. A * non-null factory must be provided either as a constructor argument * or via a call to {@link #setFactory setFactory} before the pool is used. *

*

* Implementation note: To prevent possible deadlocks, care has been taken to * ensure that no call to a factory method will occur within a synchronization * block. See POOL-125 and DBCP-44 for more information. *

* * @param the type of keys in this pool * @param the type of objects held in this pool * * @see GenericObjectPool * @author Rodney Waldhoff * @author Dirk Verbeeck * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public class GenericKeyedObjectPool extends BaseKeyedObjectPool implements KeyedObjectPool { //--- public constants ------------------------------------------- /** * A "when exhausted action" type indicating that when the pool is * exhausted (i.e., the maximum number of active objects has * been reached), the {@link #borrowObject} * method should fail, throwing a {@link NoSuchElementException}. * @see #WHEN_EXHAUSTED_BLOCK * @see #WHEN_EXHAUSTED_GROW * @see #setWhenExhaustedAction */ public static final byte WHEN_EXHAUSTED_FAIL = 0; /** * A "when exhausted action" type indicating that when the pool * is exhausted (i.e., the maximum number * of active objects has been reached), the {@link #borrowObject} * method should block until a new object is available, or the * {@link #getMaxWait maximum wait time} has been reached. * @see #WHEN_EXHAUSTED_FAIL * @see #WHEN_EXHAUSTED_GROW * @see #setMaxWait * @see #getMaxWait * @see #setWhenExhaustedAction */ public static final byte WHEN_EXHAUSTED_BLOCK = 1; /** * A "when exhausted action" type indicating that when the pool is * exhausted (i.e., the maximum number * of active objects has been reached), the {@link #borrowObject} * method should simply create a new object anyway. * @see #WHEN_EXHAUSTED_FAIL * @see #WHEN_EXHAUSTED_GROW * @see #setWhenExhaustedAction */ public static final byte WHEN_EXHAUSTED_GROW = 2; /** * The default cap on the number of idle instances (per key) in the pool. * @see #getMaxIdle * @see #setMaxIdle */ public static final int DEFAULT_MAX_IDLE = 8; /** * The default cap on the total number of active instances (per key) * from the pool. * @see #getMaxActive * @see #setMaxActive */ public static final int DEFAULT_MAX_ACTIVE = 8; /** * The default cap on the the overall maximum number of objects that can * exist at one time. * @see #getMaxTotal * @see #setMaxTotal */ public static final int DEFAULT_MAX_TOTAL = -1; /** * The default "when exhausted action" for the pool. * @see #WHEN_EXHAUSTED_BLOCK * @see #WHEN_EXHAUSTED_FAIL * @see #WHEN_EXHAUSTED_GROW * @see #setWhenExhaustedAction */ public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK; /** * The default maximum amount of time (in milliseconds) the * {@link #borrowObject} method should block before throwing * an exception when the pool is exhausted and the * {@link #getWhenExhaustedAction "when exhausted" action} is * {@link #WHEN_EXHAUSTED_BLOCK}. * @see #getMaxWait * @see #setMaxWait */ public static final long DEFAULT_MAX_WAIT = -1L; /** * The default "test on borrow" value. * @see #getTestOnBorrow * @see #setTestOnBorrow */ public static final boolean DEFAULT_TEST_ON_BORROW = false; /** * The default "test on return" value. * @see #getTestOnReturn * @see #setTestOnReturn */ public static final boolean DEFAULT_TEST_ON_RETURN = false; /** * The default "test while idle" value. * @see #getTestWhileIdle * @see #setTestWhileIdle * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ public static final boolean DEFAULT_TEST_WHILE_IDLE = false; /** * The default "time between eviction runs" value. * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L; /** * The default number of objects to examine per run in the * idle object evictor. * @see #getNumTestsPerEvictionRun * @see #setNumTestsPerEvictionRun * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3; /** * The default value for {@link #getMinEvictableIdleTimeMillis}. * @see #getMinEvictableIdleTimeMillis * @see #setMinEvictableIdleTimeMillis */ public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L; /** * The default minimum level of idle objects in the pool. * @since Pool 1.3 * @see #setMinIdle * @see #getMinIdle */ public static final int DEFAULT_MIN_IDLE = 0; /** * The default LIFO status. True means that borrowObject returns the * most recently used ("last in") idle object in a pool (if there are * idle instances available). False means that pools behave as FIFO * queues - objects are taken from idle object pools in the order that * they are returned. * @see #setLifo */ public static final boolean DEFAULT_LIFO = true; //--- constructors ----------------------------------------------- /** * Create a new GenericKeyedObjectPool with no factory. * * @see #GenericKeyedObjectPool(KeyedPoolableObjectFactory) * @see #setFactory(KeyedPoolableObjectFactory) */ public GenericKeyedObjectPool() { this(null, DEFAULT_MAX_ACTIVE, DEFAULT_WHEN_EXHAUSTED_ACTION, DEFAULT_MAX_WAIT, DEFAULT_MAX_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy * objects if not null */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory) { this(factory, DEFAULT_MAX_ACTIVE, DEFAULT_WHEN_EXHAUSTED_ACTION, DEFAULT_MAX_WAIT, DEFAULT_MAX_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects * if not null * @param config a non-null {@link GenericKeyedObjectPool.Config} describing the configuration */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) { this(factory, config.maxActive, config.whenExhaustedAction, config.maxWait, config.maxIdle, config.maxTotal, config.minIdle, config.testOnBorrow, config.testOnReturn, config.timeBetweenEvictionRunsMillis, config.numTestsPerEvictionRun, config.minEvictableIdleTimeMillis, config.testWhileIdle, config.lifo); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects * if not null * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive) { this(factory,maxActive, DEFAULT_WHEN_EXHAUSTED_ACTION, DEFAULT_MAX_WAIT, DEFAULT_MAX_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects * if not null * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) { this(factory, maxActive, whenExhaustedAction, maxWait, DEFAULT_MAX_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects * if not null * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} * method (see {@link #setTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} * method (see {@link #setTestOnReturn}) */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) { this(factory, maxActive, whenExhaustedAction, maxWait, DEFAULT_MAX_IDLE,testOnBorrow,testOnReturn, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects * if not null * @param maxActive the maximum number of objects that can be borrowed from me at one time * (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects * if not null * @param maxActive the maximum number of objects that can be borrowed from me at one time * (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} * method (see {@link #setTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} * method (see {@link #setTestOnReturn}) */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, testOnBorrow, testOnReturn, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects * if not null * @param maxActive the maximum number of objects that can be borrowed from me at one time * (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted * (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} * method (see {@link #setTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} * method (see {@link #setTestOnReturn}) * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle * objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis}) * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction * thread (if any) (see {@link #setNumTestsPerEvictionRun}) * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before * it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis}) * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any * (see {@link #setTestWhileIdle}) */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects * if not null * @param maxActive the maximum number of objects that can be borrowed from me at one time * (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} * method (see {@link #setTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} * method (see {@link #setTestOnReturn}) * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle * objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis}) * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction * thread (if any) (see {@link #setNumTestsPerEvictionRun}) * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool * before it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis}) * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any * (see {@link #setTestWhileIdle}) */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, GenericKeyedObjectPool.DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects * if not null * @param maxActive the maximum number of objects that can be borrowed at one time (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal}) * @param minIdle the minimum number of idle objects to have in the pool at any one time (see {@link #setMinIdle}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} * method (see {@link #setTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} * method (see {@link #setTestOnReturn}) * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle * objects * for eviction (see {@link #setTimeBetweenEvictionRunsMillis}) * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction * thread (if any) (see {@link #setNumTestsPerEvictionRun}) * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before * it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis}) * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any * (see {@link #setTestWhileIdle}) * @since Pool 1.3 */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, DEFAULT_LIFO); } /** * Create a new GenericKeyedObjectPool using the specified values. * @param factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects * if not null * @param maxActive the maximum number of objects that can be borrowed at one time * (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal}) * @param minIdle the minimum number of idle objects to have in the pool at any one time (see {@link #setMinIdle}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} * method (see {@link #setTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} * method (see {@link #setTestOnReturn}) * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle * objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis}) * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction * thread (if any) (see {@link #setNumTestsPerEvictionRun}) * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before * it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis}) * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any * (see {@link #setTestWhileIdle}) * @param lifo whether or not the pools behave as LIFO (last in first out) queues (see {@link #setLifo}) * @since Pool 1.4 */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, boolean lifo) { _factory = factory; _maxActive = maxActive; _lifo = lifo; switch (whenExhaustedAction) { case WHEN_EXHAUSTED_BLOCK: case WHEN_EXHAUSTED_FAIL: case WHEN_EXHAUSTED_GROW: _whenExhaustedAction = whenExhaustedAction; break; default: throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized."); } _maxWait = maxWait; _maxIdle = maxIdle; _maxTotal = maxTotal; _minIdle = minIdle; _testOnBorrow = testOnBorrow; _testOnReturn = testOnReturn; _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; _numTestsPerEvictionRun = numTestsPerEvictionRun; _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; _testWhileIdle = testWhileIdle; _poolMap = new HashMap(); _poolList = new CursorableLinkedList(); startEvictor(_timeBetweenEvictionRunsMillis); } //--- public methods --------------------------------------------- //--- configuration methods -------------------------------------- /** * Returns the cap on the number of object instances allocated by the pool * (checked out or idle), per key. * A negative value indicates no limit. * * @return the cap on the number of active instances per key. * @see #setMaxActive */ public synchronized int getMaxActive() { return _maxActive; } /** * Sets the cap on the number of object instances managed by the pool per key. * @param maxActive The cap on the number of object instances per key. * Use a negative value for no limit. * * @see #getMaxActive */ public void setMaxActive(int maxActive) { synchronized(this) { _maxActive = maxActive; } allocate(); } /** * Returns the overall maximum number of objects (across pools) that can * exist at one time. A negative value indicates no limit. * @return the maximum number of instances in circulation at one time. * @see #setMaxTotal */ public synchronized int getMaxTotal() { return _maxTotal; } /** * Sets the cap on the total number of instances from all pools combined. * When maxTotal is set to a * positive value and {@link #borrowObject borrowObject} is invoked * when at the limit with no idle instances available, an attempt is made to * create room by clearing the oldest 15% of the elements from the keyed * pools. * * @param maxTotal The cap on the total number of instances across pools. * Use a negative value for no limit. * @see #getMaxTotal */ public void setMaxTotal(int maxTotal) { synchronized(this) { _maxTotal = maxTotal; } allocate(); } /** * Returns the action to take when the {@link #borrowObject} method * is invoked when the pool is exhausted (the maximum number * of "active" objects has been reached). * * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, * {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW} * @see #setWhenExhaustedAction */ public synchronized byte getWhenExhaustedAction() { return _whenExhaustedAction; } /** * Sets the action to take when the {@link #borrowObject} method * is invoked when the pool is exhausted (the maximum number * of "active" objects has been reached). * * @param whenExhaustedAction the action code, which must be one of * {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL}, * or {@link #WHEN_EXHAUSTED_GROW} * @see #getWhenExhaustedAction */ public void setWhenExhaustedAction(byte whenExhaustedAction) { synchronized(this) { switch(whenExhaustedAction) { case WHEN_EXHAUSTED_BLOCK: case WHEN_EXHAUSTED_FAIL: case WHEN_EXHAUSTED_GROW: _whenExhaustedAction = whenExhaustedAction; break; default: throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized."); } } allocate(); } /** * Returns the maximum amount of time (in milliseconds) the * {@link #borrowObject} method should block before throwing * an exception when the pool is exhausted and the * {@link #setWhenExhaustedAction "when exhausted" action} is * {@link #WHEN_EXHAUSTED_BLOCK}. * * When less than or equal to 0, the {@link #borrowObject} method * may block indefinitely. * * @return the maximum number of milliseconds borrowObject will block. * @see #setMaxWait * @see #setWhenExhaustedAction * @see #WHEN_EXHAUSTED_BLOCK */ public synchronized long getMaxWait() { return _maxWait; } /** * Sets the maximum amount of time (in milliseconds) the * {@link #borrowObject} method should block before throwing * an exception when the pool is exhausted and the * {@link #setWhenExhaustedAction "when exhausted" action} is * {@link #WHEN_EXHAUSTED_BLOCK}. * * When less than or equal to 0, the {@link #borrowObject} method * may block indefinitely. * * @param maxWait the maximum number of milliseconds borrowObject will block or negative for indefinitely. * @see #getMaxWait * @see #setWhenExhaustedAction * @see #WHEN_EXHAUSTED_BLOCK */ public void setMaxWait(long maxWait) { synchronized(this) { _maxWait = maxWait; } allocate(); } /** * Returns the cap on the number of "idle" instances per key. * @return the maximum number of "idle" instances that can be held * in a given keyed pool. * @see #setMaxIdle */ public synchronized int getMaxIdle() { return _maxIdle; } /** * Sets the cap on the number of "idle" instances in the pool. * If maxIdle is set too low on heavily loaded systems it is possible you * will see objects being destroyed and almost immediately new objects * being created. This is a result of the active threads momentarily * returning objects faster than they are requesting them them, causing the * number of idle objects to rise above maxIdle. The best value for maxIdle * for heavily loaded system will vary but the default is a good starting * point. * @param maxIdle the maximum number of "idle" instances that can be held * in a given keyed pool. Use a negative value for no limit. * @see #getMaxIdle * @see #DEFAULT_MAX_IDLE */ public void setMaxIdle(int maxIdle) { synchronized(this) { _maxIdle = maxIdle; } allocate(); } /** * Sets the minimum number of idle objects to maintain in each of the keyed * pools. This setting has no effect unless * timeBetweenEvictionRunsMillis > 0 and attempts to ensure * that each pool has the required minimum number of instances are only * made during idle object eviction runs. * @param poolSize - The minimum size of the each keyed pool * @since Pool 1.3 * @see #getMinIdle * @see #setTimeBetweenEvictionRunsMillis */ public void setMinIdle(int poolSize) { _minIdle = poolSize; } /** * Returns the minimum number of idle objects to maintain in each of the keyed * pools. This setting has no effect unless * timeBetweenEvictionRunsMillis > 0 and attempts to ensure * that each pool has the required minimum number of instances are only * made during idle object eviction runs. * @return minimum size of the each keyed pool * @since Pool 1.3 * @see #setTimeBetweenEvictionRunsMillis */ public int getMinIdle() { return _minIdle; } /** * When true, objects will be * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated} * before being returned by the {@link #borrowObject} * method. If the object fails to validate, * it will be dropped from the pool, and we will attempt * to borrow another. * * @return true if objects are validated before being borrowed. * @see #setTestOnBorrow */ public boolean getTestOnBorrow() { return _testOnBorrow; } /** * When true, objects will be * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated} * before being returned by the {@link #borrowObject} * method. If the object fails to validate, * it will be dropped from the pool, and we will attempt * to borrow another. * * @param testOnBorrow whether object should be validated before being returned by borrowObject. * @see #getTestOnBorrow */ public void setTestOnBorrow(boolean testOnBorrow) { _testOnBorrow = testOnBorrow; } /** * When true, objects will be * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated} * before being returned to the pool within the * {@link #returnObject}. * * @return true when objects will be validated before being returned. * @see #setTestOnReturn */ public boolean getTestOnReturn() { return _testOnReturn; } /** * When true, objects will be * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated} * before being returned to the pool within the * {@link #returnObject}. * * @param testOnReturn true so objects will be validated before being returned. * @see #getTestOnReturn */ public void setTestOnReturn(boolean testOnReturn) { _testOnReturn = testOnReturn; } /** * Returns 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 milliseconds to sleep between evictor runs. * @see #setTimeBetweenEvictionRunsMillis */ public synchronized long getTimeBetweenEvictionRunsMillis() { return _timeBetweenEvictionRunsMillis; } /** * 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 milliseconds to sleep between evictor runs. * @see #getTimeBetweenEvictionRunsMillis */ public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; startEvictor(_timeBetweenEvictionRunsMillis); } /** * Returns the max number of objects to examine during each run of the * idle object evictor thread (if any). * * @return number of objects to examine each eviction run. * @see #setNumTestsPerEvictionRun * @see #setTimeBetweenEvictionRunsMillis */ public synchronized int getNumTestsPerEvictionRun() { return _numTestsPerEvictionRun; } /** * Sets the max number of objects to examine during each run of the * idle object evictor thread (if any). *

* When a negative value is supplied, * ceil({@link #getNumIdle()})/abs({@link #getNumTestsPerEvictionRun}) * tests will be run. I.e., when the value is -n, roughly one nth of the * idle objects will be tested per run. When the value is positive, the number of tests * actually performed in each run will be the minimum of this value and the number of instances * idle in the pools. * * @param numTestsPerEvictionRun number of objects to examine each eviction run. * @see #setNumTestsPerEvictionRun * @see #setTimeBetweenEvictionRunsMillis */ public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { _numTestsPerEvictionRun = numTestsPerEvictionRun; } /** * Returns 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). * * @return minimum amount of time an object may sit idle in the pool before it is eligible for eviction. * @see #setMinEvictableIdleTimeMillis * @see #setTimeBetweenEvictionRunsMillis */ public synchronized long getMinEvictableIdleTimeMillis() { return _minEvictableIdleTimeMillis; } /** * Sets the minimum amount of time an object may sit idle in the pool * before it is eligible for eviction by the idle object evictor * (if any). * When non-positive, no objects will be evicted from the pool * due to idle time alone. * * @param minEvictableIdleTimeMillis minimum amount of time an object may sit idle in the pool before * it is eligible for eviction. * @see #getMinEvictableIdleTimeMillis * @see #setTimeBetweenEvictionRunsMillis */ public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } /** * When true, objects will be * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated} * by the idle object evictor (if any). If an object * fails to validate, it will be dropped from the pool. * * @return true when objects are validated when borrowed. * @see #setTestWhileIdle * @see #setTimeBetweenEvictionRunsMillis */ public synchronized boolean getTestWhileIdle() { return _testWhileIdle; } /** * When true, objects will be * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated} * by the idle object evictor (if any). If an object * fails to validate, it will be dropped from the pool. * * @param testWhileIdle true so objects are validated when borrowed. * @see #getTestWhileIdle * @see #setTimeBetweenEvictionRunsMillis */ public synchronized void setTestWhileIdle(boolean testWhileIdle) { _testWhileIdle = testWhileIdle; } /** * Sets the configuration. * @param conf the new configuration to use. * @see GenericKeyedObjectPool.Config */ public synchronized void setConfig(GenericKeyedObjectPool.Config conf) { setMaxIdle(conf.maxIdle); setMaxActive(conf.maxActive); setMaxTotal(conf.maxTotal); setMinIdle(conf.minIdle); setMaxWait(conf.maxWait); setWhenExhaustedAction(conf.whenExhaustedAction); setTestOnBorrow(conf.testOnBorrow); setTestOnReturn(conf.testOnReturn); setTestWhileIdle(conf.testWhileIdle); setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun); setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis); setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis); } /** * Whether or not the idle object pools act as LIFO queues. True means * that borrowObject returns the most recently used ("last in") idle object * in a pool (if there are idle instances available). False means that * the pools behave as FIFO queues - objects are taken from idle object * pools in the order that they are returned. * * @return true if the pools are configured to act as LIFO queues * @since 1.4 */ public synchronized boolean getLifo() { return _lifo; } /** * Sets the LIFO property of the pools. True means that borrowObject returns * the most recently used ("last in") idle object in a pool (if there are * idle instances available). False means that the pools behave as FIFO * queues - objects are taken from idle object pools in the order that * they are returned. * * @param lifo the new value for the lifo property * @since 1.4 */ public synchronized void setLifo(boolean lifo) { this._lifo = lifo; } //-- ObjectPool methods ------------------------------------------ /** *

Borrows an object from the keyed pool associated with the given key.

* *

If there is an idle instance available in the pool associated with the given key, then * either the most-recently returned (if {@link #getLifo() lifo} == true) or "oldest" (lifo == false) * instance sitting idle in the pool will be activated and returned. If activation fails, or * {@link #getTestOnBorrow() testOnBorrow} is set to true and validation fails, the instance is destroyed and the * next available instance is examined. This continues until either a valid instance is returned or there * are no more idle instances available.

* *

If there are no idle instances available in the pool associated with the given key, behavior * depends on the {@link #getMaxActive() maxActive}, {@link #getMaxTotal() maxTotal}, and (if applicable) * {@link #getWhenExhaustedAction() whenExhaustedAction} and {@link #getMaxWait() maxWait} properties. If the * number of instances checked out from the pool under the given key is less than maxActive and * the total number of instances in circulation (under all keys) is less than maxTotal, a new instance * is created, activated and (if applicable) validated and returned to the caller.

* *

If the associated keyed pool is exhausted (no available idle instances and no capacity to create new ones), * this method will either block ({@link #WHEN_EXHAUSTED_BLOCK}), throw a NoSuchElementException * ({@link #WHEN_EXHAUSTED_FAIL}), or grow ({@link #WHEN_EXHAUSTED_GROW} - ignoring maxActive, maxTotal properties). * The length of time that this method will block when whenExhaustedAction == WHEN_EXHAUSTED_BLOCK * is determined by the {@link #getMaxWait() maxWait} property.

* *

When the pool is exhausted, multiple calling threads may be simultaneously blocked waiting for instances * to become available. As of pool 1.5, a "fairness" algorithm has been implemented to ensure that threads receive * available instances in request arrival order.

* * @param key pool key * @return object instance from the keyed pool * @throws NoSuchElementException if a keyed object instance cannot be returned. */ @Override public V borrowObject(K key) throws Exception { long starttime = System.currentTimeMillis(); Latch latch = new Latch(key); byte whenExhaustedAction; long maxWait; synchronized (this) { // Get local copy of current config. Can't sync when used later as // it can result in a deadlock. Has the added advantage that config // is consistent for entire method execution whenExhaustedAction = _whenExhaustedAction; maxWait = _maxWait; // Add this request to the queue _allocationQueue.add(latch); } // Work the allocation queue, allocating idle instances and // instance creation permits in request arrival order allocate(); for(;;) { synchronized (this) { assertOpen(); } // If no object was allocated if (null == latch.getPair()) { // Check to see if we were allowed to create one if (latch.mayCreate()) { // allow new object to be created } else { // the pool is exhausted switch(whenExhaustedAction) { case WHEN_EXHAUSTED_GROW: // allow new object to be created synchronized (this) { // Make sure another thread didn't allocate us an object // or permit a new object to be created if (latch.getPair() == null && !latch.mayCreate()) { _allocationQueue.remove(latch); latch.getPool().incrementInternalProcessingCount(); } } break; case WHEN_EXHAUSTED_FAIL: synchronized (this) { // Make sure allocate hasn't already assigned an object // in a different thread or permitted a new object to be created if (latch.getPair() != null || latch.mayCreate()) { break; } _allocationQueue.remove(latch); } throw new NoSuchElementException("Pool exhausted"); case WHEN_EXHAUSTED_BLOCK: try { synchronized (latch) { // Before we wait, make sure another thread didn't allocate us an object // or permit a new object to be created if (latch.getPair() == null && !latch.mayCreate()) { if (maxWait <= 0) { latch.wait(); } else { // this code may be executed again after a notify then continue cycle // so, need to calculate the amount of time to wait final long elapsed = (System.currentTimeMillis() - starttime); final long waitTime = maxWait - elapsed; if (waitTime > 0) { latch.wait(waitTime); } } } else { break; } } // see if we were awakened by a closing pool if(isClosed() == true) { throw new IllegalStateException("Pool closed"); } } catch(InterruptedException e) { boolean doAllocate = false; synchronized (this) { // Need to handle the all three possibilities if (latch.getPair() == null && !latch.mayCreate()) { // Case 1: latch still in allocation queue // Remove latch from the allocation queue _allocationQueue.remove(latch); } else if (latch.getPair() == null && latch.mayCreate()) { // Case 2: latch has been given permission to create // a new object latch.getPool().decrementInternalProcessingCount(); doAllocate = true; } else { // Case 3: An object has been allocated latch.getPool().decrementInternalProcessingCount(); latch.getPool().incrementActiveCount(); returnObject(latch.getkey(), latch.getPair().getValue()); } } if (doAllocate) { allocate(); } Thread.currentThread().interrupt(); throw e; } if (maxWait > 0 && ((System.currentTimeMillis() - starttime) >= maxWait)) { synchronized (this) { // Make sure allocate hasn't already assigned an object // in a different thread or permitted a new object to be created if (latch.getPair() == null && !latch.mayCreate()) { _allocationQueue.remove(latch); } else { break; } } throw new NoSuchElementException("Timeout waiting for idle object"); } else { continue; // keep looping } default: throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized."); } } } boolean newlyCreated = false; if (null == latch.getPair()) { try { V obj = _factory.makeObject(key); latch.setPair(new ObjectTimestampPair(obj)); newlyCreated = true; } finally { if (!newlyCreated) { // object cannot be created synchronized (this) { latch.getPool().decrementInternalProcessingCount(); // No need to reset latch - about to throw exception } allocate(); } } } // activate & validate the object try { _factory.activateObject(key, latch.getPair().value); if (_testOnBorrow && !_factory.validateObject(key, latch.getPair().value)) { throw new Exception("ValidateObject failed"); } synchronized (this) { latch.getPool().decrementInternalProcessingCount(); latch.getPool().incrementActiveCount(); } return latch.getPair().value; } catch (Throwable e) { PoolUtils.checkRethrow(e); // object cannot be activated or is invalid try { _factory.destroyObject(key, latch.getPair().value); } catch (Throwable e2) { PoolUtils.checkRethrow(e2); // cannot destroy broken object } synchronized (this) { latch.getPool().decrementInternalProcessingCount(); if (!newlyCreated) { latch.reset(); _allocationQueue.add(0, latch); } } allocate(); if (newlyCreated) { throw new NoSuchElementException( "Could not create a validated object, cause: " + e.getMessage()); } else { continue; // keep looping } } } } /** * Allocate available instances to latches in the allocation queue. Then * set _mayCreate to true for as many additional latches remaining in queue * as _maxActive allows for each key. This method MUST NOT be called * from inside a sync block. */ private void allocate() { boolean clearOldest = false; synchronized (this) { if (isClosed()) return; Iterator> allocationQueueIter = _allocationQueue.iterator(); while (allocationQueueIter.hasNext()) { // First use any objects in the pool to clear the queue Latch latch = allocationQueueIter.next(); ObjectQueue pool = (_poolMap.get(latch.getkey())); if (null == pool) { pool = new ObjectQueue(); _poolMap.put(latch.getkey(), pool); _poolList.add(latch.getkey()); } latch.setPool(pool); if (!pool.queue.isEmpty()) { allocationQueueIter.remove(); latch.setPair( pool.queue.removeFirst()); pool.incrementInternalProcessingCount(); _totalIdle--; synchronized (latch) { latch.notify(); } // Next item in queue continue; } // If there is a totalMaxActive and we are at the limit then // we have to make room if ((_maxTotal > 0) && (_totalActive + _totalIdle + _totalInternalProcessing >= _maxTotal)) { clearOldest = true; break; } // Second utilise any spare capacity to create new objects if ((_maxActive < 0 || pool.activeCount + pool.internalProcessingCount < _maxActive) && (_maxTotal < 0 || _totalActive + _totalIdle + _totalInternalProcessing < _maxTotal)) { // allow new object to be created allocationQueueIter.remove(); latch.setMayCreate(true); pool.incrementInternalProcessingCount(); synchronized (latch) { latch.notify(); } // Next item in queue continue; } // If there is no per-key limit and we reach this point we // must have allocated all the objects we possibly can and there // is no point looking at the rest of the allocation queue if (_maxActive < 0) { break; } } } if (clearOldest) { /* Clear oldest calls factory methods so it must be called from * outside the sync block. * It also needs to be outside the sync block as it calls * allocate(). If called inside the sync block, the call to * allocate() would be able to enter the sync block (since the * thread already has the lock) which may have unexpected, * unpleasant results. */ clearOldest(); } } /** * Clears any objects sitting idle in the pool by removing them from the * idle instance pool and then invoking the configured PoolableObjectFactory's * {@link KeyedPoolableObjectFactory#destroyObject(Object, Object)} method on * each idle instance. * *

Implementation notes: *

  • This method does not destroy or effect in any way instances that are * checked out when it is invoked.
  • *
  • Invoking this method does not prevent objects being * returned to the idle instance pool, even during its execution. It locks * the pool only during instance removal. Additional instances may be returned * while removed items are being destroyed.
  • *
  • Exceptions encountered destroying idle instances are swallowed.

*/ @Override public void clear() { Map>> toDestroy = new HashMap>>(); synchronized (this) { for (Iterator it = _poolMap.keySet().iterator(); it.hasNext();) { K key = it.next(); ObjectQueue pool = _poolMap.get(key); // Copy objects to new list so pool.queue can be cleared inside // the sync List> objects = new ArrayList>(); objects.addAll(pool.queue); toDestroy.put(key, objects); it.remove(); _poolList.remove(key); _totalIdle = _totalIdle - pool.queue.size(); _totalInternalProcessing = _totalInternalProcessing + pool.queue.size(); pool.queue.clear(); } } destroy(toDestroy, _factory); } /** * Clears oldest 15% of objects in pool. The method sorts the * objects into a TreeMap and then iterates the first 15% for removal. * * @since Pool 1.3 */ public void clearOldest() { // Map of objects to destroy my key final Map>> toDestroy = new HashMap>>(); // build sorted map of idle objects final Map, K> map = new TreeMap, K>(); synchronized (this) { for (Iterator keyiter = _poolMap.keySet().iterator(); keyiter.hasNext();) { final K key = keyiter.next(); final List> list = _poolMap.get(key).queue; for (Iterator> it = list.iterator(); it.hasNext();) { // each item into the map uses the objectimestamppair object // as the key. It then gets sorted based on the timstamp field // each value in the map is the parent list it belongs in. map.put(it.next(), key); } } // Now iterate created map and kill the first 15% plus one to account for zero Set, K>> setPairKeys = map.entrySet(); int itemsToRemove = ((int) (map.size() * 0.15)) + 1; Iterator, K>> iter = setPairKeys.iterator(); while (iter.hasNext() && itemsToRemove > 0) { Entry, K> entry = iter.next(); // kind of backwards on naming. In the map, each key is the objecttimestamppair // because it has the ordering with the timestamp value. Each value that the // key references is the key of the list it belongs to. K key = entry.getValue(); ObjectTimestampPair pairTimeStamp = entry.getKey(); ObjectQueue objectQueue = _poolMap.get(key); final List> list = objectQueue.queue; list.remove(pairTimeStamp); if (toDestroy.containsKey(key)) { toDestroy.get(key).add(pairTimeStamp); } else { List> listForKey = new ArrayList>(); listForKey.add(pairTimeStamp); toDestroy.put(key, listForKey); } objectQueue.incrementInternalProcessingCount(); _totalIdle--; itemsToRemove--; } } destroy(toDestroy, _factory); } /** * Clears the specified pool, removing all pooled instances corresponding to the given key. * * @param key the key to clear */ @Override public void clear(K key) { Map>> toDestroy = new HashMap>>(); final ObjectQueue pool; synchronized (this) { pool = _poolMap.remove(key); if (pool == null) { return; } else { _poolList.remove(key); } // Copy objects to new list so pool.queue can be cleared inside // the sync List> objects = new ArrayList>(); objects.addAll(pool.queue); toDestroy.put(key, objects); _totalIdle = _totalIdle - pool.queue.size(); _totalInternalProcessing = _totalInternalProcessing + pool.queue.size(); pool.queue.clear(); } destroy(toDestroy, _factory); } /** * Assuming Map>, destroy all * ObjectTimestampPair.value using the supplied factory. * * @param m Map containing keyed pools to clear * @param factory KeyedPoolableObjectFactory used to destroy the objects */ private void destroy(Map>> m, KeyedPoolableObjectFactory factory) { for (Iterator>>> entries = m.entrySet().iterator(); entries.hasNext();) { Entry>> entry = entries.next(); K key = entry.getKey(); List> c = entry.getValue(); for (Iterator> it = c.iterator(); it.hasNext();) { try { factory.destroyObject( key,it.next().value); } catch(Exception e) { // ignore error, keep destroying the rest } finally { synchronized(this) { ObjectQueue objectQueue = _poolMap.get(key); if (objectQueue != null) { objectQueue.decrementInternalProcessingCount(); if (objectQueue.internalProcessingCount == 0 && objectQueue.activeCount == 0 && objectQueue.queue.isEmpty()) { _poolMap.remove(key); _poolList.remove(key); } } else { _totalInternalProcessing--; } } allocate(); } } } } /** * Returns the total number of instances current borrowed from this pool but not yet returned. * * @return the total number of instances currently borrowed from this pool */ @Override public synchronized int getNumActive() { return _totalActive; } /** * Returns the total number of instances currently idle in this pool. * * @return the total number of instances currently idle in this pool */ @Override public synchronized int getNumIdle() { return _totalIdle; } /** * Returns the number of instances currently borrowed from but not yet returned * to the pool corresponding to the given key. * * @param key the key to query * @return the number of instances corresponding to the given key currently borrowed in this pool */ @Override public synchronized int getNumActive(Object key) { final ObjectQueue pool = (_poolMap.get(key)); return pool != null ? pool.activeCount : 0; } /** * Returns the number of instances corresponding to the given key currently idle in this pool. * * @param key the key to query * @return the number of instances corresponding to the given key currently idle in this pool */ @Override public synchronized int getNumIdle(Object key) { final ObjectQueue pool = (_poolMap.get(key)); return pool != null ? pool.queue.size() : 0; } /** *

Returns an object to a keyed pool.

* *

For the pool to function correctly, the object instance must have been borrowed * from the pool (under the same key) and not yet returned. Repeated returnObject calls on * the same object/key pair (with no borrowObject calls in between) will result in multiple * references to the object in the idle instance pool.

* *

If {@link #getMaxIdle() maxIdle} is set to a positive value and the number of idle instances under the given * key has reached this value, the returning instance is destroyed.

* *

If {@link #getTestOnReturn() testOnReturn} == true, the returning instance is validated before being returned * to the idle instance pool under the given key. In this case, if validation fails, the instance is destroyed.

* * @param key pool key * @param obj instance to return to the keyed pool * @throws Exception */ @Override public void returnObject(K key, V obj) throws Exception { try { addObjectToPool(key, obj, true); } catch (Exception e) { if (_factory != null) { try { _factory.destroyObject(key, obj); } catch (Exception e2) { // swallowed } // TODO: Correctness here depends on control in addObjectToPool. // These two methods should be refactored, removing the // "behavior flag", decrementNumActive, from addObjectToPool. ObjectQueue pool = (_poolMap.get(key)); if (pool != null) { synchronized(this) { pool.decrementActiveCount(); if (pool.queue.isEmpty() && pool.activeCount == 0 && pool.internalProcessingCount == 0) { _poolMap.remove(key); _poolList.remove(key); } } allocate(); } } } } /** *

Adds an object to the keyed pool.

* *

Validates the object if testOnReturn == true and passivates it before returning it to the pool. * if validation or passivation fails, or maxIdle is set and there is no room in the pool, the instance * is destroyed.

* *

Calls {@link #allocate()} on successful completion

* * @param key pool key * @param obj instance to add to the keyed pool * @param decrementNumActive whether or not to decrement the active count associated with the keyed pool * @throws Exception */ private void addObjectToPool(K key, V obj, boolean decrementNumActive) throws Exception { // if we need to validate this object, do so boolean success = true; // whether or not this object passed validation if (_testOnReturn && !_factory.validateObject(key, obj)) { success = false; } else { _factory.passivateObject(key, obj); } boolean shouldDestroy = !success; ObjectQueue pool; // Add instance to pool if there is room and it has passed validation // (if testOnreturn is set) boolean doAllocate = false; synchronized (this) { // grab the pool (list) of objects associated with the given key pool = _poolMap.get(key); // if it doesn't exist, create it if (null == pool) { pool = new ObjectQueue(); _poolMap.put(key, pool); _poolList.add(key); } if (isClosed()) { shouldDestroy = true; } else { // if there's no space in the pool, flag the object for destruction // else if we passivated successfully, return it to the pool if (_maxIdle >= 0 && (pool.queue.size() >= _maxIdle)) { shouldDestroy = true; } else if (success) { // borrowObject always takes the first element from the queue, // so for LIFO, push on top, FIFO add to end if (_lifo) { pool.queue.addFirst(new ObjectTimestampPair(obj)); } else { pool.queue.addLast(new ObjectTimestampPair(obj)); } _totalIdle++; if (decrementNumActive) { pool.decrementActiveCount(); } doAllocate = true; } } } if (doAllocate) { allocate(); } // Destroy the instance if necessary if (shouldDestroy) { try { _factory.destroyObject(key, obj); } catch(Exception e) { // ignored? } // Decrement active count *after* destroy if applicable if (decrementNumActive) { synchronized(this) { pool.decrementActiveCount(); if (pool.queue.isEmpty() && pool.activeCount == 0 && pool.internalProcessingCount == 0) { _poolMap.remove(key); _poolList.remove(key); } } allocate(); } } } /** * {@inheritDoc} *

Activation of this method decrements the active count associated with the given keyed pool * and attempts to destroy obj.

* * @param key pool key * @param obj instance to invalidate * @throws Exception if an exception occurs destroying the object */ @Override public void invalidateObject(K key, V obj) throws Exception { try { _factory.destroyObject(key, obj); } finally { synchronized (this) { ObjectQueue pool = (_poolMap.get(key)); if (null == pool) { pool = new ObjectQueue(); _poolMap.put(key, pool); _poolList.add(key); } pool.decrementActiveCount(); } allocate(); // _totalActive has changed } } /** * Create an object using the {@link KeyedPoolableObjectFactory#makeObject factory}, * passivate it, and then place it in the idle object pool. * addObject is useful for "pre-loading" a pool with idle objects. * * @param key the key a new instance should be added to * @throws Exception when {@link KeyedPoolableObjectFactory#makeObject} fails. * @throws IllegalStateException when no {@link #setFactory factory} has been set or after {@link #close} has been * called on this pool. */ @Override public void addObject(K key) throws Exception { assertOpen(); if (_factory == null) { throw new IllegalStateException("Cannot add objects without a factory."); } V obj = _factory.makeObject(key); try { assertOpen(); addObjectToPool(key, obj, false); } catch (IllegalStateException ex) { // Pool closed try { _factory.destroyObject(key, obj); } catch (Exception ex2) { // swallow } throw ex; } } /** * Registers a key for pool control. * * If populateImmediately is true and * minIdle > 0, the pool under the given key will be * populated immediately with minIdle idle instances. * * @param key - The key to register for pool control. * @param populateImmediately - If this is true, the pool * will be populated immediately. * @since Pool 1.3 */ public synchronized void preparePool(K key, boolean populateImmediately) { ObjectQueue pool = (_poolMap.get(key)); if (null == pool) { pool = new ObjectQueue(); _poolMap.put(key,pool); _poolList.add(key); } if (populateImmediately) { try { // Create the pooled objects ensureMinIdle(key); } catch (Exception e) { //Do nothing } } } /** *

Closes the keyed object pool. Once the pool is closed, {@link #borrowObject(Object)} * will fail with IllegalStateException, but {@link #returnObject(Object, Object)} and * {@link #invalidateObject(Object, Object)} will continue to work, with returned objects * destroyed on return.

* *

Destroys idle instances in the pool by invoking {@link #clear()}.

* * @throws Exception */ @Override public void close() throws Exception { super.close(); synchronized (this) { clear(); if (null != _evictionCursor) { _evictionCursor.close(); _evictionCursor = null; } if (null != _evictionKeyCursor) { _evictionKeyCursor.close(); _evictionKeyCursor = null; } startEvictor(-1L); while(_allocationQueue.size() > 0) { Latch l = _allocationQueue.removeFirst(); synchronized (l) { // notify the waiting thread l.notify(); } } } } /** *

Sets the keyed poolable object factory associated with this pool.

* *

If this method is called when objects are checked out of any of the keyed pools, * an IllegalStateException is thrown. Calling this method also has the side effect of * destroying any idle instances in existing keyed pools, using the original factory.

* * @param factory KeyedPoolableObjectFactory to use when creating keyed object pool instances * @throws IllegalStateException if there are active (checked out) instances associated with this keyed object pool * @deprecated to be removed in version 2.0 */ @Deprecated @Override public void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException { Map>> toDestroy = new HashMap>>(); final KeyedPoolableObjectFactory oldFactory = _factory; synchronized (this) { assertOpen(); if (0 < getNumActive()) { throw new IllegalStateException("Objects are already active"); } else { for (Iterator it = _poolMap.keySet().iterator(); it.hasNext();) { K key = it.next(); ObjectQueue pool = _poolMap.get(key); if (pool != null) { // Copy objects to new list so pool.queue can be cleared // inside the sync List> objects = new ArrayList>(); objects.addAll(pool.queue); toDestroy.put(key, objects); it.remove(); _poolList.remove(key); _totalIdle = _totalIdle - pool.queue.size(); _totalInternalProcessing = _totalInternalProcessing + pool.queue.size(); pool.queue.clear(); } } _factory = factory; } } destroy(toDestroy, oldFactory); } /** *

Perform numTests idle object eviction tests, evicting * examined objects that meet the criteria for eviction. If * testWhileIdle is true, examined objects are validated * when visited (and removed if invalid); otherwise only objects that * have been idle for more than minEvicableIdletimeMillis * are removed.

* *

Successive activations of this method examine objects in keyed pools * in sequence, cycling through the keys and examining objects in * oldest-to-youngest order within the keyed pools.

* * @throws Exception when there is a problem evicting idle objects. */ public void evict() throws Exception { K key = null; boolean testWhileIdle; long minEvictableIdleTimeMillis; synchronized (this) { // Get local copy of current config. Can't sync when used later as // it can result in a deadlock. Has the added advantage that config // is consistent for entire method execution testWhileIdle = _testWhileIdle; minEvictableIdleTimeMillis = _minEvictableIdleTimeMillis; // Initialize key to last key value if (_evictionKeyCursor != null && _evictionKeyCursor._lastReturned != null) { key = _evictionKeyCursor._lastReturned.value(); } } for (int i=0, m=getNumTests(); i pair; synchronized (this) { // make sure pool map is not empty; otherwise do nothing if (_poolMap == null || _poolMap.size() == 0) { continue; } // if we don't have a key cursor, then create one if (null == _evictionKeyCursor) { resetEvictionKeyCursor(); key = null; } // if we don't have an object cursor, create one if (null == _evictionCursor) { // if the _evictionKeyCursor has a next value, use this key if (_evictionKeyCursor.hasNext()) { key = _evictionKeyCursor.next(); resetEvictionObjectCursor(key); } else { // Reset the key cursor and try again resetEvictionKeyCursor(); if (_evictionKeyCursor != null) { if (_evictionKeyCursor.hasNext()) { key = _evictionKeyCursor.next(); resetEvictionObjectCursor(key); } } } } if (_evictionCursor == null) { continue; // should never happen; do nothing } // If eviction cursor is exhausted, try to move // to the next key and reset if ((_lifo && !_evictionCursor.hasPrevious()) || (!_lifo && !_evictionCursor.hasNext())) { if (_evictionKeyCursor != null) { if (_evictionKeyCursor.hasNext()) { key = _evictionKeyCursor.next(); resetEvictionObjectCursor(key); } else { // Need to reset Key cursor resetEvictionKeyCursor(); if (_evictionKeyCursor != null) { if (_evictionKeyCursor.hasNext()) { key = _evictionKeyCursor.next(); resetEvictionObjectCursor(key); } } } } } if ((_lifo && !_evictionCursor.hasPrevious()) || (!_lifo && !_evictionCursor.hasNext())) { continue; // reset failed, do nothing } // if LIFO and the _evictionCursor has a previous object, // or FIFO and _evictionCursor has a next object, test it pair = _lifo ? _evictionCursor.previous() : _evictionCursor.next(); _evictionCursor.remove(); ObjectQueue objectQueue = _poolMap.get(key); objectQueue.incrementInternalProcessingCount(); _totalIdle--; } boolean removeObject=false; if ((minEvictableIdleTimeMillis > 0) && (System.currentTimeMillis() - pair.tstamp > minEvictableIdleTimeMillis)) { removeObject=true; } if (testWhileIdle && removeObject == false) { boolean active = false; try { _factory.activateObject(key,pair.value); active = true; } catch(Exception e) { removeObject=true; } if (active) { if (!_factory.validateObject(key,pair.value)) { removeObject=true; } else { try { _factory.passivateObject(key,pair.value); } catch(Exception e) { removeObject=true; } } } } if (removeObject) { try { _factory.destroyObject(key, pair.value); } catch(Exception e) { // ignored } } synchronized (this) { ObjectQueue objectQueue = _poolMap.get(key); objectQueue.decrementInternalProcessingCount(); if (removeObject) { if (objectQueue.queue.isEmpty() && objectQueue.activeCount == 0 && objectQueue.internalProcessingCount == 0) { _poolMap.remove(key); _poolList.remove(key); } } else { _evictionCursor.add(pair); _totalIdle++; if (_lifo) { // Skip over the element we just added back _evictionCursor.previous(); } } } } allocate(); } /** * Resets the eviction key cursor and closes any * associated eviction object cursor */ private void resetEvictionKeyCursor() { if (_evictionKeyCursor != null) { _evictionKeyCursor.close(); } _evictionKeyCursor = _poolList.cursor(); if (null != _evictionCursor) { _evictionCursor.close(); _evictionCursor = null; } } /** * Resets the eviction object cursor for the given key * * @param key eviction key */ private void resetEvictionObjectCursor(Object key) { if (_evictionCursor != null) { _evictionCursor.close(); } if (_poolMap == null) { return; } ObjectQueue pool = _poolMap.get(key); if (pool != null) { CursorableLinkedList> queue = pool.queue; _evictionCursor = queue.cursor(_lifo ? queue.size() : 0); } } /** * Iterates through all the known keys and creates any necessary objects to maintain * the minimum level of pooled objects. * @see #getMinIdle * @see #setMinIdle * @throws Exception If there was an error whilst creating the pooled objects. */ @SuppressWarnings("unchecked") private void ensureMinIdle() throws Exception { //Check if should sustain the pool if (_minIdle > 0) { Object[] keysCopy; synchronized(this) { // Get the current set of keys keysCopy = _poolMap.keySet().toArray(); } // Loop through all elements in _poolList // Find out the total number of max active and max idle for that class // If the number is less than the minIdle, do creation loop to boost numbers for (int i=0; i < keysCopy.length; i++) { //Get the next key to process ensureMinIdle((K)keysCopy[i]); } } } /** * Re-creates any needed objects to maintain the minimum levels of * pooled objects for the specified key. * * This method uses {@link #calculateDeficit} to calculate the number * of objects to be created. {@link #calculateDeficit} can be overridden to * provide a different method of calculating the number of objects to be * created. * @param key The key to process * @throws Exception If there was an error whilst creating the pooled objects */ private void ensureMinIdle(K key) throws Exception { // Calculate current pool objects ObjectQueue pool; synchronized(this) { pool = (_poolMap.get(key)); } if (pool == null) { return; } // this method isn't synchronized so the // calculateDeficit is done at the beginning // as a loop limit and a second time inside the loop // to stop when another thread already returned the // needed objects int objectDeficit = calculateDeficit(pool, false); for (int i = 0; i < objectDeficit && calculateDeficit(pool, true) > 0; i++) { try { addObject(key); } finally { synchronized (this) { pool.decrementInternalProcessingCount(); } allocate(); } } } //--- non-public methods ---------------------------------------- /** * Start the eviction thread or service, or when * delay is non-positive, stop it * if it is already running. * * @param delay milliseconds between evictor runs. */ protected synchronized void startEvictor(long delay) { if (null != _evictor) { EvictionTimer.cancel(_evictor); _evictor = null; } if (delay > 0) { _evictor = new Evictor(); EvictionTimer.schedule(_evictor, delay, delay); } } /** * Returns pool info including {@link #getNumActive()}, {@link #getNumIdle()} * and currently defined keys. * * @return string containing debug information */ synchronized String debugInfo() { StringBuffer buf = new StringBuffer(); buf.append("Active: ").append(getNumActive()).append("\n"); buf.append("Idle: ").append(getNumIdle()).append("\n"); Iterator it = _poolMap.keySet().iterator(); while (it.hasNext()) { K key = it.next(); buf.append("\t").append(key).append(" ").append(_poolMap.get(key)).append("\n"); } return buf.toString(); } /** * Returns the number of tests to be performed in an Evictor run, * based on the current values of _numTestsPerEvictionRun * and _totalIdle. * * @see #setNumTestsPerEvictionRun * @return the number of tests for the Evictor to run */ private synchronized int getNumTests() { if (_numTestsPerEvictionRun >= 0) { return Math.min(_numTestsPerEvictionRun, _totalIdle); } else { return(int)(Math.ceil(_totalIdle/Math.abs((double)_numTestsPerEvictionRun))); } } /** * This returns the number of objects to create during the pool * sustain cycle. This will ensure that the minimum number of idle * instances is maintained without going past the maxActive value. * * @param pool the ObjectPool to calculate the deficit for * @param incrementInternal - Should the count of objects currently under * some form of internal processing be * incremented? * @return The number of objects to be created */ private synchronized int calculateDeficit(ObjectQueue pool, boolean incrementInternal) { int objectDefecit = 0; //Calculate no of objects needed to be created, in order to have //the number of pooled objects < maxActive(); objectDefecit = getMinIdle() - pool.queue.size(); if (getMaxActive() > 0) { int growLimit = Math.max(0, getMaxActive() - pool.activeCount - pool.queue.size() - pool.internalProcessingCount); objectDefecit = Math.min(objectDefecit, growLimit); } // Take the maxTotal limit into account if (getMaxTotal() > 0) { int growLimit = Math.max(0, getMaxTotal() - getNumActive() - getNumIdle() - _totalInternalProcessing); objectDefecit = Math.min(objectDefecit, growLimit); } if (incrementInternal && objectDefecit > 0) { pool.incrementInternalProcessingCount(); } return objectDefecit; } //--- inner classes ---------------------------------------------- /** * A "struct" that keeps additional information about the actual queue of pooled objects. */ private class ObjectQueue { /** Number of instances checked out to clients from this queue */ private int activeCount = 0; /** Idle instance queue */ private final CursorableLinkedList> queue = new CursorableLinkedList>(); /** Number of instances in process of being created */ private int internalProcessingCount = 0; /** Increment the active count for this queue */ void incrementActiveCount() { synchronized (GenericKeyedObjectPool.this) { _totalActive++; } activeCount++; } /** Decrement the active count for this queue */ void decrementActiveCount() { synchronized (GenericKeyedObjectPool.this) { _totalActive--; } if (activeCount > 0) { activeCount--; } } /** Record the fact that one more instance is queued for creation */ void incrementInternalProcessingCount() { synchronized (GenericKeyedObjectPool.this) { _totalInternalProcessing++; } internalProcessingCount++; } /** Decrement the number of instances in process of being created */ void decrementInternalProcessingCount() { synchronized (GenericKeyedObjectPool.this) { _totalInternalProcessing--; } internalProcessingCount--; } } /** * A simple "struct" encapsulating an object instance and a timestamp. * * Implements Comparable, objects are sorted from old to new. * * This is also used by {@link GenericObjectPool}. */ static class ObjectTimestampPair implements Comparable { //CHECKSTYLE: stop VisibilityModifier /** * Object instance * @deprecated this field will be made private and final in version 2.0 */ @Deprecated T value; /** * timestamp * @deprecated this field will be made private and final in version 2.0 */ @Deprecated long tstamp; //CHECKSTYLE: resume VisibilityModifier /** * Create a new ObjectTimestampPair using the given object and the current system time. * @param val object instance */ ObjectTimestampPair(T val) { this(val, System.currentTimeMillis()); } /** * Create a new ObjectTimeStampPair using the given object and timestamp value. * @param val object instance * @param time long representation of timestamp */ ObjectTimestampPair(T val, long time) { value = val; tstamp = time; } /** * Returns a string representation. * * @return String representing this ObjectTimestampPair */ @Override public String toString() { return value + ";" + tstamp; } /** * Compares this to another object by casting the argument to an * ObjectTimestampPair. * * @param obj object to cmpare * @return result of comparison */ @SuppressWarnings("unchecked") public int compareTo(Object obj) { return compareTo((ObjectTimestampPair) obj); } /** * Compares this to another ObjectTimestampPair, using the timestamp as basis for comparison. * Implementation is consistent with equals. * * @param other object to compare * @return result of comparison */ public int compareTo(ObjectTimestampPair other) { final long tstampdiff = this.tstamp - other.tstamp; if (tstampdiff == 0) { // make sure the natural ordering is consistent with equals // see java.lang.Comparable Javadocs return System.identityHashCode(this) - System.identityHashCode(other); } else { // handle int overflow return (int)Math.min(Math.max(tstampdiff, Integer.MIN_VALUE), Integer.MAX_VALUE); } } /** * @return the value */ public T getValue() { return value; } /** * @return the tstamp */ public long getTstamp() { return tstamp; } } /** * The idle object evictor {@link TimerTask}. * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis */ private class Evictor extends TimerTask { /** * Run pool maintenance. Evict objects qualifying for eviction and then * invoke {@link GenericKeyedObjectPool#ensureMinIdle()}. */ @Override public void run() { //Evict from the pool try { evict(); } catch(Exception e) { // ignored } catch(OutOfMemoryError oome) { // Log problem but give evictor thread a chance to continue in // case error is recoverable oome.printStackTrace(System.err); } //Re-create idle instances. try { ensureMinIdle(); } catch (Exception e) { // ignored } } } /** * A simple "struct" encapsulating the * configuration information for a GenericKeyedObjectPool. * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory,GenericKeyedObjectPool.Config) * @see GenericKeyedObjectPool#setConfig */ public static class Config { //CHECKSTYLE: stop VisibilityModifier /** * @see GenericKeyedObjectPool#setMaxIdle */ public int maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE; /** * @see GenericKeyedObjectPool#setMaxActive */ public int maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE; /** * @see GenericKeyedObjectPool#setMaxTotal */ public int maxTotal = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL; /** * @see GenericKeyedObjectPool#setMinIdle */ public int minIdle = GenericKeyedObjectPool.DEFAULT_MIN_IDLE; /** * @see GenericKeyedObjectPool#setMaxWait */ public long maxWait = GenericKeyedObjectPool.DEFAULT_MAX_WAIT; /** * @see GenericKeyedObjectPool#setWhenExhaustedAction */ public byte whenExhaustedAction = GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION; /** * @see GenericKeyedObjectPool#setTestOnBorrow */ public boolean testOnBorrow = GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW; /** * @see GenericKeyedObjectPool#setTestOnReturn */ public boolean testOnReturn = GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN; /** * @see GenericKeyedObjectPool#setTestWhileIdle */ public boolean testWhileIdle = GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE; /** * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis */ public long timeBetweenEvictionRunsMillis = GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; /** * @see GenericKeyedObjectPool#setNumTestsPerEvictionRun */ public int numTestsPerEvictionRun = GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; /** * @see GenericKeyedObjectPool#setMinEvictableIdleTimeMillis */ public long minEvictableIdleTimeMillis = GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; /** * @see GenericKeyedObjectPool#setLifo */ public boolean lifo = GenericKeyedObjectPool.DEFAULT_LIFO; //CHECKSTYLE: resume VisibilityModifier } /** * Latch used to control allocation order of objects to threads to ensure * fairness. That is, for each key, objects are allocated to threads in the order * that threads request objects. * * @since 1.5 */ private final class Latch { /** key of associated pool */ private final LK _key; /** keyed pool associated with this latch */ private ObjectQueue _pool; /** holds an ObjectTimestampPair when this latch has been allocated an instance */ private ObjectTimestampPair _pair; /** indicates that this latch can create an instance */ private boolean _mayCreate = false; /** * Create a latch with the given key * @param key key of the pool associated with this latch */ private Latch(LK key) { _key = key; } /** * Retuns the key of the associated pool * @return associated pool key */ private synchronized LK getkey() { return _key; } /** * Returns the pool associated with this latch * @return pool */ private synchronized ObjectQueue getPool() { return _pool; } /** * Sets the pool associated with this latch * @param pool the pool */ private synchronized void setPool(ObjectQueue pool) { _pool = pool; } /** * Gets the ObjectTimestampPair allocated to this latch. * Returns null if this latch does not have an instance allocated to it. * @return the associated ObjectTimestampPair */ private synchronized ObjectTimestampPair getPair() { return _pair; } /** * Allocate an ObjectTimestampPair to this latch. * @param pair ObjectTimestampPair on this latch */ private synchronized void setPair(ObjectTimestampPair pair) { _pair = pair; } /** * Whether or not this latch can create an instance * @return true if this latch has an instance creation permit */ private synchronized boolean mayCreate() { return _mayCreate; } /** * Sets the mayCreate property * * @param mayCreate true means this latch can create an instance */ private synchronized void setMayCreate(boolean mayCreate) { _mayCreate = mayCreate; } /** * Reset the latch data. Used when an allocation fails and the latch * needs to be re-added to the queue. */ private synchronized void reset() { _pair = null; _mayCreate = false; } } //--- protected attributes --------------------------------------- /** * The cap on the number of idle instances in the pool. * @see #setMaxIdle * @see #getMaxIdle */ private int _maxIdle = DEFAULT_MAX_IDLE; /** * The minimum no of idle objects to keep in the pool. * @see #setMinIdle * @see #getMinIdle */ private volatile int _minIdle = DEFAULT_MIN_IDLE; /** * The cap on the number of active instances from the pool. * @see #setMaxActive * @see #getMaxActive */ private int _maxActive = DEFAULT_MAX_ACTIVE; /** * The cap on the total number of instances from the pool if non-positive. * @see #setMaxTotal * @see #getMaxTotal */ private int _maxTotal = DEFAULT_MAX_TOTAL; /** * The maximum amount of time (in millis) the * {@link #borrowObject} method should block before throwing * an exception when the pool is exhausted and the * {@link #getWhenExhaustedAction "when exhausted" action} is * {@link #WHEN_EXHAUSTED_BLOCK}. * * When less than or equal to 0, the {@link #borrowObject} method * may block indefinitely. * * @see #setMaxWait * @see #getMaxWait * @see #WHEN_EXHAUSTED_BLOCK * @see #setWhenExhaustedAction * @see #getWhenExhaustedAction */ private long _maxWait = DEFAULT_MAX_WAIT; /** * The action to take when the {@link #borrowObject} method * is invoked when the pool is exhausted (the maximum number * of "active" objects has been reached). * * @see #WHEN_EXHAUSTED_BLOCK * @see #WHEN_EXHAUSTED_FAIL * @see #WHEN_EXHAUSTED_GROW * @see #DEFAULT_WHEN_EXHAUSTED_ACTION * @see #setWhenExhaustedAction * @see #getWhenExhaustedAction */ private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION; /** * When true, objects will be * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated} * before being returned by the {@link #borrowObject} * method. If the object fails to validate, * it will be dropped from the pool, and we will attempt * to borrow another. * * @see #setTestOnBorrow * @see #getTestOnBorrow */ private volatile boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW; /** * When true, objects will be * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated} * before being returned to the pool within the * {@link #returnObject}. * * @see #getTestOnReturn * @see #setTestOnReturn */ private volatile boolean _testOnReturn = DEFAULT_TEST_ON_RETURN; /** * When true, objects will be * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated} * by the idle object evictor (if any). If an object * fails to validate, it will be dropped from the pool. * * @see #setTestWhileIdle * @see #getTestWhileIdle * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ private boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE; /** * 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 #setTimeBetweenEvictionRunsMillis * @see #getTimeBetweenEvictionRunsMillis */ private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; /** * The number of objects to examine during each run of the * idle object evictor thread (if any). *

* When a negative value is supplied, ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun}) * tests will be run. I.e., when the value is -n, roughly one nth of the * idle objects will be tested per run. * * @see #setNumTestsPerEvictionRun * @see #getNumTestsPerEvictionRun * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ private int _numTestsPerEvictionRun = 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). * When non-positive, no objects will be evicted from the pool * due to idle time alone. * * @see #setMinEvictableIdleTimeMillis * @see #getMinEvictableIdleTimeMillis * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ private long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; /** My hash of pools (ObjectQueue). */ private Map _poolMap = null; /** The total number of active instances. */ private int _totalActive = 0; /** The total number of idle instances. */ private int _totalIdle = 0; /** * The number of objects subject to some form of internal processing * (usually creation or destruction) that should be included in the total * number of objects but are neither active nor idle. */ private int _totalInternalProcessing = 0; /** My {@link KeyedPoolableObjectFactory}. */ private KeyedPoolableObjectFactory _factory = null; /** * My idle object eviction {@link TimerTask}, if any. */ private Evictor _evictor = null; /** * A cursorable list of my pools. * @see GenericKeyedObjectPool.Evictor#run */ private CursorableLinkedList _poolList = null; /** Eviction cursor (over instances within-key) */ private CursorableLinkedList>.Cursor _evictionCursor = null; /** Eviction cursor (over keys) */ private CursorableLinkedList.Cursor _evictionKeyCursor = null; /** Whether or not the pools behave as LIFO queues (last in first out) */ private boolean _lifo = DEFAULT_LIFO; /** * Used to track the order in which threads call {@link #borrowObject()} so * that objects can be allocated in the order in which the threads requested * them. */ private LinkedList> _allocationQueue = new LinkedList>(); } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPoolFactory.java100644 0 0 66544 11701070262 27570 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import org.apache.commons.pool.KeyedObjectPool; import org.apache.commons.pool.KeyedObjectPoolFactory; import org.apache.commons.pool.KeyedPoolableObjectFactory; /** * A factory for creating {@link GenericKeyedObjectPool} instances. * * @param the type of keys in this pool * @param the type of objects held in this pool * * @see GenericKeyedObjectPool * @see KeyedObjectPoolFactory * * @author Rodney Waldhoff * @author Dirk Verbeeck * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public class GenericKeyedObjectPoolFactory implements KeyedObjectPoolFactory { /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory) */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory) { this(factory,GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE,GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,GenericKeyedObjectPool.DEFAULT_MAX_WAIT,GenericKeyedObjectPool.DEFAULT_MAX_IDLE,GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param config a non-null GenericKeyedObjectPool.Config describing the configuration. * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory, GenericKeyedObjectPool.Config) * @throws NullPointerException when config is null. */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) throws NullPointerException { this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.maxTotal,config.minIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle,config.lifo); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param maxActive the maximum number of objects that can be borrowed from pools at one time. * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory, int) */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive) { this(factory,maxActive,GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,GenericKeyedObjectPool.DEFAULT_MAX_WAIT,GenericKeyedObjectPool.DEFAULT_MAX_IDLE, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL,GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param maxActive the maximum number of objects that can be borrowed from pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory, int, byte, long) */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) { this(factory,maxActive,whenExhaustedAction,maxWait,GenericKeyedObjectPool.DEFAULT_MAX_IDLE, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL,GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param maxActive the maximum number of objects that can be borrowed from pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param testOnBorrow whether to validate objects before they are returned by borrowObject. * @param testOnReturn whether to validate objects after they are returned to returnObject. * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory, int, byte, long, boolean, boolean) */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) { this(factory,maxActive,whenExhaustedAction,maxWait,GenericKeyedObjectPool.DEFAULT_MAX_IDLE, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL,testOnBorrow,testOnReturn,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param maxActive the maximum number of objects that can be borrowed from pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in the pools. * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory, int, byte, long, int) */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) { this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL,GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param maxActive the maximum number of objects that can be borrowed from pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in the pools. * @param maxTotal the maximum number of objects that can exists at one time. */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal) { this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle, maxTotal, GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param maxActive the maximum number of objects that can be borrowed from pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in the pools. * @param testOnBorrow whether to validate objects before they are returned by borrowObject. * @param testOnReturn whether to validate objects after they are returned to returnObject. * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory, int, byte, long, int, boolean, boolean) */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) { this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL,testOnBorrow,testOnReturn,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param maxActive the maximum number of objects that can be borrowed from pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in the pools. * @param testOnBorrow whether to validate objects before they are returned by borrowObject. * @param testOnReturn whether to validate objects after they are returned to returnObject. * @param timeBetweenEvictionRunsMillis the number of milliseconds to sleep between examining idle objects for eviction. * @param numTestsPerEvictionRun the number of idle objects to examine per run of the evictor. * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction. * @param testWhileIdle whether to validate objects in the idle object eviction thread. * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory, int, byte, long, int, boolean, boolean, long, int, long, boolean) */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param maxActive the maximum number of objects that can be borrowed from pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in the pools. * @param maxTotal the maximum number of objects that can exists at one time. * @param testOnBorrow whether to validate objects before they are returned by borrowObject. * @param testOnReturn whether to validate objects after they are returned to returnObject. * @param timeBetweenEvictionRunsMillis the number of milliseconds to sleep between examining idle objects for eviction. * @param numTestsPerEvictionRun the number of idle objects to examine per run of the evictor. * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction. * @param testWhileIdle whether to validate objects in the idle object eviction thread. * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory, int, byte, long, int, int, boolean, boolean, long, int, long, boolean) */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, GenericKeyedObjectPool.DEFAULT_MIN_IDLE , testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param maxActive the maximum number of objects that can be borrowed from pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in the pools. * @param maxTotal the maximum number of objects that can exists at one time. * @param minIdle the minimum number of idle objects to have in the pool at any one time. * @param testOnBorrow whether to validate objects before they are returned by borrowObject. * @param testOnReturn whether to validate objects after they are returned to returnObject. * @param timeBetweenEvictionRunsMillis the number of milliseconds to sleep between examining idle objects for eviction. * @param numTestsPerEvictionRun the number of idle objects to examine per run of the evictor. * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction. * @param testWhileIdle whether to validate objects in the idle object eviction thread. * @since Pool 1.3 * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory, int, byte, long, int, int, int, boolean, boolean, long, int, long, boolean) */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, GenericKeyedObjectPool.DEFAULT_LIFO); } /** * Create a new GenericKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory to used by created pools. * @param maxActive the maximum number of objects that can be borrowed from pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in the pools. * @param maxTotal the maximum number of objects that can exists at one time. * @param minIdle the minimum number of idle objects to have in the pool at any one time. * @param testOnBorrow whether to validate objects before they are returned by borrowObject. * @param testOnReturn whether to validate objects after they are returned to returnObject. * @param timeBetweenEvictionRunsMillis the number of milliseconds to sleep between examining idle objects for eviction. * @param numTestsPerEvictionRun the number of idle objects to examine per run of the evictor. * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction. * @param testWhileIdle whether to validate objects in the idle object eviction thread. * @param lifo whether or not objects are returned in last-in-first-out order from the idle object pool. * @since Pool 1.4 * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory, int, byte, long, int, int, int, boolean, boolean, long, int, long, boolean, boolean) */ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, boolean lifo) { _maxIdle = maxIdle; _maxActive = maxActive; _maxTotal = maxTotal; _minIdle = minIdle; _maxWait = maxWait; _whenExhaustedAction = whenExhaustedAction; _testOnBorrow = testOnBorrow; _testOnReturn = testOnReturn; _testWhileIdle = testWhileIdle; _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; _numTestsPerEvictionRun = numTestsPerEvictionRun; _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; _factory = factory; _lifo = lifo; } /** * Create a new GenericKeyedObjectPool with the currently configured properties. * * @return GenericKeyedObjectPool with {@link GenericKeyedObjectPool.Config Configuration} determined by * current property settings */ public KeyedObjectPool createPool() { return new GenericKeyedObjectPool(_factory,_maxActive,_whenExhaustedAction,_maxWait,_maxIdle,_maxTotal,_minIdle,_testOnBorrow,_testOnReturn,_timeBetweenEvictionRunsMillis,_numTestsPerEvictionRun,_minEvictableIdleTimeMillis,_testWhileIdle,_lifo); } /** * @return the {@link GenericKeyedObjectPool#getMaxIdle() maxIdle} setting for pools created by this factory. * @since 1.5.5 */ public int getMaxIdle() { return _maxIdle; } /** * @return the {@link GenericKeyedObjectPool#getMaxActive() maxActive} setting for pools created by this factory. * @since 1.5.5 */ public int getMaxActive() { return _maxActive; } /** * @return the {@link GenericKeyedObjectPool#getMaxTotal() maxTotal} setting for pools created by this factory. * @since 1.5.5 */ public int getMaxTotal() { return _maxTotal; } /** * @return the {@link GenericKeyedObjectPool#getMinIdle() minIdle} setting for pools created by this factory. * @since 1.5.5 */ public int getMinIdle() { return _minIdle; } /** * @return the {@link GenericKeyedObjectPool#getMaxWait() maxWait} setting for pools created by this factory. * @since 1.5.5 */ public long getMaxWait() { return _maxWait; } /** * @return the {@link GenericKeyedObjectPool#getWhenExhaustedAction() whenExhaustedAction} setting for pools created by this factory. * @since 1.5.5 */ public byte getWhenExhaustedAction() { return _whenExhaustedAction; } /** * @return the {@link GenericKeyedObjectPool#getTestOnBorrow() testOnBorrow} setting for pools created by this factory. * @since 1.5.5 */ public boolean getTestOnBorrow() { return _testOnBorrow; } /** * @return the {@link GenericKeyedObjectPool#getTestOnReturn() testOnReturn} setting for pools created by this factory. * @since 1.5.5 */ public boolean getTestOnReturn() { return _testOnReturn; } /** * @return the {@link GenericKeyedObjectPool#getTestWhileIdle() testWhileIdle} setting for pools created by this factory. * @since 1.5.5 */ public boolean getTestWhileIdle() { return _testWhileIdle; } /** * @return the {@link GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis() timeBetweenEvictionRunsMillis} * setting for pools created by this factory. * @since 1.5.5 */ public long getTimeBetweenEvictionRunsMillis() { return _timeBetweenEvictionRunsMillis; } /** * @return the {@link GenericKeyedObjectPool#getNumTestsPerEvictionRun() numTestsPerEvictionRun} * setting for pools created by this factory. * @since 1.5.5 */ public int getNumTestsPerEvictionRun() { return _numTestsPerEvictionRun; } /** * @return the {@link GenericKeyedObjectPool#getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} * setting for pools created by this factory. * @since 1.5.5 */ public long getMinEvictableIdleTimeMillis() { return _minEvictableIdleTimeMillis; } /** * @return the {@link KeyedPoolableObjectFactory} used by pools created by this factory. * @since 1.5.5 */ public KeyedPoolableObjectFactory getFactory() { return _factory; } /** * @return the {@link GenericKeyedObjectPool#getLifo() lifo} setting for pools created by this factory. * @since 1.5.5 */ public boolean getLifo() { return _lifo; } //--- protected attributes - deprecated, use getters to access these properties /** * The {@link GenericKeyedObjectPool#getMaxIdle() maxIdle} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMaxIdle()}. */ @Deprecated protected int _maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE; /** * The {@link GenericKeyedObjectPool#getMaxActive() maxActive} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMaxActive()}. */ @Deprecated protected int _maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE; /** * The {@link GenericKeyedObjectPool#getMaxTotal() maxTotal} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMaxTotal()}. */ @Deprecated protected int _maxTotal = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL; /** * The {@link GenericKeyedObjectPool#getMinIdle() minIdle} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMinIdle()}. */ @Deprecated protected int _minIdle = GenericKeyedObjectPool.DEFAULT_MIN_IDLE; /** * The {@link GenericKeyedObjectPool#getMaxWait() maxWait} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMaxWait()}. */ @Deprecated protected long _maxWait = GenericKeyedObjectPool.DEFAULT_MAX_WAIT; /** * The {@link GenericKeyedObjectPool#getWhenExhaustedAction() whenExhaustedAction} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getWhenExhaustedAction()}. */ @Deprecated protected byte _whenExhaustedAction = GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION; /** * The {@link GenericKeyedObjectPool#getTestOnBorrow() testOnBorrow} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getTestOnBorrow()}. */ @Deprecated protected boolean _testOnBorrow = GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW; /** * The {@link GenericKeyedObjectPool#getTestOnReturn() testOnReturn} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getTestOnReturn()}. */ @Deprecated protected boolean _testOnReturn = GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN; /** * The {@link GenericKeyedObjectPool#getTestWhileIdle() testWhileIdle} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getTestWhileIdle()}. */ @Deprecated protected boolean _testWhileIdle = GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE; /** * The {@link GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis() timeBetweenEvictionRunsMillis} setting for * pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getTimeBetweenEvictionRunsMillis()}. */ @Deprecated protected long _timeBetweenEvictionRunsMillis = GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; /** * The {@link GenericKeyedObjectPool#getNumTestsPerEvictionRun() numTestsPerEvictionRun} setting for * pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getNumTestsPerEvictionRun()}. */ @Deprecated protected int _numTestsPerEvictionRun = GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; /** * The {@link GenericKeyedObjectPool#getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} setting for * pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMinEvictableIdleTimeMillis()}. */ @Deprecated protected long _minEvictableIdleTimeMillis = GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; /** * The {@link KeyedPoolableObjectFactory} used by pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getFactory()}. */ @Deprecated protected KeyedPoolableObjectFactory _factory = null; /** * The {@link GenericKeyedObjectPool#getLifo() lifo} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getLifo()}. */ @Deprecated protected boolean _lifo = GenericKeyedObjectPool.DEFAULT_LIFO; } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/GenericObjectPool.java100644 0 0 267631 11701070262 25276 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; import java.util.TimerTask; import org.apache.commons.pool.BaseObjectPool; import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.PoolUtils; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.GenericKeyedObjectPool.ObjectTimestampPair; /** * A configurable {@link ObjectPool} implementation. *

* When coupled with the appropriate {@link PoolableObjectFactory}, * GenericObjectPool provides robust pooling functionality for * arbitrary objects. *

* A GenericObjectPool provides a number of configurable parameters: *

    *
  • * {@link #setMaxActive maxActive} controls the maximum number of * objects that can be allocated by the pool (checked out to clients, or * idle awaiting checkout) at a given time. When non-positive, there is no * limit to the number of objects that can be managed by the pool at one time. * When {@link #setMaxActive maxActive} is reached, the pool is said * to be exhausted. The default setting for this parameter is 8. *
  • *
  • * {@link #setMaxIdle maxIdle} controls the maximum number of objects * that can sit idle in the pool at any time. When negative, there is no * limit to the number of objects that may be idle at one time. The default * setting for this parameter is 8. *
  • *
  • * {@link #setWhenExhaustedAction whenExhaustedAction} specifies the * behavior of the {@link #borrowObject} method when the pool is exhausted: *
      *
    • * When {@link #setWhenExhaustedAction whenExhaustedAction} is * {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject} will throw * a {@link NoSuchElementException} *
    • *
    • * When {@link #setWhenExhaustedAction whenExhaustedAction} is * {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject} will create a new * object and return it (essentially making {@link #setMaxActive maxActive} * meaningless.) *
    • *
    • * When {@link #setWhenExhaustedAction whenExhaustedAction} * is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject} will block * (invoke {@link Object#wait()}) until a new or idle object is available. * If a positive {@link #setMaxWait maxWait} * value is supplied, then {@link #borrowObject} will block for at * most that many milliseconds, after which a {@link NoSuchElementException} * will be thrown. If {@link #setMaxWait maxWait} is non-positive, * the {@link #borrowObject} method will block indefinitely. *
    • *
    * The default whenExhaustedAction setting is * {@link #WHEN_EXHAUSTED_BLOCK} and the default maxWait * setting is -1. By default, therefore, borrowObject will * block indefinitely until an idle instance becomes available. *
  • *
  • * When {@link #setTestOnBorrow testOnBorrow} is set, the pool will * attempt to validate each object before it is returned from the * {@link #borrowObject} method. (Using the provided factory's * {@link PoolableObjectFactory#validateObject} method.) Objects that fail * to validate will be dropped from the pool, and a different object will * be borrowed. The default setting for this parameter is * false. *
  • *
  • * When {@link #setTestOnReturn testOnReturn} is set, the pool will * attempt to validate each object before it is returned to the pool in the * {@link #returnObject} method. (Using the provided factory's * {@link PoolableObjectFactory#validateObject} * method.) Objects that fail to validate will be dropped from the pool. * The default setting for this parameter is false. *
  • *
*

* Optionally, one may configure the pool to examine and possibly evict objects * as they sit idle in the pool and to ensure that a minimum number of idle * objects are available. This is performed by an "idle object eviction" * thread, which runs asynchronously. Caution should be used when configuring * this optional feature. Eviction runs contend with client threads for access * to objects in the pool, so if they run too frequently performance issues may * result. The idle object eviction thread may be configured using the following * attributes: *

    *
  • * {@link #setTimeBetweenEvictionRunsMillis timeBetweenEvictionRunsMillis} * indicates how long the eviction thread should sleep before "runs" of examining * idle objects. When non-positive, no eviction thread will be launched. The * default setting for this parameter is -1 (i.e., idle object eviction is * disabled by default). *
  • *
  • * {@link #setMinEvictableIdleTimeMillis minEvictableIdleTimeMillis} * specifies the minimum amount of time that an object may sit idle in the pool * before it is eligible for eviction due to idle time. When non-positive, no object * will be dropped from the pool due to idle time alone. This setting has no * effect unless timeBetweenEvictionRunsMillis > 0. The default * setting for this parameter is 30 minutes. *
  • *
  • * {@link #setTestWhileIdle testWhileIdle} indicates whether or not idle * objects should be validated using the factory's * {@link PoolableObjectFactory#validateObject} method. Objects that fail to * validate will be dropped from the pool. This setting has no effect unless * timeBetweenEvictionRunsMillis > 0. The default setting for * this parameter is false. *
  • *
  • * {@link #setSoftMinEvictableIdleTimeMillis softMinEvictableIdleTimeMillis} * specifies 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), with the extra condition that at least "minIdle" object instances * remain in the pool. When non-positive, no objects will be evicted from the pool * due to idle time alone. This setting has no effect unless * timeBetweenEvictionRunsMillis > 0. and it is superceded by * {@link #setMinEvictableIdleTimeMillis minEvictableIdleTimeMillis} * (that is, if minEvictableIdleTimeMillis is positive, then * softMinEvictableIdleTimeMillis is ignored). The default setting for * this parameter is -1 (disabled). *
  • *
  • * {@link #setNumTestsPerEvictionRun numTestsPerEvictionRun} * determines the number of objects examined in each run of the idle object * evictor. This setting has no effect unless * timeBetweenEvictionRunsMillis > 0. The default setting for * this parameter is 3. *
  • *
*

*

* The pool can be configured to behave as a LIFO queue with respect to idle * objects - always returning the most recently used object from the pool, * or as a FIFO queue, where borrowObject always returns the oldest object * in the idle object pool. *

    *
  • * {@link #setLifo lifo} * determines whether or not the pool returns idle objects in * last-in-first-out order. The default setting for this parameter is * true. *
  • *
*

* GenericObjectPool is not usable without a {@link PoolableObjectFactory}. A * non-null factory must be provided either as a constructor argument * or via a call to {@link #setFactory} before the pool is used. *

* Implementation note: To prevent possible deadlocks, care has been taken to * ensure that no call to a factory method will occur within a synchronization * block. See POOL-125 and DBCP-44 for more information. * * @param the type of objects held in this pool * * @see GenericKeyedObjectPool * @author Rodney Waldhoff * @author Dirk Verbeeck * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public class GenericObjectPool extends BaseObjectPool implements ObjectPool { //--- public constants ------------------------------------------- /** * A "when exhausted action" type indicating that when the pool is * exhausted (i.e., the maximum number of active objects has * been reached), the {@link #borrowObject} * method should fail, throwing a {@link NoSuchElementException}. * @see #WHEN_EXHAUSTED_BLOCK * @see #WHEN_EXHAUSTED_GROW * @see #setWhenExhaustedAction */ public static final byte WHEN_EXHAUSTED_FAIL = 0; /** * A "when exhausted action" type indicating that when the pool * is exhausted (i.e., the maximum number * of active objects has been reached), the {@link #borrowObject} * method should block until a new object is available, or the * {@link #getMaxWait maximum wait time} has been reached. * @see #WHEN_EXHAUSTED_FAIL * @see #WHEN_EXHAUSTED_GROW * @see #setMaxWait * @see #getMaxWait * @see #setWhenExhaustedAction */ public static final byte WHEN_EXHAUSTED_BLOCK = 1; /** * A "when exhausted action" type indicating that when the pool is * exhausted (i.e., the maximum number * of active objects has been reached), the {@link #borrowObject} * method should simply create a new object anyway. * @see #WHEN_EXHAUSTED_FAIL * @see #WHEN_EXHAUSTED_GROW * @see #setWhenExhaustedAction */ public static final byte WHEN_EXHAUSTED_GROW = 2; /** * The default cap on the number of "sleeping" instances in the pool. * @see #getMaxIdle * @see #setMaxIdle */ public static final int DEFAULT_MAX_IDLE = 8; /** * The default minimum number of "sleeping" instances in the pool * before before the evictor thread (if active) spawns new objects. * @see #getMinIdle * @see #setMinIdle */ public static final int DEFAULT_MIN_IDLE = 0; /** * The default cap on the total number of active instances from the pool. * @see #getMaxActive */ public static final int DEFAULT_MAX_ACTIVE = 8; /** * The default "when exhausted action" for the pool. * @see #WHEN_EXHAUSTED_BLOCK * @see #WHEN_EXHAUSTED_FAIL * @see #WHEN_EXHAUSTED_GROW * @see #setWhenExhaustedAction */ public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK; /** * The default LIFO status. True means that borrowObject returns the * most recently used ("last in") idle object in the pool (if there are * idle instances available). False means that the pool behaves as a FIFO * queue - objects are taken from the idle object pool in the order that * they are returned to the pool. * @see #setLifo * @since 1.4 */ public static final boolean DEFAULT_LIFO = true; /** * The default maximum amount of time (in milliseconds) the * {@link #borrowObject} method should block before throwing * an exception when the pool is exhausted and the * {@link #getWhenExhaustedAction "when exhausted" action} is * {@link #WHEN_EXHAUSTED_BLOCK}. * @see #getMaxWait * @see #setMaxWait */ public static final long DEFAULT_MAX_WAIT = -1L; /** * The default "test on borrow" value. * @see #getTestOnBorrow * @see #setTestOnBorrow */ public static final boolean DEFAULT_TEST_ON_BORROW = false; /** * The default "test on return" value. * @see #getTestOnReturn * @see #setTestOnReturn */ public static final boolean DEFAULT_TEST_ON_RETURN = false; /** * The default "test while idle" value. * @see #getTestWhileIdle * @see #setTestWhileIdle * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ public static final boolean DEFAULT_TEST_WHILE_IDLE = false; /** * The default "time between eviction runs" value. * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L; /** * The default number of objects to examine per run in the * idle object evictor. * @see #getNumTestsPerEvictionRun * @see #setNumTestsPerEvictionRun * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3; /** * The default value for {@link #getMinEvictableIdleTimeMillis}. * @see #getMinEvictableIdleTimeMillis * @see #setMinEvictableIdleTimeMillis */ public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L; /** * The default value for {@link #getSoftMinEvictableIdleTimeMillis}. * @see #getSoftMinEvictableIdleTimeMillis * @see #setSoftMinEvictableIdleTimeMillis */ public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1; //--- constructors ----------------------------------------------- /** * Create a new GenericObjectPool with default properties. */ public GenericObjectPool() { this(null, DEFAULT_MAX_ACTIVE, DEFAULT_WHEN_EXHAUSTED_ACTION, DEFAULT_MAX_WAIT, DEFAULT_MAX_IDLE, DEFAULT_MIN_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPool using the specified factory. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects */ public GenericObjectPool(PoolableObjectFactory factory) { this(factory, DEFAULT_MAX_ACTIVE, DEFAULT_WHEN_EXHAUSTED_ACTION, DEFAULT_MAX_WAIT, DEFAULT_MAX_IDLE, DEFAULT_MIN_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPool using the specified values. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects * @param config a non-null {@link GenericObjectPool.Config} describing my configuration */ public GenericObjectPool(PoolableObjectFactory factory, GenericObjectPool.Config config) { this(factory, config.maxActive, config.whenExhaustedAction, config.maxWait, config.maxIdle, config.minIdle, config.testOnBorrow, config.testOnReturn, config.timeBetweenEvictionRunsMillis, config.numTestsPerEvictionRun, config.minEvictableIdleTimeMillis, config.testWhileIdle, config.softMinEvictableIdleTimeMillis, config.lifo); } /** * Create a new GenericObjectPool using the specified values. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) */ public GenericObjectPool(PoolableObjectFactory factory, int maxActive) { this(factory, maxActive, DEFAULT_WHEN_EXHAUSTED_ACTION, DEFAULT_MAX_WAIT, DEFAULT_MAX_IDLE, DEFAULT_MIN_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPool using the specified values. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait}) */ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) { this(factory, maxActive, whenExhaustedAction, maxWait, DEFAULT_MAX_IDLE, DEFAULT_MIN_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPool using the specified values. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects * @param maxActive the maximum number of objects that can be borrowed at one time (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method * (see {@link #getTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method * (see {@link #getTestOnReturn}) */ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) { this(factory, maxActive, whenExhaustedAction, maxWait, DEFAULT_MAX_IDLE, DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPool using the specified values. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects * @param maxActive the maximum number of objects that can be borrowed at one time (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #getMaxIdle}) */ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPool using the specified values. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects * @param maxActive the maximum number of objects that can be borrowed at one time (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #getMaxIdle}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method * (see {@link #getTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method * (see {@link #getTestOnReturn}) */ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPool using the specified values. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects * @param maxActive the maximum number of objects that can be borrowed at one time (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} * method (see {@link #setTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method * (see {@link #setTestOnReturn}) * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects * for eviction (see {@link #setTimeBetweenEvictionRunsMillis}) * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread * (if any) (see {@link #setNumTestsPerEvictionRun}) * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it * is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis}) * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any * (see {@link #setTestWhileIdle}) */ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle); } /** * Create a new GenericObjectPool using the specified values. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects * @param maxActive the maximum number of objects that can be borrowed at one time (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) * @param minIdle the minimum number of idle objects in my pool (see {@link #setMinIdle}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method * (see {@link #setTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method * (see {@link #setTestOnReturn}) * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects * for eviction (see {@link #setTimeBetweenEvictionRunsMillis}) * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread * (if any) (see {@link #setNumTestsPerEvictionRun}) * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before * it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis}) * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any * (see {@link #setTestWhileIdle}) */ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS); } /** * Create a new GenericObjectPool using the specified values. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects * @param maxActive the maximum number of objects that can be borrowed at one time (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) * @param minIdle the minimum number of idle objects in my pool (see {@link #setMinIdle}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} * method (see {@link #setTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} * method (see {@link #setTestOnReturn}) * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects * for eviction (see {@link #setTimeBetweenEvictionRunsMillis}) * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread * (if any) (see {@link #setNumTestsPerEvictionRun}) * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before * it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis}) * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any * (see {@link #setTestWhileIdle}) * @param softMinEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is * eligible for eviction with the extra condition that at least "minIdle" amount of object remain in the pool. * (see {@link #setSoftMinEvictableIdleTimeMillis}) * @since Pool 1.3 */ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, long softMinEvictableIdleTimeMillis) { this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, softMinEvictableIdleTimeMillis, DEFAULT_LIFO); } /** * Create a new GenericObjectPool using the specified values. * @param factory the (possibly null)PoolableObjectFactory to use to create, validate and destroy objects * @param maxActive the maximum number of objects that can be borrowed at one time (see {@link #setMaxActive}) * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and * whenExhaustedAction is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) * @param minIdle the minimum number of idle objects in my pool (see {@link #setMinIdle}) * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} * method (see {@link #setTestOnBorrow}) * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} * method (see {@link #setTestOnReturn}) * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle * objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis}) * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction * thread (if any) (see {@link #setNumTestsPerEvictionRun}) * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before * it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis}) * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any * (see {@link #setTestWhileIdle}) * @param softMinEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the * pool before it is eligible for eviction with the extra condition that at least "minIdle" amount of object * remain in the pool. (see {@link #setSoftMinEvictableIdleTimeMillis}) * @param lifo whether or not objects are returned in last-in-first-out order from the idle object pool * (see {@link #setLifo}) * @since Pool 1.4 */ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, long softMinEvictableIdleTimeMillis, boolean lifo) { _factory = factory; _maxActive = maxActive; _lifo = lifo; switch(whenExhaustedAction) { case WHEN_EXHAUSTED_BLOCK: case WHEN_EXHAUSTED_FAIL: case WHEN_EXHAUSTED_GROW: _whenExhaustedAction = whenExhaustedAction; break; default: throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized."); } _maxWait = maxWait; _maxIdle = maxIdle; _minIdle = minIdle; _testOnBorrow = testOnBorrow; _testOnReturn = testOnReturn; _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; _numTestsPerEvictionRun = numTestsPerEvictionRun; _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; _softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; _testWhileIdle = testWhileIdle; _pool = new CursorableLinkedList>(); startEvictor(_timeBetweenEvictionRunsMillis); } //--- public methods --------------------------------------------- //--- configuration methods -------------------------------------- /** * Returns the maximum number of objects that can be allocated by the pool * (checked out to clients, or idle awaiting checkout) at a given time. * When non-positive, there is no limit to the number of objects that can * be managed by the pool at one time. * * @return the cap on the total number of object instances managed by the pool. * @see #setMaxActive */ public synchronized int getMaxActive() { return _maxActive; } /** * Sets the cap on the number of objects that can be allocated by the pool * (checked out to clients, or idle awaiting checkout) at a given time. Use * a negative value for no limit. * * @param maxActive The cap on the total number of object instances managed by the pool. * Negative values mean that there is no limit to the number of objects allocated * by the pool. * @see #getMaxActive */ public void setMaxActive(int maxActive) { synchronized(this) { _maxActive = maxActive; } allocate(); } /** * Returns the action to take when the {@link #borrowObject} method * is invoked when the pool is exhausted (the maximum number * of "active" objects has been reached). * * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW} * @see #setWhenExhaustedAction */ public synchronized byte getWhenExhaustedAction() { return _whenExhaustedAction; } /** * Sets the action to take when the {@link #borrowObject} method * is invoked when the pool is exhausted (the maximum number * of "active" objects has been reached). * * @param whenExhaustedAction the action code, which must be one of * {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL}, * or {@link #WHEN_EXHAUSTED_GROW} * @see #getWhenExhaustedAction */ public void setWhenExhaustedAction(byte whenExhaustedAction) { synchronized(this) { switch(whenExhaustedAction) { case WHEN_EXHAUSTED_BLOCK: case WHEN_EXHAUSTED_FAIL: case WHEN_EXHAUSTED_GROW: _whenExhaustedAction = whenExhaustedAction; break; default: throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized."); } } allocate(); } /** * Returns the maximum amount of time (in milliseconds) the * {@link #borrowObject} method should block before throwing * an exception when the pool is exhausted and the * {@link #setWhenExhaustedAction "when exhausted" action} is * {@link #WHEN_EXHAUSTED_BLOCK}. * * When less than or equal to 0, the {@link #borrowObject} method * may block indefinitely. * * @return maximum number of milliseconds to block when borrowing an object. * @see #setMaxWait * @see #setWhenExhaustedAction * @see #WHEN_EXHAUSTED_BLOCK */ public synchronized long getMaxWait() { return _maxWait; } /** * Sets the maximum amount of time (in milliseconds) the * {@link #borrowObject} method should block before throwing * an exception when the pool is exhausted and the * {@link #setWhenExhaustedAction "when exhausted" action} is * {@link #WHEN_EXHAUSTED_BLOCK}. * * When less than or equal to 0, the {@link #borrowObject} method * may block indefinitely. * * @param maxWait maximum number of milliseconds to block when borrowing an object. * @see #getMaxWait * @see #setWhenExhaustedAction * @see #WHEN_EXHAUSTED_BLOCK */ public void setMaxWait(long maxWait) { synchronized(this) { _maxWait = maxWait; } allocate(); } /** * Returns the cap on the number of "idle" instances in the pool. * @return the cap on the number of "idle" instances in the pool. * @see #setMaxIdle */ public synchronized int getMaxIdle() { return _maxIdle; } /** * Sets the cap on the number of "idle" instances in the pool. * If maxIdle is set too low on heavily loaded systems it is possible you * will see objects being destroyed and almost immediately new objects * being created. This is a result of the active threads momentarily * returning objects faster than they are requesting them them, causing the * number of idle objects to rise above maxIdle. The best value for maxIdle * for heavily loaded system will vary but the default is a good starting * point. * @param maxIdle The cap on the number of "idle" instances in the pool. * Use a negative value to indicate an unlimited number of idle instances. * @see #getMaxIdle */ public void setMaxIdle(int maxIdle) { synchronized(this) { _maxIdle = maxIdle; } allocate(); } /** * Sets the minimum number of objects allowed in the pool * before the evictor thread (if active) spawns new objects. * Note that no objects are created when * numActive + numIdle >= maxActive. * This setting has no effect if the idle object evictor is disabled * (i.e. if timeBetweenEvictionRunsMillis <= 0). * * @param minIdle The minimum number of objects. * @see #getMinIdle * @see #getTimeBetweenEvictionRunsMillis() */ public void setMinIdle(int minIdle) { synchronized(this) { _minIdle = minIdle; } allocate(); } /** * Returns the minimum number of objects allowed in the pool * before the evictor thread (if active) spawns new objects. * (Note no objects are created when: numActive + numIdle >= maxActive) * * @return The minimum number of objects. * @see #setMinIdle */ public synchronized int getMinIdle() { return _minIdle; } /** * When true, objects will be * {@link PoolableObjectFactory#validateObject validated} * before being returned by the {@link #borrowObject} * method. If the object fails to validate, * it will be dropped from the pool, and we will attempt * to borrow another. * * @return true if objects are validated before being borrowed. * @see #setTestOnBorrow */ public boolean getTestOnBorrow() { return _testOnBorrow; } /** * When true, objects will be * {@link PoolableObjectFactory#validateObject validated} * before being returned by the {@link #borrowObject} * method. If the object fails to validate, * it will be dropped from the pool, and we will attempt * to borrow another. * * @param testOnBorrow true if objects should be validated before being borrowed. * @see #getTestOnBorrow */ public void setTestOnBorrow(boolean testOnBorrow) { _testOnBorrow = testOnBorrow; } /** * When true, objects will be * {@link PoolableObjectFactory#validateObject validated} * before being returned to the pool within the * {@link #returnObject}. * * @return true when objects will be validated after returned to {@link #returnObject}. * @see #setTestOnReturn */ public boolean getTestOnReturn() { return _testOnReturn; } /** * When true, objects will be * {@link PoolableObjectFactory#validateObject validated} * before being returned to the pool within the * {@link #returnObject}. * * @param testOnReturn true so objects will be validated after returned to {@link #returnObject}. * @see #getTestOnReturn */ public void setTestOnReturn(boolean testOnReturn) { _testOnReturn = testOnReturn; } /** * Returns the number of milliseconds to sleep between runs of the * idle object evictor thread. * When non-positive, no idle object evictor thread will be * run. * * @return number of milliseconds to sleep between evictor runs. * @see #setTimeBetweenEvictionRunsMillis */ public synchronized long getTimeBetweenEvictionRunsMillis() { return _timeBetweenEvictionRunsMillis; } /** * 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 number of milliseconds to sleep between evictor runs. * @see #getTimeBetweenEvictionRunsMillis */ public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; startEvictor(_timeBetweenEvictionRunsMillis); } /** * Returns the max number of objects to examine during each run of the * idle object evictor thread (if any). * * @return max number of objects to examine during each evictor run. * @see #setNumTestsPerEvictionRun * @see #setTimeBetweenEvictionRunsMillis */ public synchronized int getNumTestsPerEvictionRun() { return _numTestsPerEvictionRun; } /** * Sets the max number of objects to examine during each run of the * idle object evictor thread (if any). *

* When a negative value is supplied, ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun}) * tests will be run. That is, when the value is -n, roughly one nth of the * idle objects will be tested per run. When the value is positive, the number of tests * actually performed in each run will be the minimum of this value and the number of instances * idle in the pool. * * @param numTestsPerEvictionRun max number of objects to examine during each evictor run. * @see #getNumTestsPerEvictionRun * @see #setTimeBetweenEvictionRunsMillis */ public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { _numTestsPerEvictionRun = numTestsPerEvictionRun; } /** * Returns 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). * * @return minimum amount of time an object may sit idle in the pool before it is eligible for eviction. * @see #setMinEvictableIdleTimeMillis * @see #setTimeBetweenEvictionRunsMillis */ public synchronized long getMinEvictableIdleTimeMillis() { return _minEvictableIdleTimeMillis; } /** * Sets the minimum amount of time an object may sit idle in the pool * before it is eligible for eviction by the idle object evictor * (if any). * When non-positive, no objects will be evicted from the pool * due to idle time alone. * @param minEvictableIdleTimeMillis minimum amount of time an object may sit idle in the pool before * it is eligible for eviction. * @see #getMinEvictableIdleTimeMillis * @see #setTimeBetweenEvictionRunsMillis */ public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } /** * Returns 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), with the extra condition that at least * "minIdle" amount of object remain in the pool. * * @return minimum amount of time an object may sit idle in the pool before it is eligible for eviction. * @since Pool 1.3 * @see #setSoftMinEvictableIdleTimeMillis */ public synchronized long getSoftMinEvictableIdleTimeMillis() { return _softMinEvictableIdleTimeMillis; } /** * Sets the minimum amount of time an object may sit idle in the pool * before it is eligible for eviction by the idle object evictor * (if any), with the extra condition that at least * "minIdle" object instances remain in the pool. * When non-positive, no objects will be evicted from the pool * due to idle time alone. * * @param softMinEvictableIdleTimeMillis minimum amount of time an object may sit idle in the pool before * it is eligible for eviction. * @since Pool 1.3 * @see #getSoftMinEvictableIdleTimeMillis */ public synchronized void setSoftMinEvictableIdleTimeMillis(long softMinEvictableIdleTimeMillis) { _softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; } /** * When true, objects will be * {@link PoolableObjectFactory#validateObject validated} * by the idle object evictor (if any). If an object * fails to validate, it will be dropped from the pool. * * @return true when objects will be validated by the evictor. * @see #setTestWhileIdle * @see #setTimeBetweenEvictionRunsMillis */ public synchronized boolean getTestWhileIdle() { return _testWhileIdle; } /** * When true, objects will be * {@link PoolableObjectFactory#validateObject validated} * by the idle object evictor (if any). If an object * fails to validate, it will be dropped from the pool. * * @param testWhileIdle true so objects will be validated by the evictor. * @see #getTestWhileIdle * @see #setTimeBetweenEvictionRunsMillis */ public synchronized void setTestWhileIdle(boolean testWhileIdle) { _testWhileIdle = testWhileIdle; } /** * Whether or not the idle object pool acts as a LIFO queue. True means * that borrowObject returns the most recently used ("last in") idle object * in the pool (if there are idle instances available). False means that * the pool behaves as a FIFO queue - objects are taken from the idle object * pool in the order that they are returned to the pool. * * @return true if the pool is configured to act as a LIFO queue * @since 1.4 */ public synchronized boolean getLifo() { return _lifo; } /** * Sets the LIFO property of the pool. True means that borrowObject returns * the most recently used ("last in") idle object in the pool (if there are * idle instances available). False means that the pool behaves as a FIFO * queue - objects are taken from the idle object pool in the order that * they are returned to the pool. * * @param lifo the new value for the LIFO property * @since 1.4 */ public synchronized void setLifo(boolean lifo) { this._lifo = lifo; } /** * Sets my configuration. * * @param conf configuration to use. * @see GenericObjectPool.Config */ public void setConfig(GenericObjectPool.Config conf) { synchronized (this) { setMaxIdle(conf.maxIdle); setMinIdle(conf.minIdle); setMaxActive(conf.maxActive); setMaxWait(conf.maxWait); setWhenExhaustedAction(conf.whenExhaustedAction); setTestOnBorrow(conf.testOnBorrow); setTestOnReturn(conf.testOnReturn); setTestWhileIdle(conf.testWhileIdle); setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun); setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis); setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis); setSoftMinEvictableIdleTimeMillis(conf.softMinEvictableIdleTimeMillis); setLifo(conf.lifo); } allocate(); } //-- ObjectPool methods ------------------------------------------ /** *

Borrows an object from the pool.

* *

If there is an idle instance available in the pool, then either the most-recently returned * (if {@link #getLifo() lifo} == true) or "oldest" (lifo == false) instance sitting idle in the pool * will be activated and returned. If activation fails, or {@link #getTestOnBorrow() testOnBorrow} is set * to true and validation fails, the instance is destroyed and the next available instance is examined. * This continues until either a valid instance is returned or there are no more idle instances available.

* *

If there are no idle instances available in the pool, behavior depends on the {@link #getMaxActive() maxActive} * and (if applicable) {@link #getWhenExhaustedAction() whenExhaustedAction} and {@link #getMaxWait() maxWait} * properties. If the number of instances checked out from the pool is less than maxActive, a new * instance is created, activated and (if applicable) validated and returned to the caller.

* *

If the pool is exhausted (no available idle instances and no capacity to create new ones), * this method will either block ({@link #WHEN_EXHAUSTED_BLOCK}), throw a NoSuchElementException * ({@link #WHEN_EXHAUSTED_FAIL}), or grow ({@link #WHEN_EXHAUSTED_GROW} - ignoring maxActive). * The length of time that this method will block when whenExhaustedAction == WHEN_EXHAUSTED_BLOCK * is determined by the {@link #getMaxWait() maxWait} property.

* *

When the pool is exhausted, multiple calling threads may be simultaneously blocked waiting for instances * to become available. As of pool 1.5, a "fairness" algorithm has been implemented to ensure that threads receive * available instances in request arrival order.

* * @return object instance * @throws NoSuchElementException if an instance cannot be returned */ @Override public T borrowObject() throws Exception { long starttime = System.currentTimeMillis(); Latch latch = new Latch(); byte whenExhaustedAction; long maxWait; synchronized (this) { // Get local copy of current config. Can't sync when used later as // it can result in a deadlock. Has the added advantage that config // is consistent for entire method execution whenExhaustedAction = _whenExhaustedAction; maxWait = _maxWait; // Add this request to the queue _allocationQueue.add(latch); } // Work the allocation queue, allocating idle instances and // instance creation permits in request arrival order allocate(); for(;;) { synchronized (this) { assertOpen(); } // If no object was allocated from the pool above if(latch.getPair() == null) { // check if we were allowed to create one if(latch.mayCreate()) { // allow new object to be created } else { // the pool is exhausted switch(whenExhaustedAction) { case WHEN_EXHAUSTED_GROW: // allow new object to be created synchronized (this) { // Make sure another thread didn't allocate us an object // or permit a new object to be created if (latch.getPair() == null && !latch.mayCreate()) { _allocationQueue.remove(latch); _numInternalProcessing++; } } break; case WHEN_EXHAUSTED_FAIL: synchronized (this) { // Make sure allocate hasn't already assigned an object // in a different thread or permitted a new object to be created if (latch.getPair() != null || latch.mayCreate()) { break; } _allocationQueue.remove(latch); } throw new NoSuchElementException("Pool exhausted"); case WHEN_EXHAUSTED_BLOCK: try { synchronized (latch) { // Before we wait, make sure another thread didn't allocate us an object // or permit a new object to be created if (latch.getPair() == null && !latch.mayCreate()) { if(maxWait <= 0) { latch.wait(); } else { // this code may be executed again after a notify then continue cycle // so, need to calculate the amount of time to wait final long elapsed = (System.currentTimeMillis() - starttime); final long waitTime = maxWait - elapsed; if (waitTime > 0) { latch.wait(waitTime); } } } else { break; } } // see if we were awakened by a closing pool if(isClosed() == true) { throw new IllegalStateException("Pool closed"); } } catch(InterruptedException e) { boolean doAllocate = false; synchronized(this) { // Need to handle the all three possibilities if (latch.getPair() == null && !latch.mayCreate()) { // Case 1: latch still in allocation queue // Remove latch from the allocation queue _allocationQueue.remove(latch); } else if (latch.getPair() == null && latch.mayCreate()) { // Case 2: latch has been given permission to create // a new object _numInternalProcessing--; doAllocate = true; } else { // Case 3: An object has been allocated _numInternalProcessing--; _numActive++; returnObject(latch.getPair().getValue()); } } if (doAllocate) { allocate(); } Thread.currentThread().interrupt(); throw e; } if(maxWait > 0 && ((System.currentTimeMillis() - starttime) >= maxWait)) { synchronized(this) { // Make sure allocate hasn't already assigned an object // in a different thread or permitted a new object to be created if (latch.getPair() == null && !latch.mayCreate()) { // Remove latch from the allocation queue _allocationQueue.remove(latch); } else { break; } } throw new NoSuchElementException("Timeout waiting for idle object"); } else { continue; // keep looping } default: throw new IllegalArgumentException("WhenExhaustedAction property " + whenExhaustedAction + " not recognized."); } } } boolean newlyCreated = false; if(null == latch.getPair()) { try { T obj = _factory.makeObject(); latch.setPair(new ObjectTimestampPair(obj)); newlyCreated = true; } finally { if (!newlyCreated) { // object cannot be created synchronized (this) { _numInternalProcessing--; // No need to reset latch - about to throw exception } allocate(); } } } // activate & validate the object try { _factory.activateObject(latch.getPair().value); if(_testOnBorrow && !_factory.validateObject(latch.getPair().value)) { throw new Exception("ValidateObject failed"); } synchronized(this) { _numInternalProcessing--; _numActive++; } return latch.getPair().value; } catch (Throwable e) { PoolUtils.checkRethrow(e); // object cannot be activated or is invalid try { _factory.destroyObject(latch.getPair().value); } catch (Throwable e2) { PoolUtils.checkRethrow(e2); // cannot destroy broken object } synchronized (this) { _numInternalProcessing--; if (!newlyCreated) { latch.reset(); _allocationQueue.add(0, latch); } } allocate(); if(newlyCreated) { throw new NoSuchElementException("Could not create a validated object, cause: " + e.getMessage()); } else { continue; // keep looping } } } } /** * Allocate available instances to latches in the allocation queue. Then * set _mayCreate to true for as many additional latches remaining in queue * as _maxActive allows. While it is safe for GOP, for consistency with GKOP * this method should not be called from inside a sync block. */ private synchronized void allocate() { if (isClosed()) return; // First use any objects in the pool to clear the queue for (;;) { if (!_pool.isEmpty() && !_allocationQueue.isEmpty()) { Latch latch = _allocationQueue.removeFirst(); latch.setPair( _pool.removeFirst()); _numInternalProcessing++; synchronized (latch) { latch.notify(); } } else { break; } } // Second utilise any spare capacity to create new objects for(;;) { if((!_allocationQueue.isEmpty()) && (_maxActive < 0 || (_numActive + _numInternalProcessing) < _maxActive)) { Latch latch = _allocationQueue.removeFirst(); latch.setMayCreate(true); _numInternalProcessing++; synchronized (latch) { latch.notify(); } } else { break; } } } /** * {@inheritDoc} *

Activation of this method decrements the active count and attempts to destroy the instance.

* * @throws Exception if the configured {@link PoolableObjectFactory} throws an exception destroying obj */ @Override public void invalidateObject(T obj) throws Exception { try { if (_factory != null) { _factory.destroyObject(obj); } } finally { synchronized (this) { _numActive--; } allocate(); } } /** * Clears any objects sitting idle in the pool by removing them from the * idle instance pool and then invoking the configured * {@link PoolableObjectFactory#destroyObject(Object)} method on each idle * instance. * *

Implementation notes: *

  • This method does not destroy or effect in any way instances that are * checked out of the pool when it is invoked.
  • *
  • Invoking this method does not prevent objects being * returned to the idle instance pool, even during its execution. It locks * the pool only during instance removal. Additional instances may be returned * while removed items are being destroyed.
  • *
  • Exceptions encountered destroying idle instances are swallowed.

*/ @Override public void clear() { List> toDestroy = new ArrayList>(); synchronized(this) { toDestroy.addAll(_pool); _numInternalProcessing = _numInternalProcessing + _pool._size; _pool.clear(); } destroy(toDestroy, _factory); } /** * Private method to destroy all the objects in a collection using the * supplied object factory. Assumes that objects in the collection are * instances of ObjectTimestampPair and that the object instances that * they wrap were created by the factory. * * @param c Collection of objects to destroy * @param factory PoolableConnectionFactory used to destroy the objects */ private void destroy(Collection> c, PoolableObjectFactory factory) { for (Iterator> it = c.iterator(); it.hasNext();) { try { factory.destroyObject(it.next().value); } catch(Exception e) { // ignore error, keep destroying the rest } finally { synchronized(this) { _numInternalProcessing--; } allocate(); } } } /** * Return the number of instances currently borrowed from this pool. * * @return the number of instances currently borrowed from this pool */ @Override public synchronized int getNumActive() { return _numActive; } /** * Return the number of instances currently idle in this pool. * * @return the number of instances currently idle in this pool */ @Override public synchronized int getNumIdle() { return _pool.size(); } /** *

Returns an object instance to the pool.

* *

If {@link #getMaxIdle() maxIdle} is set to a positive value and the number of idle instances * has reached this value, the returning instance is destroyed.

* *

If {@link #getTestOnReturn() testOnReturn} == true, the returning instance is validated before being returned * to the idle instance pool. In this case, if validation fails, the instance is destroyed.

* *

Note: There is no guard to prevent an object * being returned to the pool multiple times. Clients are expected to * discard references to returned objects and ensure that an object is not * returned to the pool multiple times in sequence (i.e., without being * borrowed again between returns). Violating this contract will result in * the same object appearing multiple times in the pool and pool counters * (numActive, numIdle) returning incorrect values.

* * @param obj instance to return to the pool */ @Override public void returnObject(T obj) throws Exception { try { addObjectToPool(obj, true); } catch (Exception e) { if (_factory != null) { try { _factory.destroyObject(obj); } catch (Exception e2) { // swallowed } // TODO: Correctness here depends on control in addObjectToPool. // These two methods should be refactored, removing the // "behavior flag", decrementNumActive, from addObjectToPool. synchronized(this) { _numActive--; } allocate(); } } } /** *

Adds an object to the pool.

* *

Validates the object if testOnReturn == true and passivates it before returning it to the pool. * if validation or passivation fails, or maxIdle is set and there is no room in the pool, the instance * is destroyed.

* *

Calls {@link #allocate()} on successful completion

* * @param obj instance to add to the pool * @param decrementNumActive whether or not to decrement the active count * @throws Exception */ private void addObjectToPool(T obj, boolean decrementNumActive) throws Exception { boolean success = true; if(_testOnReturn && !(_factory.validateObject(obj))) { success = false; } else { _factory.passivateObject(obj); } boolean shouldDestroy = !success; // Add instance to pool if there is room and it has passed validation // (if testOnreturn is set) boolean doAllocate = false; synchronized (this) { if (isClosed()) { shouldDestroy = true; } else { if((_maxIdle >= 0) && (_pool.size() >= _maxIdle)) { shouldDestroy = true; } else if(success) { // borrowObject always takes the first element from the queue, // so for LIFO, push on top, FIFO add to end if (_lifo) { _pool.addFirst(new ObjectTimestampPair(obj)); } else { _pool.addLast(new ObjectTimestampPair(obj)); } if (decrementNumActive) { _numActive--; } doAllocate = true; } } } if (doAllocate) { allocate(); } // Destroy the instance if necessary if(shouldDestroy) { try { _factory.destroyObject(obj); } catch(Exception e) { // ignored } // Decrement active count *after* destroy if applicable if (decrementNumActive) { synchronized(this) { _numActive--; } allocate(); } } } /** *

Closes the pool. Once the pool is closed, {@link #borrowObject()} * will fail with IllegalStateException, but {@link #returnObject(Object)} and * {@link #invalidateObject(Object)} will continue to work, with returned objects * destroyed on return.

* *

Destroys idle instances in the pool by invoking {@link #clear()}.

* * @throws Exception */ @Override public void close() throws Exception { super.close(); synchronized (this) { clear(); startEvictor(-1L); while(_allocationQueue.size() > 0) { Latch l = _allocationQueue.removeFirst(); synchronized (l) { // notify the waiting thread l.notify(); } } } } /** * Sets the {@link PoolableObjectFactory factory} this pool uses * to create new instances. Trying to change * the factory while there are borrowed objects will * throw an {@link IllegalStateException}. If there are instances idle * in the pool when this method is invoked, these will be destroyed * using the original factory. * * @param factory the {@link PoolableObjectFactory} used to create new instances. * @throws IllegalStateException when the factory cannot be set at this time * @deprecated to be removed in version 2.0 */ @Deprecated @Override public void setFactory(PoolableObjectFactory factory) throws IllegalStateException { List> toDestroy = new ArrayList>(); final PoolableObjectFactory oldFactory = _factory; synchronized (this) { assertOpen(); if(0 < getNumActive()) { throw new IllegalStateException("Objects are already active"); } else { toDestroy.addAll(_pool); _numInternalProcessing = _numInternalProcessing + _pool._size; _pool.clear(); } _factory = factory; } destroy(toDestroy, oldFactory); } /** *

Perform numTests idle object eviction tests, evicting * examined objects that meet the criteria for eviction. If * testWhileIdle is true, examined objects are validated * when visited (and removed if invalid); otherwise only objects that * have been idle for more than minEvicableIdletimeMillis * are removed.

* *

Successive activations of this method examine objects in * in sequence, cycling through objects in oldest-to-youngest order.

* * @throws Exception if the pool is closed or eviction fails. */ public void evict() throws Exception { assertOpen(); synchronized (this) { if(_pool.isEmpty()) { return; } if (null == _evictionCursor) { _evictionCursor = _pool.cursor(_lifo ? _pool.size() : 0); } } for (int i=0,m=getNumTests();i pair; synchronized (this) { if ((_lifo && !_evictionCursor.hasPrevious()) || !_lifo && !_evictionCursor.hasNext()) { _evictionCursor.close(); _evictionCursor = _pool.cursor(_lifo ? _pool.size() : 0); } pair = _lifo ? _evictionCursor.previous() : _evictionCursor.next(); _evictionCursor.remove(); _numInternalProcessing++; } boolean removeObject = false; final long idleTimeMilis = System.currentTimeMillis() - pair.tstamp; if ((getMinEvictableIdleTimeMillis() > 0) && (idleTimeMilis > getMinEvictableIdleTimeMillis())) { removeObject = true; } else if ((getSoftMinEvictableIdleTimeMillis() > 0) && (idleTimeMilis > getSoftMinEvictableIdleTimeMillis()) && ((getNumIdle() + 1)> getMinIdle())) { // +1 accounts for object we are processing removeObject = true; } if(getTestWhileIdle() && !removeObject) { boolean active = false; try { _factory.activateObject(pair.value); active = true; } catch(Exception e) { removeObject=true; } if(active) { if(!_factory.validateObject(pair.value)) { removeObject=true; } else { try { _factory.passivateObject(pair.value); } catch(Exception e) { removeObject=true; } } } } if (removeObject) { try { _factory.destroyObject(pair.value); } catch(Exception e) { // ignored } } synchronized (this) { if(!removeObject) { _evictionCursor.add(pair); if (_lifo) { // Skip over the element we just added back _evictionCursor.previous(); } } _numInternalProcessing--; } } allocate(); } /** * Check to see if we are below our minimum number of objects * if so enough to bring us back to our minimum. * * @throws Exception when {@link #addObject()} fails. */ private void ensureMinIdle() throws Exception { // this method isn't synchronized so the // calculateDeficit is done at the beginning // as a loop limit and a second time inside the loop // to stop when another thread already returned the // needed objects int objectDeficit = calculateDeficit(false); for ( int j = 0 ; j < objectDeficit && calculateDeficit(true) > 0 ; j++ ) { try { addObject(); } finally { synchronized (this) { _numInternalProcessing--; } allocate(); } } } /** * This returns the number of objects to create during the pool * sustain cycle. This will ensure that the minimum number of idle * instances is maintained without going past the maxActive value. * * @param incrementInternal - Should the count of objects currently under * some form of internal processing be * incremented? * @return The number of objects to be created */ private synchronized int calculateDeficit(boolean incrementInternal) { int objectDeficit = getMinIdle() - getNumIdle(); if (_maxActive > 0) { int growLimit = Math.max(0, getMaxActive() - getNumActive() - getNumIdle() - _numInternalProcessing); objectDeficit = Math.min(objectDeficit, growLimit); } if (incrementInternal && objectDeficit >0) { _numInternalProcessing++; } return objectDeficit; } /** * Create an object, and place it into the pool. * addObject() is useful for "pre-loading" a pool with idle objects. */ @Override public void addObject() throws Exception { assertOpen(); if (_factory == null) { throw new IllegalStateException("Cannot add objects without a factory."); } T obj = _factory.makeObject(); try { assertOpen(); addObjectToPool(obj, false); } catch (IllegalStateException ex) { // Pool closed try { _factory.destroyObject(obj); } catch (Exception ex2) { // swallow } throw ex; } } //--- non-public methods ---------------------------------------- /** * Start the eviction thread or service, or when * delay is non-positive, stop it * if it is already running. * * @param delay milliseconds between evictor runs. */ protected synchronized void startEvictor(long delay) { if(null != _evictor) { EvictionTimer.cancel(_evictor); _evictor = null; } if(delay > 0) { _evictor = new Evictor(); EvictionTimer.schedule(_evictor, delay, delay); } } /** * Returns pool info including {@link #getNumActive()}, {@link #getNumIdle()} * and a list of objects idle in the pool with their idle times. * * @return string containing debug information */ synchronized String debugInfo() { StringBuffer buf = new StringBuffer(); buf.append("Active: ").append(getNumActive()).append("\n"); buf.append("Idle: ").append(getNumIdle()).append("\n"); buf.append("Idle Objects:\n"); Iterator> it = _pool.iterator(); long time = System.currentTimeMillis(); while(it.hasNext()) { ObjectTimestampPair pair = it.next(); buf.append("\t").append(pair.value).append("\t").append(time - pair.tstamp).append("\n"); } return buf.toString(); } /** * Returns the number of tests to be performed in an Evictor run, * based on the current value of numTestsPerEvictionRun * and the number of idle instances in the pool. * * @see #setNumTestsPerEvictionRun * @return the number of tests for the Evictor to run */ private int getNumTests() { if(_numTestsPerEvictionRun >= 0) { return Math.min(_numTestsPerEvictionRun, _pool.size()); } else { return(int)(Math.ceil(_pool.size()/Math.abs((double)_numTestsPerEvictionRun))); } } //--- inner classes ---------------------------------------------- /** * The idle object evictor {@link TimerTask}. * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis */ private class Evictor extends TimerTask { /** * Run pool maintenance. Evict objects qualifying for eviction and then * invoke {@link GenericObjectPool#ensureMinIdle()}. */ @Override public void run() { try { evict(); } catch(Exception e) { // ignored } catch(OutOfMemoryError oome) { // Log problem but give evictor thread a chance to continue in // case error is recoverable oome.printStackTrace(System.err); } try { ensureMinIdle(); } catch(Exception e) { // ignored } } } /** * A simple "struct" encapsulating the * configuration information for a {@link GenericObjectPool}. * @see GenericObjectPool#GenericObjectPool(org.apache.commons.pool.PoolableObjectFactory, * org.apache.commons.pool.impl.GenericObjectPool.Config) * @see GenericObjectPool#setConfig */ public static class Config { //CHECKSTYLE: stop VisibilityModifier /** * @see GenericObjectPool#setMaxIdle */ public int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE; /** * @see GenericObjectPool#setMinIdle */ public int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE; /** * @see GenericObjectPool#setMaxActive */ public int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE; /** * @see GenericObjectPool#setMaxWait */ public long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT; /** * @see GenericObjectPool#setWhenExhaustedAction */ public byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION; /** * @see GenericObjectPool#setTestOnBorrow */ public boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW; /** * @see GenericObjectPool#setTestOnReturn */ public boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN; /** * @see GenericObjectPool#setTestWhileIdle */ public boolean testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE; /** * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis */ public long timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; /** * @see GenericObjectPool#setNumTestsPerEvictionRun */ public int numTestsPerEvictionRun = GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; /** * @see GenericObjectPool#setMinEvictableIdleTimeMillis */ public long minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; /** * @see GenericObjectPool#setSoftMinEvictableIdleTimeMillis */ public long softMinEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS; /** * @see GenericObjectPool#setLifo */ public boolean lifo = GenericObjectPool.DEFAULT_LIFO; //CHECKSTYLE: resume VisibilityModifier } /** * Latch used to control allocation order of objects to threads to ensure * fairness. That is, objects are allocated to threads in the order that * threads request objects. */ private static final class Latch { /** object timestamp pair allocated to this latch */ private ObjectTimestampPair _pair; /** Whether or not this latch may create an object instance */ private boolean _mayCreate = false; /** * Returns ObjectTimestampPair allocated to this latch * @return ObjectTimestampPair allocated to this latch */ private synchronized ObjectTimestampPair getPair() { return _pair; } /** * Sets ObjectTimestampPair on this latch * @param pair ObjectTimestampPair allocated to this latch */ private synchronized void setPair(ObjectTimestampPair pair) { _pair = pair; } /** * Whether or not this latch may create an object instance * @return true if this latch has an instance creation permit */ private synchronized boolean mayCreate() { return _mayCreate; } /** * Sets the mayCreate property * @param mayCreate new value for mayCreate */ private synchronized void setMayCreate(boolean mayCreate) { _mayCreate = mayCreate; } /** * Reset the latch data. Used when an allocation fails and the latch * needs to be re-added to the queue. */ private synchronized void reset() { _pair = null; _mayCreate = false; } } //--- private attributes --------------------------------------- /** * The cap on the number of idle instances in the pool. * @see #setMaxIdle * @see #getMaxIdle */ private int _maxIdle = DEFAULT_MAX_IDLE; /** * The cap on the minimum number of idle instances in the pool. * @see #setMinIdle * @see #getMinIdle */ private int _minIdle = DEFAULT_MIN_IDLE; /** * The cap on the total number of active instances from the pool. * @see #setMaxActive * @see #getMaxActive */ private int _maxActive = DEFAULT_MAX_ACTIVE; /** * The maximum amount of time (in millis) the * {@link #borrowObject} method should block before throwing * an exception when the pool is exhausted and the * {@link #getWhenExhaustedAction "when exhausted" action} is * {@link #WHEN_EXHAUSTED_BLOCK}. * * When less than or equal to 0, the {@link #borrowObject} method * may block indefinitely. * * @see #setMaxWait * @see #getMaxWait * @see #WHEN_EXHAUSTED_BLOCK * @see #setWhenExhaustedAction * @see #getWhenExhaustedAction */ private long _maxWait = DEFAULT_MAX_WAIT; /** * The action to take when the {@link #borrowObject} method * is invoked when the pool is exhausted (the maximum number * of "active" objects has been reached). * * @see #WHEN_EXHAUSTED_BLOCK * @see #WHEN_EXHAUSTED_FAIL * @see #WHEN_EXHAUSTED_GROW * @see #DEFAULT_WHEN_EXHAUSTED_ACTION * @see #setWhenExhaustedAction * @see #getWhenExhaustedAction */ private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION; /** * When true, objects will be * {@link PoolableObjectFactory#validateObject validated} * before being returned by the {@link #borrowObject} * method. If the object fails to validate, * it will be dropped from the pool, and we will attempt * to borrow another. * * @see #setTestOnBorrow * @see #getTestOnBorrow */ private volatile boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW; /** * When true, objects will be * {@link PoolableObjectFactory#validateObject validated} * before being returned to the pool within the * {@link #returnObject}. * * @see #getTestOnReturn * @see #setTestOnReturn */ private volatile boolean _testOnReturn = DEFAULT_TEST_ON_RETURN; /** * When true, objects will be * {@link PoolableObjectFactory#validateObject validated} * by the idle object evictor (if any). If an object * fails to validate, it will be dropped from the pool. * * @see #setTestWhileIdle * @see #getTestWhileIdle * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ private boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE; /** * 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 #setTimeBetweenEvictionRunsMillis * @see #getTimeBetweenEvictionRunsMillis */ private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; /** * The max number of objects to examine during each run of the * idle object evictor thread (if any). *

* When a negative value is supplied, ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun}) * tests will be run. I.e., when the value is -n, roughly one nth of the * idle objects will be tested per run. * * @see #setNumTestsPerEvictionRun * @see #getNumTestsPerEvictionRun * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ private int _numTestsPerEvictionRun = 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). * When non-positive, no objects will be evicted from the pool * due to idle time alone. * * @see #setMinEvictableIdleTimeMillis * @see #getMinEvictableIdleTimeMillis * @see #getTimeBetweenEvictionRunsMillis * @see #setTimeBetweenEvictionRunsMillis */ private long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; /** * 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), with the extra condition that at least * "minIdle" amount of object remain in the pool. * When non-positive, no objects will be evicted from the pool * due to idle time alone. * * @see #setSoftMinEvictableIdleTimeMillis * @see #getSoftMinEvictableIdleTimeMillis */ private long _softMinEvictableIdleTimeMillis = DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS; /** Whether or not the pool behaves as a LIFO queue (last in first out) */ private boolean _lifo = DEFAULT_LIFO; /** My pool. */ private CursorableLinkedList> _pool = null; /** Eviction cursor - keeps track of idle object evictor position */ private CursorableLinkedList>.Cursor _evictionCursor = null; /** My {@link PoolableObjectFactory}. */ private PoolableObjectFactory _factory = null; /** * The number of objects {@link #borrowObject} borrowed * from the pool, but not yet returned. */ private int _numActive = 0; /** * My idle object eviction {@link TimerTask}, if any. */ private Evictor _evictor = null; /** * The number of objects subject to some form of internal processing * (usually creation or destruction) that should be included in the total * number of objects but are neither active nor idle. */ private int _numInternalProcessing = 0; /** * Used to track the order in which threads call {@link #borrowObject()} so * that objects can be allocated in the order in which the threads requested * them. */ private final LinkedList> _allocationQueue = new LinkedList>(); } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/GenericObjectPoolFactory.java100644 0 0 63433 11701070262 26600 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.ObjectPoolFactory; import org.apache.commons.pool.PoolableObjectFactory; /** * A factory for creating {@link GenericObjectPool} instances. * * @param the type of objects held in this pool * * @see GenericObjectPool * @see ObjectPoolFactory * * @author Rodney Waldhoff * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public class GenericObjectPoolFactory implements ObjectPoolFactory { /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory) */ public GenericObjectPoolFactory(PoolableObjectFactory factory) { this(factory,GenericObjectPool.DEFAULT_MAX_ACTIVE,GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,GenericObjectPool.DEFAULT_MAX_WAIT,GenericObjectPool.DEFAULT_MAX_IDLE,GenericObjectPool.DEFAULT_MIN_IDLE,GenericObjectPool.DEFAULT_TEST_ON_BORROW,GenericObjectPool.DEFAULT_TEST_ON_RETURN,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param config a non-null GenericObjectPool.Config describing the configuration. * @throws NullPointerException when config is null. * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory, GenericObjectPool.Config) */ public GenericObjectPoolFactory(PoolableObjectFactory factory, GenericObjectPool.Config config) throws NullPointerException { this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.minIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle,config.softMinEvictableIdleTimeMillis, config.lifo); } /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxActive maximum number of objects that can be borrowed from created pools at one time. * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory, int) */ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive) { this(factory,maxActive,GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,GenericObjectPool.DEFAULT_MAX_WAIT,GenericObjectPool.DEFAULT_MAX_IDLE,GenericObjectPool.DEFAULT_MIN_IDLE,GenericObjectPool.DEFAULT_TEST_ON_BORROW,GenericObjectPool.DEFAULT_TEST_ON_RETURN,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxActive maximum number of objects that can be borrowed from created pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory, int, byte, long) */ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) { this(factory,maxActive,whenExhaustedAction,maxWait,GenericObjectPool.DEFAULT_MAX_IDLE,GenericObjectPool.DEFAULT_MIN_IDLE,GenericObjectPool.DEFAULT_TEST_ON_BORROW,GenericObjectPool.DEFAULT_TEST_ON_RETURN,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxActive maximum number of objects that can be borrowed from created pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param testOnBorrow whether to validate objects before they are returned by the borrowObject. * @param testOnReturn whether to validate objects after they are returned to the returnObject. * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory, int, byte, long, boolean, boolean) */ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) { this(factory,maxActive,whenExhaustedAction,maxWait,GenericObjectPool.DEFAULT_MAX_IDLE,GenericObjectPool.DEFAULT_MIN_IDLE,testOnBorrow,testOnReturn,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxActive maximum number of objects that can be borrowed from created pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in my pool. * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory, int, byte, long, int) */ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) { this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,GenericObjectPool.DEFAULT_MIN_IDLE,GenericObjectPool.DEFAULT_TEST_ON_BORROW,GenericObjectPool.DEFAULT_TEST_ON_RETURN,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxActive maximum number of objects that can be borrowed from created pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in my pool. * @param testOnBorrow whether to validate objects before they are returned by the borrowObject. * @param testOnReturn whether to validate objects after they are returned to the returnObject. * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory, int, byte, long, int, boolean, boolean) */ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) { this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,GenericObjectPool.DEFAULT_MIN_IDLE,testOnBorrow,testOnReturn,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE); } /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxActive maximum number of objects that can be borrowed from created pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in my pool. * @param testOnBorrow whether to validate objects before they are returned by the borrowObject. * @param testOnReturn whether to validate objects after they are returned to the returnObject. * @param timeBetweenEvictionRunsMillis the number of milliseconds to sleep between examining idle objects for eviction. * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread. * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction. * @param testWhileIdle whether or not to validate objects in the idle object eviction thread. * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory, int, byte, long, int, boolean, boolean, long, int, long, boolean) */ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,GenericObjectPool.DEFAULT_MIN_IDLE,testOnBorrow,testOnReturn,timeBetweenEvictionRunsMillis,numTestsPerEvictionRun,minEvictableIdleTimeMillis,testWhileIdle, GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS); } /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxActive maximum number of objects that can be borrowed from created pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in my pool. * @param minIdle the minimum number of idle objects in my pool. * @param testOnBorrow whether to validate objects before they are returned by the borrowObject. * @param testOnReturn whether to validate objects after they are returned to the returnObject. * @param timeBetweenEvictionRunsMillis the number of milliseconds to sleep between examining idle objects for eviction. * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread. * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction. * @param testWhileIdle whether or not to validate objects in the idle object eviction thread. * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory, int, byte, long, int, int, boolean, boolean, long, int, long, boolean) */ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,minIdle,testOnBorrow,testOnReturn,timeBetweenEvictionRunsMillis,numTestsPerEvictionRun,minEvictableIdleTimeMillis,testWhileIdle, GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS); } /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxActive maximum number of objects that can be borrowed from created pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in my pool. * @param minIdle the minimum number of idle objects in my pool. * @param testOnBorrow whether to validate objects before they are returned by the borrowObject. * @param testOnReturn whether to validate objects after they are returned to the returnObject. * @param timeBetweenEvictionRunsMillis the number of milliseconds to sleep between examining idle objects for eviction. * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread. * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction. * @param testWhileIdle whether or not to validate objects in the idle object eviction thread. * @param softMinEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction with the extra condition that at least "minIdle" amount of object remain in the pool. * @since Pool 1.3 * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory, int, byte, long, int, int, boolean, boolean, long, int, long, boolean, long) */ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, long softMinEvictableIdleTimeMillis) { this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,minIdle,testOnBorrow,testOnReturn,timeBetweenEvictionRunsMillis,numTestsPerEvictionRun,minEvictableIdleTimeMillis,testWhileIdle,softMinEvictableIdleTimeMillis, GenericObjectPool.DEFAULT_LIFO); } /** * Create a new GenericObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxActive maximum number of objects that can be borrowed from created pools at one time. * @param whenExhaustedAction the action to take when the pool is exhausted. * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted. * @param maxIdle the maximum number of idle objects in my pool. * @param minIdle the minimum number of idle objects in my pool. * @param testOnBorrow whether to validate objects before they are returned by the borrowObject. * @param testOnReturn whether to validate objects after they are returned to the returnObject. * @param timeBetweenEvictionRunsMillis the number of milliseconds to sleep between examining idle objects for eviction. * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread. * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction. * @param testWhileIdle whether or not to validate objects in the idle object eviction thread. * @param softMinEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction with the extra condition that at least "minIdle" amount of object remain in the pool. * @param lifo whether or not objects are returned in last-in-first-out order from the idle object pool. * @since Pool 1.4 * @see GenericObjectPool#GenericObjectPool(PoolableObjectFactory, int, byte, long, int, int, boolean, boolean, long, int, long, boolean, long, boolean) */ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, long softMinEvictableIdleTimeMillis, boolean lifo) { _maxIdle = maxIdle; _minIdle = minIdle; _maxActive = maxActive; _maxWait = maxWait; _whenExhaustedAction = whenExhaustedAction; _testOnBorrow = testOnBorrow; _testOnReturn = testOnReturn; _testWhileIdle = testWhileIdle; _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; _numTestsPerEvictionRun = numTestsPerEvictionRun; _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; _softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; _lifo = lifo; _factory = factory; } /** * {@inheritDoc} */ public ObjectPool createPool() { return new GenericObjectPool(_factory,_maxActive,_whenExhaustedAction,_maxWait,_maxIdle,_minIdle,_testOnBorrow,_testOnReturn,_timeBetweenEvictionRunsMillis,_numTestsPerEvictionRun,_minEvictableIdleTimeMillis,_testWhileIdle,_softMinEvictableIdleTimeMillis,_lifo); } /** * @return the {@link GenericObjectPool#getMaxIdle() maxIdle} setting for pools created by this factory. * @since 1.5.5 */ public int getMaxIdle() { return _maxIdle; } /** * @return the {@link GenericObjectPool#getMinIdle() minIdle} setting for pools created by this factory. * @since 1.5.5 */ public int getMinIdle() { return _minIdle; } /** * @return the {@link GenericObjectPool#getMaxActive() maxActive} setting for pools created by this factory. * @since 1.5.5 */ public int getMaxActive() { return _maxActive; } /** * @return the {@link GenericObjectPool#getMaxWait() maxWait} setting for pools created by this factory. * @since 1.5.5 */ public long getMaxWait() { return _maxWait; } /** * @return the {@link GenericObjectPool#getWhenExhaustedAction() whenExhaustedAction} setting for pools * created by this factory. * @since 1.5.5 */ public byte getWhenExhaustedAction() { return _whenExhaustedAction; } /** * @return the {@link GenericObjectPool#getTestOnBorrow() testOnBorrow} setting for pools * created by this factory. * @since 1.5.5 */ public boolean getTestOnBorrow() { return _testOnBorrow; } /** * @return the {@link GenericObjectPool#getTestOnReturn() testOnReturn} setting for pools * created by this factory. * @since 1.5.5 */ public boolean getTestOnReturn() { return _testOnReturn; } /** * @return the {@link GenericObjectPool#getTestWhileIdle() testWhileIdle} setting for pools * created by this factory. * @since 1.5.5 */ public boolean getTestWhileIdle() { return _testWhileIdle; } /** * @return the {@link GenericObjectPool#getTimeBetweenEvictionRunsMillis() timeBetweenEvictionRunsMillis} * setting for pools created by this factory. * @since 1.5.5 */ public long getTimeBetweenEvictionRunsMillis() { return _timeBetweenEvictionRunsMillis; } /** * @return the {@link GenericObjectPool#getNumTestsPerEvictionRun() numTestsPerEvictionRun} * setting for pools created by this factory. * @since 1.5.5 */ public int getNumTestsPerEvictionRun() { return _numTestsPerEvictionRun; } /** * @return the {@link GenericObjectPool#getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} * setting for pools created by this factory. * @since 1.5.5 */ public long getMinEvictableIdleTimeMillis() { return _minEvictableIdleTimeMillis; } /** * @return the {@link GenericObjectPool#getSoftMinEvictableIdleTimeMillis() softMinEvicatableIdleTimeMillis} * setting for pools created by this factory. * @since 1.5.5 */ public long getSoftMinEvictableIdleTimeMillis() { return _softMinEvictableIdleTimeMillis; } /** * @return the {@link GenericObjectPool#getLifo() lifo} setting for pools created by this factory. * @since 1.5.5 */ public boolean getLifo() { return _lifo; } /** * @return the {@link PoolableObjectFactory} used by pools created by this factory */ public PoolableObjectFactory getFactory() { return _factory; } /** * The {@link GenericObjectPool#getMaxIdle() maxIdle} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMaxIdle()}. */ @Deprecated protected int _maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE; /** * The {@link GenericObjectPool#getMinIdle() minIdle} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMinIdle()}. */ @Deprecated protected int _minIdle = GenericObjectPool.DEFAULT_MIN_IDLE; /** * The {@link GenericObjectPool#getMaxActive() maxActive} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMaxActive()}. */ @Deprecated protected int _maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE; /** * The {@link GenericObjectPool#getMaxWait() maxWait} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMaxWait()}. */ @Deprecated protected long _maxWait = GenericObjectPool.DEFAULT_MAX_WAIT; /** * The {@link GenericObjectPool#getWhenExhaustedAction() whenExhaustedAction} setting for pools * created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getWhenExhaustedAction()}. */ @Deprecated protected byte _whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION; /** * The {@link GenericObjectPool#getTestOnBorrow() testOnBorrow} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getTestOnBorrow()}. */ @Deprecated protected boolean _testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW; /** * The {@link GenericObjectPool#getTestOnReturn() testOnReturn} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getTestOnReturn()}. */ @Deprecated protected boolean _testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN; /** * The {@link GenericObjectPool#getTestWhileIdle() testWhileIdle} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getTestWhileIdle()}. */ @Deprecated protected boolean _testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE; /** * The {@link GenericObjectPool#getTimeBetweenEvictionRunsMillis() timeBetweenEvictionRunsMillis} * setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getTimeBetweenEvictionRunsMillis()}. */ @Deprecated protected long _timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; /** * The {@link GenericObjectPool#getNumTestsPerEvictionRun() numTestsPerEvictionRun} setting * for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getNumTestsPerEvictionRun()}. */ @Deprecated protected int _numTestsPerEvictionRun = GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; /** * The {@link GenericObjectPool#getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} * setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getMinEvictableIdleTimeMillis()}. */ @Deprecated protected long _minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; /** * The {@link GenericObjectPool#getSoftMinEvictableIdleTimeMillis() softMinEvictableIdleTimeMillis} * setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getSoftMinEvictableIdleTimeMillis()}. */ @Deprecated protected long _softMinEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; /** * The {@link GenericObjectPool#getLifo() lifo} setting for pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getLifo()}. */ @Deprecated protected boolean _lifo = GenericObjectPool.DEFAULT_LIFO; /** * The {@link PoolableObjectFactory} used by pools created by this factory. * @deprecated to be removed in pool 2.0. Use {@link #getFactory()}. */ @Deprecated protected PoolableObjectFactory _factory = null; } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/package.html100644 0 0 5532 11701070262 23305 0ustar 0 0 Package Documentation for org.apache.commons.pool.impl

Object pooling API implementations.

{@link org.apache.commons.pool.impl.StackObjectPool StackObjectPool} ({@link org.apache.commons.pool.impl.StackKeyedObjectPool StackKeyedObjectPool}) provides a simple, {@link java.util.Stack Stack}-based implementation of {@link org.apache.commons.pool.ObjectPool ObjectPool} ({@link org.apache.commons.pool.KeyedObjectPool KeyedObjectPool}). {@link org.apache.commons.pool.impl.StackObjectPoolFactory StackObjectPoolFactory} ({@link org.apache.commons.pool.impl.StackKeyedObjectPoolFactory StackKeyedObjectPoolFactory}) provides an implementation of the {@link org.apache.commons.pool.ObjectPoolFactory ObjectPoolFactory} ({@link org.apache.commons.pool.KeyedObjectPoolFactory KeyedObjectPoolFactory}) factory interface for this class.

{@link org.apache.commons.pool.impl.GenericObjectPool GenericObjectPool} ({@link org.apache.commons.pool.impl.GenericKeyedObjectPool GenericKeyedObjectPool}) provides a more robust (but also more complicated) implementation of {@link org.apache.commons.pool.ObjectPool ObjectPool} ({@link org.apache.commons.pool.KeyedObjectPool KeyedObjectPool}). {@link org.apache.commons.pool.impl.GenericObjectPoolFactory GenericObjectPoolFactory} ({@link org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory GenericKeyedObjectPoolFactory}) provides an implementation of the {@link org.apache.commons.pool.ObjectPoolFactory ObjectPoolFactory} ({@link org.apache.commons.pool.KeyedObjectPoolFactory KeyedObjectPoolFactory}) factory interface for this class.

See also the {@link org.apache.commons.pool} package.

commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/SoftReferenceObjectPool.java100644 0 0 34457 11701070262 26432 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import org.apache.commons.pool.BaseObjectPool; import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.PoolUtils; import org.apache.commons.pool.PoolableObjectFactory; /** * A {@link java.lang.ref.SoftReference SoftReference} based * {@link ObjectPool}. * * @param the type of objects held in this pool * * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222710 $ $Date: 2011-12-23 10:58:12 -0500 (Fri, 23 Dec 2011) $ * @since Pool 1.0 */ public class SoftReferenceObjectPool extends BaseObjectPool implements ObjectPool { /** * Create a SoftReferenceObjectPool without a factory. * {@link #setFactory(PoolableObjectFactory) setFactory} should be called * before any attempts to use the pool are made. * Generally speaking you should prefer the {@link #SoftReferenceObjectPool(PoolableObjectFactory)} constructor. * * @see #SoftReferenceObjectPool(PoolableObjectFactory) * @deprecated to be removed in pool 2.0. Use {@link #SoftReferenceObjectPool(PoolableObjectFactory)}. */ @Deprecated public SoftReferenceObjectPool() { _pool = new ArrayList>(); _factory = null; } /** * Create a SoftReferenceObjectPool with the specified factory. * * @param factory object factory to use. */ public SoftReferenceObjectPool(PoolableObjectFactory factory) { _pool = new ArrayList>(); _factory = factory; } /** * Create a SoftReferenceObjectPool with the specified factory and initial idle object count. * * @param factory object factory to use. * @param initSize initial size to attempt to prefill the pool. * @throws Exception when there is a problem prefilling the pool. * @throws IllegalArgumentException when factory is null. * @deprecated because this is a SoftReference pool, prefilled idle obejects may be garbage collected before they are used. * To be removed in Pool 2.0. */ @Deprecated public SoftReferenceObjectPool(PoolableObjectFactory factory, int initSize) throws Exception, IllegalArgumentException { if (factory == null) { throw new IllegalArgumentException("factory required to prefill the pool."); } _pool = new ArrayList>(initSize); _factory = factory; PoolUtils.prefill(this, initSize); } /** *

Borrow an object from the pool. If there are no idle instances available in the pool, the configured * factory's {@link PoolableObjectFactory#makeObject()} method is invoked to create a new instance.

* *

All instances are {@link PoolableObjectFactory#activateObject(Object) activated} and * {@link PoolableObjectFactory#validateObject(Object) validated} before being returned by this * method. If validation fails or an exception occurs activating or validating an idle instance, * the failing instance is {@link PoolableObjectFactory#destroyObject(Object) destroyed} and another * instance is retrieved from the pool, validated and activated. This process continues until either the * pool is empty or an instance passes validation. If the pool is empty on activation or * it does not contain any valid instances, the factory's makeObject method is used * to create a new instance. If the created instance either raises an exception on activation or * fails validation, NoSuchElementException is thrown. Exceptions thrown by MakeObject * are propagated to the caller; but other than ThreadDeath or VirtualMachineError, * exceptions generated by activation, validation or destroy methods are swallowed silently.

* * @throws NoSuchElementException if a valid object cannot be provided * @throws IllegalStateException if invoked on a {@link #close() closed} pool * @throws Exception if an exception occurs creating a new instance * @return a valid, activated object instance */ @Override public synchronized T borrowObject() throws Exception { assertOpen(); T obj = null; boolean newlyCreated = false; while(null == obj) { if(_pool.isEmpty()) { if(null == _factory) { throw new NoSuchElementException(); } else { newlyCreated = true; obj = _factory.makeObject(); } } else { SoftReference ref = _pool.remove(_pool.size() - 1); obj = ref.get(); ref.clear(); // prevent this ref from being enqueued with refQueue. } if (null != _factory && null != obj) { try { _factory.activateObject(obj); if (!_factory.validateObject(obj)) { throw new Exception("ValidateObject failed"); } } catch (Throwable t) { PoolUtils.checkRethrow(t); try { _factory.destroyObject(obj); } catch (Throwable t2) { PoolUtils.checkRethrow(t2); // Swallowed } finally { obj = null; } if (newlyCreated) { throw new NoSuchElementException( "Could not create a validated object, cause: " + t.getMessage()); } } } } _numActive++; return obj; } /** *

Returns an instance to the pool after successful validation and passivation. The returning instance * is destroyed if any of the following are true:

    *
  • the pool is closed
  • *
  • {@link PoolableObjectFactory#validateObject(Object) validation} fails
  • *
  • {@link PoolableObjectFactory#passivateObject(Object) passivation} throws an exception
  • *
*

* *

Exceptions passivating or destroying instances are silently swallowed. Exceptions validating * instances are propagated to the client.

* * @param obj instance to return to the pool */ @Override public synchronized void returnObject(T obj) throws Exception { boolean success = !isClosed(); if (_factory != null) { if(!_factory.validateObject(obj)) { success = false; } else { try { _factory.passivateObject(obj); } catch(Exception e) { success = false; } } } boolean shouldDestroy = !success; _numActive--; if(success) { _pool.add(new SoftReference(obj, refQueue)); } notifyAll(); // _numActive has changed if (shouldDestroy && _factory != null) { try { _factory.destroyObject(obj); } catch(Exception e) { // ignored } } } /** * {@inheritDoc} */ @Override public synchronized void invalidateObject(T obj) throws Exception { _numActive--; if (_factory != null) { _factory.destroyObject(obj); } notifyAll(); // _numActive has changed } /** *

Create an object, and place it into the pool. * addObject() is useful for "pre-loading" a pool with idle objects.

* *

Before being added to the pool, the newly created instance is * {@link PoolableObjectFactory#validateObject(Object) validated} and * {@link PoolableObjectFactory#passivateObject(Object) passivated}. If validation * fails, the new instance is {@link PoolableObjectFactory#destroyObject(Object) destroyed}. * Exceptions generated by the factory makeObject or passivate are * propagated to the caller. Exceptions destroying instances are silently swallowed.

* * @throws IllegalStateException if invoked on a {@link #close() closed} pool * @throws Exception when the {@link #getFactory() factory} has a problem creating or passivating an object. */ @Override public synchronized void addObject() throws Exception { assertOpen(); if (_factory == null) { throw new IllegalStateException("Cannot add objects without a factory."); } T obj = _factory.makeObject(); boolean success = true; if(!_factory.validateObject(obj)) { success = false; } else { _factory.passivateObject(obj); } boolean shouldDestroy = !success; if(success) { _pool.add(new SoftReference(obj, refQueue)); notifyAll(); // _numActive has changed } if(shouldDestroy) { try { _factory.destroyObject(obj); } catch(Exception e) { // ignored } } } /** * Returns an approximation not less than the of the number of idle instances in the pool. * * @return estimated number of idle instances in the pool */ @Override public synchronized int getNumIdle() { pruneClearedReferences(); return _pool.size(); } /** * Return the number of instances currently borrowed from this pool. * * @return the number of instances currently borrowed from this pool */ @Override public synchronized int getNumActive() { return _numActive; } /** * Clears any objects sitting idle in the pool. */ @Override public synchronized void clear() { if(null != _factory) { Iterator> iter = _pool.iterator(); while(iter.hasNext()) { try { T obj = iter.next().get(); if(null != obj) { _factory.destroyObject(obj); } } catch(Exception e) { // ignore error, keep destroying the rest } } } _pool.clear(); pruneClearedReferences(); } /** *

Close this pool, and free any resources associated with it. Invokes * {@link #clear()} to destroy and remove instances in the pool.

* *

Calling {@link #addObject} or {@link #borrowObject} after invoking * this method on a pool will cause them to throw an * {@link IllegalStateException}.

* * @throws Exception never - exceptions clearing the pool are swallowed */ @Override public void close() throws Exception { super.close(); clear(); } /** * Sets the {@link PoolableObjectFactory factory} this pool uses * to create new instances. Trying to change * the factory while there are borrowed objects will * throw an {@link IllegalStateException}. * * @param factory the {@link PoolableObjectFactory} used to create new instances. * @throws IllegalStateException when the factory cannot be set at this time * @deprecated to be removed in pool 2.0 */ @Deprecated @Override public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException { assertOpen(); if(0 < getNumActive()) { throw new IllegalStateException("Objects are already active"); } else { clear(); _factory = factory; } } /** * If any idle objects were garbage collected, remove their * {@link Reference} wrappers from the idle object pool. */ private void pruneClearedReferences() { Reference ref; while ((ref = refQueue.poll()) != null) { try { _pool.remove(ref); } catch (UnsupportedOperationException uoe) { // ignored } } } /** * Returns the {@link PoolableObjectFactory} used by this pool to create and manage object instances. * * @return the factory * @since 1.5.5 */ public synchronized PoolableObjectFactory getFactory() { return _factory; } /** My pool. */ private final List> _pool; /** My {@link PoolableObjectFactory}. */ private PoolableObjectFactory _factory = null; /** * Queue of broken references that might be able to be removed from _pool. * This is used to help {@link #getNumIdle()} be more accurate with minimial * performance overhead. */ private final ReferenceQueue refQueue = new ReferenceQueue(); /** Number of active objects. */ private int _numActive = 0; //@GuardeBy("this") } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/StackKeyedObjectPool.java100644 0 0 53675 11701070262 25732 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Stack; import org.apache.commons.pool.BaseKeyedObjectPool; import org.apache.commons.pool.KeyedObjectPool; import org.apache.commons.pool.KeyedPoolableObjectFactory; import org.apache.commons.pool.PoolUtils; /** * A simple, Stack-based KeyedObjectPool implementation. *

* Given a {@link KeyedPoolableObjectFactory}, this class will maintain * a simple pool of instances. A finite number of "sleeping" * or inactive instances is enforced, but when the pool is * empty, new instances are created to support the new load. * Hence this class places no limit on the number of "active" * instances created by the pool, but is quite useful for * re-using Objects without introducing * artificial limits. *

* * @param the type of keys in this pool * @param the type of objects held in this pool * * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222710 $ $Date: 2011-12-23 10:58:12 -0500 (Fri, 23 Dec 2011) $ * @see Stack * @since Pool 1.0 */ public class StackKeyedObjectPool extends BaseKeyedObjectPool implements KeyedObjectPool { /** * Create a new pool using no factory. * Clients must first set the {@link #setFactory factory} or * may populate the pool using {@link #returnObject returnObject} * before they can be {@link #borrowObject borrowed}. * * @see #StackKeyedObjectPool(KeyedPoolableObjectFactory) * @see #setFactory(KeyedPoolableObjectFactory) */ public StackKeyedObjectPool() { this(null,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new pool using no factory. * Clients must first set the {@link #setFactory factory} or * may populate the pool using {@link #returnObject returnObject} * before they can be {@link #borrowObject borrowed}. * * @param max cap on the number of "sleeping" instances in the pool * @see #StackKeyedObjectPool(KeyedPoolableObjectFactory, int) * @see #setFactory(KeyedPoolableObjectFactory) */ public StackKeyedObjectPool(int max) { this(null,max,DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new pool using no factory. * Clients must first set the {@link #setFactory factory} or * may populate the pool using {@link #returnObject returnObject} * before they can be {@link #borrowObject borrowed}. * * @param max cap on the number of "sleeping" instances in the pool * @param init initial size of the pool (this specifies the size of the container, * it does not cause the pool to be pre-populated.) * @see #StackKeyedObjectPool(KeyedPoolableObjectFactory, int, int) * @see #setFactory(KeyedPoolableObjectFactory) */ public StackKeyedObjectPool(int max, int init) { this(null,max,init); } /** * Create a new SimpleKeyedObjectPool using * the specified factory to create new instances. * * @param factory the {@link KeyedPoolableObjectFactory} used to populate the pool */ public StackKeyedObjectPool(KeyedPoolableObjectFactory factory) { this(factory,DEFAULT_MAX_SLEEPING); } /** * Create a new SimpleKeyedObjectPool using * the specified factory to create new instances. * capping the number of "sleeping" instances to max * * @param factory the {@link KeyedPoolableObjectFactory} used to populate the pool * @param max cap on the number of "sleeping" instances in the pool */ public StackKeyedObjectPool(KeyedPoolableObjectFactory factory, int max) { this(factory,max,DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new SimpleKeyedObjectPool using * the specified factory to create new instances. * capping the number of "sleeping" instances to max, * and initially allocating a container capable of containing * at least init instances. * * @param factory the {@link KeyedPoolableObjectFactory} used to populate the pool * @param max cap on the number of "sleeping" instances in the pool * @param init initial size of the pool (this specifies the size of the container, * it does not cause the pool to be pre-populated.) */ public StackKeyedObjectPool(KeyedPoolableObjectFactory factory, int max, int init) { _factory = factory; _maxSleeping = (max < 0 ? DEFAULT_MAX_SLEEPING : max); _initSleepingCapacity = (init < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : init); _pools = new HashMap>(); _activeCount = new HashMap(); } /** * Borrows an object with the given key. If there are no idle instances under the * given key, a new one is created. * * @param key the pool key * @return keyed poolable object instance */ @Override public synchronized V borrowObject(K key) throws Exception { assertOpen(); Stack stack = (_pools.get(key)); if(null == stack) { stack = new Stack(); stack.ensureCapacity( _initSleepingCapacity > _maxSleeping ? _maxSleeping : _initSleepingCapacity); _pools.put(key,stack); } V obj = null; do { boolean newlyMade = false; if (!stack.empty()) { obj = stack.pop(); _totIdle--; } else { if(null == _factory) { throw new NoSuchElementException("pools without a factory cannot create new objects as needed."); } else { obj = _factory.makeObject(key); newlyMade = true; } } if (null != _factory && null != obj) { try { _factory.activateObject(key, obj); if (!_factory.validateObject(key, obj)) { throw new Exception("ValidateObject failed"); } } catch (Throwable t) { PoolUtils.checkRethrow(t); try { _factory.destroyObject(key,obj); } catch (Throwable t2) { PoolUtils.checkRethrow(t2); // swallowed } finally { obj = null; } if (newlyMade) { throw new NoSuchElementException( "Could not create a validated object, cause: " + t.getMessage()); } } } } while (obj == null); incrementActiveCount(key); return obj; } /** * Returns obj to the pool under key. If adding the * returning instance to the pool results in {@link #_maxSleeping maxSleeping} * exceeded for the given key, the oldest instance in the idle object pool * is destroyed to make room for the returning instance. * * @param key the pool key * @param obj returning instance */ @Override public synchronized void returnObject(K key, V obj) throws Exception { decrementActiveCount(key); if (null != _factory) { if (_factory.validateObject(key, obj)) { try { _factory.passivateObject(key, obj); } catch (Exception ex) { _factory.destroyObject(key, obj); return; } } else { return; } } if (isClosed()) { if (null != _factory) { try { _factory.destroyObject(key, obj); } catch (Exception e) { // swallowed } } return; } Stack stack = _pools.get(key); if(null == stack) { stack = new Stack(); stack.ensureCapacity( _initSleepingCapacity > _maxSleeping ? _maxSleeping : _initSleepingCapacity); _pools.put(key,stack); } final int stackSize = stack.size(); if (stackSize >= _maxSleeping) { final V staleObj; if (stackSize > 0) { staleObj = stack.remove(0); _totIdle--; } else { staleObj = obj; } if(null != _factory) { try { _factory.destroyObject(key, staleObj); } catch (Exception e) { // swallowed } } } stack.push(obj); _totIdle++; } /** * {@inheritDoc} */ @Override public synchronized void invalidateObject(K key, V obj) throws Exception { decrementActiveCount(key); if(null != _factory) { _factory.destroyObject(key,obj); } notifyAll(); // _totalActive has changed } /** * Create an object using the {@link KeyedPoolableObjectFactory#makeObject factory}, * passivate it, and then placed in the idle object pool. * addObject is useful for "pre-loading" a pool with idle objects. * * @param key the key a new instance should be added to * @throws Exception when {@link KeyedPoolableObjectFactory#makeObject} fails. * @throws IllegalStateException when no {@link #setFactory factory} has been set or after {@link #close} has been called on this pool. */ @Override public synchronized void addObject(K key) throws Exception { assertOpen(); if (_factory == null) { throw new IllegalStateException("Cannot add objects without a factory."); } V obj = _factory.makeObject(key); try { if (!_factory.validateObject(key, obj)) { return; } } catch (Exception e) { try { _factory.destroyObject(key, obj); } catch (Exception e2) { // swallowed } return; } _factory.passivateObject(key, obj); Stack stack = _pools.get(key); if(null == stack) { stack = new Stack(); stack.ensureCapacity( _initSleepingCapacity > _maxSleeping ? _maxSleeping : _initSleepingCapacity); _pools.put(key,stack); } final int stackSize = stack.size(); if (stackSize >= _maxSleeping) { final V staleObj; if (stackSize > 0) { staleObj = stack.remove(0); _totIdle--; } else { staleObj = obj; } try { _factory.destroyObject(key, staleObj); } catch (Exception e) { // Don't swallow destroying the newly created object. if (obj == staleObj) { throw e; } } } else { stack.push(obj); _totIdle++; } } /** * Returns the total number of instances currently idle in this pool. * * @return the total number of instances currently idle in this pool */ @Override public synchronized int getNumIdle() { return _totIdle; } /** * Returns the total number of instances current borrowed from this pool but not yet returned. * * @return the total number of instances currently borrowed from this pool */ @Override public synchronized int getNumActive() { return _totActive; } /** * Returns the number of instances currently borrowed from but not yet returned * to the pool corresponding to the given key. * * @param key the key to query * @return the number of instances corresponding to the given key currently borrowed in this pool */ @Override public synchronized int getNumActive(K key) { return getActiveCount(key); } /** * Returns the number of instances corresponding to the given key currently idle in this pool. * * @param key the key to query * @return the number of instances corresponding to the given key currently idle in this pool */ @Override public synchronized int getNumIdle(K key) { try { return(_pools.get(key)).size(); } catch(Exception e) { return 0; } } /** * Clears the pool, removing all pooled instances. */ @Override public synchronized void clear() { Iterator it = _pools.keySet().iterator(); while(it.hasNext()) { K key = it.next(); Stack stack = _pools.get(key); destroyStack(key,stack); } _totIdle = 0; _pools.clear(); _activeCount.clear(); } /** * Clears the specified pool, removing all pooled instances corresponding to the given key. * * @param key the key to clear */ @Override public synchronized void clear(K key) { Stack stack = _pools.remove(key); destroyStack(key,stack); } /** * Destroys all instances in the stack and clears the stack. * * @param key key passed to factory when destroying instances * @param stack stack to destroy */ private synchronized void destroyStack(K key, Stack stack) { if(null == stack) { return; } else { if(null != _factory) { Iterator it = stack.iterator(); while(it.hasNext()) { try { _factory.destroyObject(key,it.next()); } catch(Exception e) { // ignore error, keep destroying the rest } } } _totIdle -= stack.size(); _activeCount.remove(key); stack.clear(); } } /** * Returns a string representation of this StackKeyedObjectPool, including * the number of pools, the keys and the size of each keyed pool. * * @return Keys and pool sizes */ @Override public synchronized String toString() { StringBuffer buf = new StringBuffer(); buf.append(getClass().getName()); buf.append(" contains ").append(_pools.size()).append(" distinct pools: "); Iterator it = _pools.keySet().iterator(); while(it.hasNext()) { K key = it.next(); buf.append(" |").append(key).append("|="); Stack s = _pools.get(key); buf.append(s.size()); } return buf.toString(); } /** * Close this pool, and free any resources associated with it. *

* Calling {@link #addObject addObject} or {@link #borrowObject borrowObject} after invoking * this method on a pool will cause them to throw an {@link IllegalStateException}. *

* * @throws Exception deprecated: implementations should silently fail if not all resources can be freed. */ @Override public void close() throws Exception { super.close(); clear(); } /** * Sets the {@link KeyedPoolableObjectFactory factory} the pool uses * to create new instances. * Trying to change the factory after a pool has been used will frequently * throw an {@link UnsupportedOperationException}. * * @param factory the {@link KeyedPoolableObjectFactory} used to manage object instances * @throws IllegalStateException when the factory cannot be set at this time * @deprecated to be removed in pool 2.0 */ @Deprecated @Override public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException { if(0 < getNumActive()) { throw new IllegalStateException("Objects are already active"); } else { clear(); _factory = factory; } } /** * @return the {@link KeyedPoolableObjectFactory} used by this pool to manage object instances. * @since 1.5.5 */ public synchronized KeyedPoolableObjectFactory getFactory() { return _factory; } /** * Returns the active instance count for the given key. * * @param key pool key * @return active count */ private int getActiveCount(K key) { try { return _activeCount.get(key).intValue(); } catch(NoSuchElementException e) { return 0; } catch(NullPointerException e) { return 0; } } /** * Increment the active count for the given key. Also * increments the total active count. * * @param key pool key */ private void incrementActiveCount(K key) { _totActive++; Integer old = _activeCount.get(key); if(null == old) { _activeCount.put(key,new Integer(1)); } else { _activeCount.put(key,new Integer(old.intValue() + 1)); } } /** * Decrements the active count for the given key. * Also decrements the total active count. * * @param key pool key */ private void decrementActiveCount(K key) { _totActive--; Integer active = _activeCount.get(key); if(null == active) { // do nothing, either null or zero is OK } else if(active.intValue() <= 1) { _activeCount.remove(key); } else { _activeCount.put(key, new Integer(active.intValue() - 1)); } } /** * @return map of keyed pools * @since 1.5.5 */ public Map> getPools() { return _pools; } /** * @return the cap on the number of "sleeping" instances in each pool. * @since 1.5.5 */ public int getMaxSleeping() { return _maxSleeping; } /** * @return the initial capacity of each pool. * @since 1.5.5 */ public int getInitSleepingCapacity() { return _initSleepingCapacity; } /** * @return the _totActive */ public int getTotActive() { return _totActive; } /** * @return the _totIdle */ public int getTotIdle() { return _totIdle; } /** * @return the _activeCount * @since 1.5.5 */ public Map getActiveCount() { return _activeCount; } /** The default cap on the number of "sleeping" instances in the pool. */ protected static final int DEFAULT_MAX_SLEEPING = 8; /** * The default initial size of the pool * (this specifies the size of the container, it does not * cause the pool to be pre-populated.) */ protected static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4; /** * My named-set of pools. * @deprecated to be removed in pool 2.0. Use {@link #getPools()} */ @Deprecated protected HashMap> _pools = null; /** * My {@link KeyedPoolableObjectFactory}. * @deprecated to be removed in pool 2.0. Use {@link #getFactory()} */ @Deprecated protected KeyedPoolableObjectFactory _factory = null; /** * The cap on the number of "sleeping" instances in each pool. * @deprecated to be removed in pool 2.0. Use {@link #getMaxSleeping()} */ @Deprecated protected int _maxSleeping = DEFAULT_MAX_SLEEPING; /** * The initial capacity of each pool. * @deprecated to be removed in pool 2.0. Use {@link #getInitSleepingCapacity()}. */ @Deprecated protected int _initSleepingCapacity = DEFAULT_INIT_SLEEPING_CAPACITY; /** * Total number of object borrowed and not yet returned for all pools. * @deprecated to be removed in pool 2.0. Use {@link #getTotActive()}. */ @Deprecated protected int _totActive = 0; /** * Total number of objects "sleeping" for all pools * @deprecated to be removed in pool 2.0. Use {@link #getTotIdle()}. */ @Deprecated protected int _totIdle = 0; /** * Number of active objects borrowed and not yet returned by pool * @deprecated to be removed in pool 2.0. Use {@link #getActiveCount()}. */ @Deprecated protected HashMap _activeCount = null; } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/StackKeyedObjectPoolFactory.java100644 0 0 14331 11701070262 27244 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import org.apache.commons.pool.KeyedObjectPool; import org.apache.commons.pool.KeyedObjectPoolFactory; import org.apache.commons.pool.KeyedPoolableObjectFactory; /** * A factory for creating {@link StackKeyedObjectPool} instances. * * @param the type of keys in this pool * @param the type of objects held in this pool * * @see StackKeyedObjectPool * @see KeyedObjectPoolFactory * * @author Rodney Waldhoff * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public class StackKeyedObjectPoolFactory implements KeyedObjectPoolFactory { /** * Create a new StackKeyedObjectPoolFactory. * * @see StackKeyedObjectPool#StackKeyedObjectPool() */ public StackKeyedObjectPoolFactory() { this(null,StackKeyedObjectPool.DEFAULT_MAX_SLEEPING,StackKeyedObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackKeyedObjectPoolFactory. * * @param maxSleeping cap on the number of "sleeping" instances in the pool. * @see StackKeyedObjectPool#StackKeyedObjectPool(int) */ public StackKeyedObjectPoolFactory(int maxSleeping) { this(null,maxSleeping,StackKeyedObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackKeyedObjectPoolFactory. * * @param maxSleeping cap on the number of "sleeping" instances in the pool. * @param initialCapacity initial size of the pool (this specifies the size of the container, * it does not cause the pool to be pre-populated.) * @see StackKeyedObjectPool#StackKeyedObjectPool(int, int) */ public StackKeyedObjectPoolFactory(int maxSleeping, int initialCapacity) { this(null,maxSleeping,initialCapacity); } /** * Create a new StackKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory used by created pools. * @see StackKeyedObjectPool#StackKeyedObjectPool(KeyedPoolableObjectFactory) */ public StackKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory) { this(factory,StackKeyedObjectPool.DEFAULT_MAX_SLEEPING,StackKeyedObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory used by created pools. * @param maxSleeping cap on the number of "sleeping" instances in the pool. * @see StackKeyedObjectPool#StackKeyedObjectPool(KeyedPoolableObjectFactory, int) */ public StackKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxSleeping) { this(factory,maxSleeping,StackKeyedObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackKeyedObjectPoolFactory. * * @param factory the KeyedPoolableObjectFactory used by created pools. * @param maxSleeping cap on the number of "sleeping" instances in the pool. * @param initialCapacity initial size of the pool (this specifies the size of the container, * it does not cause the pool to be pre-populated.) * @see StackKeyedObjectPool#StackKeyedObjectPool(KeyedPoolableObjectFactory, int, int) */ public StackKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxSleeping, int initialCapacity) { _factory = factory; _maxSleeping = maxSleeping; _initCapacity = initialCapacity; } /** * Create a StackKeyedObjectPool with current property settings. * * @return a new StackKeyedObjectPool with the configured factory, maxSleeping and initialCapacity */ public KeyedObjectPool createPool() { return new StackKeyedObjectPool(_factory,_maxSleeping,_initCapacity); } /** * KeyedPoolableObjectFactory used by StackKeyedObjectPools created by this factory * @deprecated to be removed in pool 2.0 */ @Deprecated protected KeyedPoolableObjectFactory _factory = null; /** * Maximum number of idle instances in each keyed pool for StackKeyedObjectPools created by this factory * @deprecated to be removed in pool 2.0 */ @Deprecated protected int _maxSleeping = StackKeyedObjectPool.DEFAULT_MAX_SLEEPING; /** * Initial capacity of StackKeyedObjectPools created by this factory. * @deprecated to be removed in pool 2.0 */ @Deprecated protected int _initCapacity = StackKeyedObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY; /** * Returns the KeyedPoolableObjectFactory used by StackKeyedObjectPools created by this factory * * @return factory setting for created pools * @since 1.5.5 */ public KeyedPoolableObjectFactory getFactory() { return _factory; } /** * Returns the maximum number of idle instances in each keyed pool for StackKeyedObjectPools created by this factory * * @return maxSleeping setting for created pools * @since 1.5.5 */ public int getMaxSleeping() { return _maxSleeping; } /** * Returns the initial capacity of StackKeyedObjectPools created by this factory. * * @return initial capacity setting for created pools * @since 1.5.5 */ public int getInitialCapacity() { return _initCapacity; } } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/StackObjectPool.java100644 0 0 46014 11701070262 24735 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Stack; import org.apache.commons.pool.BaseObjectPool; import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.PoolUtils; import org.apache.commons.pool.PoolableObjectFactory; /** * A simple, {@link java.util.Stack Stack}-based {@link ObjectPool} implementation. *

* Given a {@link PoolableObjectFactory}, this class will maintain * a simple pool of instances. A finite number of "sleeping" * or idle instances is enforced, but when the pool is * empty, new instances are created to support the new load. * Hence this class places no limit on the number of "active" * instances created by the pool, but is quite useful for * re-using Objects without introducing * artificial limits. * * @param the type of objects held in this pool * * @author Rodney Waldhoff * @author Dirk Verbeeck * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public class StackObjectPool extends BaseObjectPool implements ObjectPool { /** * Create a new pool using no factory. Clients must first * {@link #setFactory(PoolableObjectFactory) set the factory} or * else this pool will not behave correctly. Clients may first populate the pool * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed} * but this usage is discouraged. * * @see #StackObjectPool(PoolableObjectFactory) * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory)} */ @Deprecated public StackObjectPool() { this(null,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new pool using no factory. * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory} or * else this pool will not behave correctly. Clients may first populate the pool * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed} * but this usage is discouraged. * * @param maxIdle cap on the number of "sleeping" instances in the pool * @see #StackObjectPool(PoolableObjectFactory, int) * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory, int)} */ @Deprecated public StackObjectPool(int maxIdle) { this(null,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new pool using no factory. * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory} or * else this pool will not behave correctly. Clients may first populate the pool * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed} * but this usage is discouraged. * * @param maxIdle cap on the number of "sleeping" instances in the pool * @param initIdleCapacity initial size of the pool (this specifies the size of the container, * it does not cause the pool to be pre-populated.) * @see #StackObjectPool(PoolableObjectFactory, int, int) * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory, int, int)} */ @Deprecated public StackObjectPool(int maxIdle, int initIdleCapacity) { this(null,maxIdle,initIdleCapacity); } /** * Create a new StackObjectPool using the specified factory to create new instances. * * @param factory the {@link PoolableObjectFactory} used to populate the pool */ public StackObjectPool(PoolableObjectFactory factory) { this(factory,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new SimpleObjectPool using the specified factory to create new instances, * capping the number of "sleeping" instances to maxIdle. * * @param factory the {@link PoolableObjectFactory} used to populate the pool * @param maxIdle cap on the number of "sleeping" instances in the pool */ public StackObjectPool(PoolableObjectFactory factory, int maxIdle) { this(factory,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY); } /** *

Create a new StackObjectPool using the specified factory to create new instances, * capping the number of "sleeping" instances to maxIdle, and initially allocating a container * capable of containing at least initIdleCapacity instances. The pool is not pre-populated. * The initIdleCapacity parameter just determines the initial size of the underlying * container, which can increase beyond this value if maxIdle > initIdleCapacity.

* *

Negative values of maxIdle are ignored (i.e., the pool is created using * {@link #DEFAULT_MAX_SLEEPING}) as are non-positive values for initIdleCapacity. * * @param factory the {@link PoolableObjectFactory} used to populate the pool * @param maxIdle cap on the number of "sleeping" instances in the pool * @param initIdleCapacity initial size of the pool (this specifies the size of the container, * it does not cause the pool to be pre-populated.) */ public StackObjectPool(PoolableObjectFactory factory, int maxIdle, int initIdleCapacity) { _factory = factory; _maxSleeping = (maxIdle < 0 ? DEFAULT_MAX_SLEEPING : maxIdle); int initcapacity = (initIdleCapacity < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : initIdleCapacity); _pool = new Stack(); _pool.ensureCapacity( initcapacity > _maxSleeping ? _maxSleeping : initcapacity); } /** *

Borrows an object from the pool. If there are idle instances available on the stack, * the top element of the stack is popped to activate, validate and return to the client. If there * are no idle instances available, the {@link PoolableObjectFactory#makeObject() makeObject} * method of the pool's {@link PoolableObjectFactory} is invoked to create a new instance.

* *

All instances are {@link PoolableObjectFactory#activateObject(Object) activated} and * {@link PoolableObjectFactory#validateObject(Object) validated} before being returned to the * client. If validation fails or an exception occurs activating or validating an instance * popped from the idle instance stack, the failing instance is * {@link PoolableObjectFactory#destroyObject(Object) destroyed} and the next instance on * the stack is popped, validated and activated. This process continues until either the * stack is empty or an instance passes validation. If the stack is empty on activation or * it does not contain any valid instances, the factory's makeObject method is used * to create a new instance. If a null instance is returned by the factory or the created * instance either raises an exception on activation or fails validation, NoSuchElementException * is thrown. Exceptions thrown by MakeObject are propagated to the caller; but * other than ThreadDeath or VirtualMachineError, exceptions generated by * activation, validation or destroy methods are swallowed silently.

* * @return an instance from the pool */ @Override public synchronized T borrowObject() throws Exception { assertOpen(); T obj = null; boolean newlyCreated = false; while (null == obj) { if (!_pool.empty()) { obj = _pool.pop(); } else { if(null == _factory) { throw new NoSuchElementException(); } else { obj = _factory.makeObject(); newlyCreated = true; if (obj == null) { throw new NoSuchElementException("PoolableObjectFactory.makeObject() returned null."); } } } if (null != _factory && null != obj) { try { _factory.activateObject(obj); if (!_factory.validateObject(obj)) { throw new Exception("ValidateObject failed"); } } catch (Throwable t) { PoolUtils.checkRethrow(t); try { _factory.destroyObject(obj); } catch (Throwable t2) { PoolUtils.checkRethrow(t2); // swallowed } finally { obj = null; } if (newlyCreated) { throw new NoSuchElementException( "Could not create a validated object, cause: " + t.getMessage()); } } } } _numActive++; return obj; } /** *

Returns an instance to the pool, pushing it on top of the idle instance stack after successful * validation and passivation. The returning instance is destroyed if any of the following are true:

    *
  • the pool is closed
  • *
  • {@link PoolableObjectFactory#validateObject(Object) validation} fails
  • *
  • {@link PoolableObjectFactory#passivateObject(Object) passivation} throws an exception
  • *
* If adding a validated, passivated returning instance to the stack would cause * {@link #getMaxSleeping() maxSleeping} to be exceeded, the oldest (bottom) instance on the stack * is destroyed to make room for the returning instance, which is pushed on top of the stack.

* *

Exceptions passivating or destroying instances are silently swallowed. Exceptions validating * instances are propagated to the client.

* * @param obj instance to return to the pool */ @Override public synchronized void returnObject(T obj) throws Exception { boolean success = !isClosed(); if(null != _factory) { if(!_factory.validateObject(obj)) { success = false; } else { try { _factory.passivateObject(obj); } catch(Exception e) { success = false; } } } boolean shouldDestroy = !success; _numActive--; if (success) { T toBeDestroyed = null; if(_pool.size() >= _maxSleeping) { shouldDestroy = true; toBeDestroyed = _pool.remove(0); // remove the stalest object } _pool.push(obj); obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed } notifyAll(); // _numActive has changed if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null try { _factory.destroyObject(obj); } catch(Exception e) { // ignored } } } /** * {@inheritDoc} */ @Override public synchronized void invalidateObject(T obj) throws Exception { _numActive--; if (null != _factory) { _factory.destroyObject(obj); } notifyAll(); // _numActive has changed } /** * Return the number of instances * currently idle in this pool. * * @return the number of instances currently idle in this pool */ @Override public synchronized int getNumIdle() { return _pool.size(); } /** * Return the number of instances currently borrowed from this pool. * * @return the number of instances currently borrowed from this pool */ @Override public synchronized int getNumActive() { return _numActive; } /** * Clears any objects sitting idle in the pool. Silently swallows any * exceptions thrown by {@link PoolableObjectFactory#destroyObject(Object)}. */ @Override public synchronized void clear() { if(null != _factory) { Iterator it = _pool.iterator(); while(it.hasNext()) { try { _factory.destroyObject(it.next()); } catch(Exception e) { // ignore error, keep destroying the rest } } } _pool.clear(); } /** *

Close this pool, and free any resources associated with it. Invokes * {@link #clear()} to destroy and remove instances in the pool.

* *

Calling {@link #addObject} or {@link #borrowObject} after invoking * this method on a pool will cause them to throw an * {@link IllegalStateException}.

* * @throws Exception never - exceptions clearing the pool are swallowed */ @Override public void close() throws Exception { super.close(); clear(); } /** *

Create an object, and place it on top of the stack. * This method is useful for "pre-loading" a pool with idle objects.

* *

Before being added to the pool, the newly created instance is * {@link PoolableObjectFactory#validateObject(Object) validated} and * {@link PoolableObjectFactory#passivateObject(Object) passivated}. If validation * fails, the new instance is {@link PoolableObjectFactory#destroyObject(Object) destroyed}. * Exceptions generated by the factory makeObject or passivate are * propagated to the caller. Exceptions destroying instances are silently swallowed.

* *

If a new instance is created and successfully validated and passivated and adding this * instance to the pool causes {@link #getMaxSleeping() maxSleeping} to be exceeded, the oldest * (bottom) instance in the pool is destroyed to make room for the newly created instance, which * is pushed on top of the stack. * * @throws Exception when the {@link #getFactory() factory} has a problem creating or passivating an object. */ @Override public synchronized void addObject() throws Exception { assertOpen(); if (_factory == null) { throw new IllegalStateException("Cannot add objects without a factory."); } T obj = _factory.makeObject(); boolean success = true; if(!_factory.validateObject(obj)) { success = false; } else { _factory.passivateObject(obj); } boolean shouldDestroy = !success; if (success) { T toBeDestroyed = null; if(_pool.size() >= _maxSleeping) { shouldDestroy = true; toBeDestroyed = _pool.remove(0); // remove the stalest object } _pool.push(obj); obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed } notifyAll(); // _numIdle has changed if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null try { _factory.destroyObject(obj); } catch(Exception e) { // ignored } } } /** * Sets the {@link PoolableObjectFactory factory} this pool uses * to create new instances. Trying to change * the factory while there are borrowed objects will * throw an {@link IllegalStateException}. * * @param factory the {@link PoolableObjectFactory} used to create new instances. * @throws IllegalStateException when the factory cannot be set at this time * @deprecated to be removed in pool 2.0 */ @Deprecated @Override public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException { assertOpen(); if(0 < getNumActive()) { throw new IllegalStateException("Objects are already active"); } else { clear(); _factory = factory; } } /** * The cap on the number of "sleeping" instances in the pool. */ protected static final int DEFAULT_MAX_SLEEPING = 8; /** * The default initial size of the pool * (this specifies the size of the container, it does not * cause the pool to be pre-populated.) */ protected static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4; /** * My pool. * @deprecated to be made private in pool 2.0 */ @Deprecated protected Stack _pool = null; /** * My {@link PoolableObjectFactory}. * @deprecated to be made private in pool 2.0 - use {@link #getFactory()} */ @Deprecated protected PoolableObjectFactory _factory = null; /** * The cap on the number of "sleeping" instances in the pool. * @deprecated to be made private in pool 2.0 - use {@link #getMaxSleeping()} */ @Deprecated protected int _maxSleeping = DEFAULT_MAX_SLEEPING; /** * Number of objects borrowed but not yet returned to the pool. * @deprecated to be made private in pool 2.0 - use {@link #getNumActive()} */ @Deprecated protected int _numActive = 0; /** * Returns the {@link PoolableObjectFactory} used by this pool to create and manage object instances. * * @return the factory * @since 1.5.5 */ public synchronized PoolableObjectFactory getFactory() { return _factory; } /** * Returns the maximum number of idle instances in the pool. * * @return maxSleeping * @since 1.5.5 */ public int getMaxSleeping() { return _maxSleeping; } } commons-pool-1.6-src/src/java/org/apache/commons/pool/impl/StackObjectPoolFactory.java100644 0 0 13556 11701070262 26272 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.ObjectPoolFactory; import org.apache.commons.pool.PoolableObjectFactory; /** * A factory for creating {@link StackObjectPool} instances. * * @param the type of objects held in this pool * * @see StackObjectPool * @see StackKeyedObjectPoolFactory * * @author Rodney Waldhoff * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public class StackObjectPoolFactory implements ObjectPoolFactory { /** * Create a new StackObjectPoolFactory. * * @see StackObjectPool#StackObjectPool() * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPoolFactory(PoolableObjectFactory)} */ @Deprecated public StackObjectPoolFactory() { this(null,StackObjectPool.DEFAULT_MAX_SLEEPING,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackObjectPoolFactory. * * @param maxIdle cap on the number of "sleeping" instances in the pool. * @see StackObjectPool#StackObjectPool(int) * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPoolFactory(PoolableObjectFactory, int)} */ @Deprecated public StackObjectPoolFactory(int maxIdle) { this(null,maxIdle,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackObjectPoolFactory. * * @param maxIdle cap on the number of "sleeping" instances in the pool. * @param initIdleCapacity - initial size of the pool (this specifies the size of the container, * it does not cause the pool to be pre-populated.) * @see StackObjectPool#StackObjectPool(int, int) * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPoolFactory(PoolableObjectFactory, int, int)} */ @Deprecated public StackObjectPoolFactory(int maxIdle, int initIdleCapacity) { this(null,maxIdle,initIdleCapacity); } /** * Create a new StackObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @see StackObjectPool#StackObjectPool(PoolableObjectFactory) */ public StackObjectPoolFactory(PoolableObjectFactory factory) { this(factory,StackObjectPool.DEFAULT_MAX_SLEEPING,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxIdle cap on the number of "sleeping" instances in the pool. */ public StackObjectPoolFactory(PoolableObjectFactory factory, int maxIdle) { this(factory,maxIdle,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY); } /** * Create a new StackObjectPoolFactory. * * @param factory the PoolableObjectFactory used by created pools. * @param maxIdle cap on the number of "sleeping" instances in the pool. * @param initIdleCapacity - initial size of the pool (this specifies the size of the container, * it does not cause the pool to be pre-populated.) */ public StackObjectPoolFactory(PoolableObjectFactory factory, int maxIdle, int initIdleCapacity) { _factory = factory; _maxSleeping = maxIdle; _initCapacity = initIdleCapacity; } /** * Create a StackObjectPool. * * @return a new StackObjectPool with the configured factory, maxIdle and initial capacity settings */ public ObjectPool createPool() { return new StackObjectPool(_factory,_maxSleeping,_initCapacity); } /** * The PoolableObjectFactory used by created pools. * @deprecated to be made private in pool 2.0 */ @Deprecated protected PoolableObjectFactory _factory = null; /** * The maximum number of idle instances in created pools. * @deprecated to be made private in pool 2.0 */ @Deprecated protected int _maxSleeping = StackObjectPool.DEFAULT_MAX_SLEEPING; /** * The initial size of created pools. * @deprecated to be made private in pool 2.0 */ @Deprecated protected int _initCapacity = StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY; /** * Returns the factory used by created pools. * * @return the PoolableObjectFactory used by created pools * @since 1.5.5 */ public PoolableObjectFactory getFactory() { return _factory; } /** * Returns the maxIdle setting for created pools. * * @return the maximum number of idle instances in created pools * @since 1.5.5 */ public int getMaxSleeping() { return _maxSleeping; } /** * Returns the initial capacity of created pools. * * @return size of created containers (created pools are not pre-populated) * @since 1.5.5 */ public int getInitCapacity() { return _initCapacity; } } commons-pool-1.6-src/src/java/org/apache/commons/pool/KeyedObjectPool.java100644 0 0 25555 11701070263 24000 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import java.util.NoSuchElementException; /** * A "keyed" pooling interface. *

* A keyed pool pools instances of multiple types. Each * type may be accessed using an arbitrary key. *

*

* Example of use: *

 Object obj = null;
 * Object key = "Key";
 *
 * try {
 *     obj = pool.borrowObject(key);
 *     //...use the object...
 * } catch(Exception e) {
 *     // invalidate the object
 *     pool.invalidateObject(key, obj);
 *     // do not return the object to the pool twice
 *     obj = null;
 * } finally {
 *     // make sure the object is returned to the pool
 *     if(null != obj) {
 *         pool.returnObject(key, obj);
 *     }
 * }
*

*

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

* *

See {@link BaseKeyedObjectPool} for a simple base implementation.

* * @param the type of keys in this pool * @param the type of objects held in this pool * * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @see KeyedPoolableObjectFactory * @see KeyedObjectPoolFactory * @see ObjectPool * @see BaseKeyedObjectPool * @since Pool 1.0 */ public interface KeyedObjectPool { /** * Obtains an instance from this pool for the specified key. *

* Instances returned from this method will have been either newly created with * {@link KeyedPoolableObjectFactory#makeObject makeObject} or will be a previously idle object and * have been activated with {@link KeyedPoolableObjectFactory#activateObject activateObject} and * then validated with {@link KeyedPoolableObjectFactory#validateObject validateObject}. *

* By contract, clients must return the borrowed object using * {@link #returnObject returnObject}, {@link #invalidateObject invalidateObject}, or a related method * as defined in an implementation or sub-interface, * using a key that is {@link Object#equals equivalent} to the one used to * borrow the instance in the first place. *

* The behaviour of this method when the pool has been exhausted * is not strictly specified (although it may be specified by implementations). * Older versions of this method would return null to indicate exhaustion, * newer versions are encouraged to throw a {@link NoSuchElementException}. * * @param key the key used to obtain the object * @return an instance from this pool. * @throws IllegalStateException after {@link #close close} has been called on this pool * @throws Exception when {@link KeyedPoolableObjectFactory#makeObject makeObject} throws an exception * @throws NoSuchElementException when the pool is exhausted and cannot or will not return another instance */ V borrowObject(K key) throws Exception, NoSuchElementException, IllegalStateException; /** * Return an instance to the pool. * By contract, obj must have been obtained * using {@link #borrowObject borrowObject} * or a related method as defined in an implementation * or sub-interface * using a key that is equivalent to the one used to * borrow the instance in the first place. * * @param key the key used to obtain the object * @param obj a {@link #borrowObject borrowed} instance to be returned. * @throws Exception */ void returnObject(K key, V obj) throws Exception; /** *

Invalidates an object from the pool.

* *

By contract, obj must have been obtained * using {@link #borrowObject borrowObject} or a related method as defined * in an implementation or sub-interface using a key that is * equivalent to the one used to borrow the Object in the first place.

* *

This method should be used when an object that has been borrowed * is determined (due to an exception or other problem) to be invalid.

* * @param key the key used to obtain the object * @param obj a {@link #borrowObject borrowed} instance to be returned. * @throws Exception */ void invalidateObject(K key, V obj) throws Exception; /** * Create an object using the {@link KeyedPoolableObjectFactory factory} or other * implementation dependent mechanism, passivate it, and then place it in the idle object pool. * addObject is useful for "pre-loading" a pool with idle objects * (Optional operation). * * @param key the key a new instance should be added to * @throws Exception when {@link KeyedPoolableObjectFactory#makeObject} fails. * @throws IllegalStateException after {@link #close} has been called on this pool. * @throws UnsupportedOperationException when this pool cannot add new idle objects. */ void addObject(K key) throws Exception, IllegalStateException, UnsupportedOperationException; /** * Returns the number of instances * corresponding to the given key * currently idle in this pool (optional operation). * Returns a negative value if this information is not available. * * @param key the key to query * @return the number of instances corresponding to the given key currently idle in this pool or a negative value if unsupported * @throws UnsupportedOperationException deprecated: when this implementation doesn't support the operation */ int getNumIdle(K key) throws UnsupportedOperationException; /** * Returns the number of instances * currently borrowed from but not yet returned * to the pool corresponding to the * given key (optional operation). * Returns a negative value if this information is not available. * * @param key the key to query * @return the number of instances corresponding to the given key currently borrowed in this pool or a negative value if unsupported * @throws UnsupportedOperationException deprecated: when this implementation doesn't support the operation */ int getNumActive(K key) throws UnsupportedOperationException; /** * Returns the total number of instances * currently idle in this pool (optional operation). * Returns a negative value if this information is not available. * * @return the total number of instances currently idle in this pool or a negative value if unsupported * @throws UnsupportedOperationException deprecated: when this implementation doesn't support the operation */ int getNumIdle() throws UnsupportedOperationException; /** * Returns the total number of instances * current borrowed from this pool but not * yet returned (optional operation). * Returns a negative value if this information is not available. * * @return the total number of instances currently borrowed from this pool or a negative value if unsupported * @throws UnsupportedOperationException deprecated: when this implementation doesn't support the operation */ int getNumActive() throws UnsupportedOperationException; /** * Clears the pool, removing all pooled instances (optional operation). * Throws {@link UnsupportedOperationException} if the pool cannot be cleared. * * @throws UnsupportedOperationException when this implementation doesn't support the operation */ void clear() throws Exception, UnsupportedOperationException; /** * Clears the specified pool, removing all * pooled instances corresponding to * the given key (optional operation). * Throws {@link UnsupportedOperationException} if the pool cannot be cleared. * * @param key the key to clear * @throws UnsupportedOperationException when this implementation doesn't support the operation */ void clear(K key) throws Exception, UnsupportedOperationException; /** * Close this pool, and free any resources associated with it. *

* Calling {@link #addObject addObject} or {@link #borrowObject borrowObject} after invoking * this method on a pool will cause them to throw an {@link IllegalStateException}. *

* * @throws Exception */ void close() throws Exception; /** * Sets the {@link KeyedPoolableObjectFactory factory} the pool uses * to create new instances (optional operation). * Trying to change the factory after a pool has been used will frequently * throw an {@link UnsupportedOperationException}. It is up to the pool * implementation to determine when it is acceptable to call this method. * * @param factory the {@link KeyedPoolableObjectFactory} used to create new instances. * @throws IllegalStateException when the factory cannot be set at this time * @throws UnsupportedOperationException when this implementation doesn't support the operation * @deprecated to be removed in pool 2.0 */ @Deprecated void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException; } commons-pool-1.6-src/src/java/org/apache/commons/pool/KeyedObjectPoolFactory.java100644 0 0 2750 11701070263 25300 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * A factory for creating {@link KeyedObjectPool}s. * * @param the type of keys in this pool * @param the type of objects held in this pool * * @see KeyedObjectPool * * @author Rodney Waldhoff * @version $Revision: 1222388 $ $Date: 2011-12-22 13:28:27 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public interface KeyedObjectPoolFactory { /** * Create a new {@link KeyedObjectPool}. * @return a new {@link KeyedObjectPool} * @throws IllegalStateException when this pool factory is not configured properly */ KeyedObjectPool createPool() throws IllegalStateException; } commons-pool-1.6-src/src/java/org/apache/commons/pool/KeyedPoolableObjectFactory.java100644 0 0 13071 11701070263 26142 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * An interface defining life-cycle methods for * instances to be served by a {@link KeyedObjectPool}. *

* By contract, when an {@link KeyedObjectPool} * delegates to a {@link KeyedPoolableObjectFactory}, *

    *
  1. * {@link #makeObject makeObject} * is called whenever a new instance is needed. *
  2. *
  3. * {@link #activateObject activateObject} * is invoked on every instance that has been * {@link #passivateObject passivated} before it is * {@link KeyedObjectPool#borrowObject borrowed} from the pool. *
  4. *
  5. * {@link #validateObject validateObject} * is invoked on {@link #activateObject activated} instances to make sure * they can be {@link KeyedObjectPool#borrowObject borrowed} from the pool. * validateObject may also be used to test an * instance being {@link KeyedObjectPool#returnObject returned} to the pool * before it is {@link #passivateObject passivated}. It will only be invoked * on an activated instance. *
  6. *
  7. * {@link #passivateObject passivateObject} * is invoked on every instance when it is returned to the pool. *
  8. *
  9. * {@link #destroyObject destroyObject} * is invoked on every instance when it is being "dropped" from the * pool (whether due to the response from validateObject, * or for reasons specific to the pool implementation.) There is no * guarantee that the instance being destroyed will * be considered active, passive or in a generally consistent state. *
  10. *
*

*

* {@link KeyedPoolableObjectFactory} must be thread-safe. The only promise * an {@link KeyedObjectPool} makes is that the same instance of an object will not * be passed to more than one method of a KeyedPoolableObjectFactory * at a time. *

* * @param the type of keys in this pool * @param the type of objects held in this pool * * @see KeyedObjectPool * * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222388 $ $Date: 2011-12-22 13:28:27 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public interface KeyedPoolableObjectFactory { /** * Create an instance that can be served by the pool. * * @param key the key used when constructing the object * @return an instance that can be served by the pool. * @throws Exception if there is a problem creating a new instance, * this will be propagated to the code requesting an object. */ V makeObject(K key) throws Exception; /** * Destroy an instance no longer needed by the pool. *

* It is important for implementations of this method to be aware * that there is no guarantee about what state obj * will be in and the implementation should be prepared to handle * unexpected errors. *

*

* Also, an implementation must take in to consideration that * instances lost to the garbage collector may never be destroyed. *

* * @param key the key used when selecting the instance * @param obj the instance to be destroyed * @throws Exception should be avoided as it may be swallowed by * the pool implementation. * @see #validateObject * @see KeyedObjectPool#invalidateObject */ void destroyObject(K key, V obj) throws Exception; /** * Ensures that the instance is safe to be returned by the pool. * Returns false if obj should be destroyed. * * @param key the key used when selecting the object * @param obj the instance to be validated * @return false if obj is not valid and should * be dropped from the pool, true otherwise. */ boolean validateObject(K key, V obj); /** * Reinitialize an instance to be returned by the pool. * * @param key the key used when selecting the object * @param obj the instance to be activated * @throws Exception if there is a problem activating obj, * this exception may be swallowed by the pool. * @see #destroyObject */ void activateObject(K key, V obj) throws Exception; /** * Uninitialize an instance to be returned to the idle object pool. * * @param key the key used when selecting the object * @param obj the instance to be passivated * @throws Exception if there is a problem passivating obj, * this exception may be swallowed by the pool. * @see #destroyObject */ void passivateObject(K key, V obj) throws Exception; } commons-pool-1.6-src/src/java/org/apache/commons/pool/ObjectPool.java100644 0 0 21271 11701070262 23004 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import java.util.NoSuchElementException; /** * A pooling interface. *

* ObjectPool defines a trivially simple pooling interface. The only * required methods are {@link #borrowObject borrowObject}, {@link #returnObject returnObject} * and {@link #invalidateObject invalidateObject}. *

*

* Example of use: *

 Object obj = null;
 *
 * try {
 *     obj = pool.borrowObject();
 *     try {
 *         //...use the object...
 *     } catch(Exception e) {
 *         // invalidate the object
 *         pool.invalidateObject(obj);
 *         // do not return the object to the pool twice
 *         obj = null;
 *     } finally {
 *         // make sure the object is returned to the pool
 *         if(null != obj) {
 *             pool.returnObject(obj);
 *        }
 *     }
 * } catch(Exception e) {
 *       // failed to borrow an object
 * }
*

* *

See {@link BaseObjectPool} for a simple base implementation.

* * @param the type of objects held in this pool * * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ * @see PoolableObjectFactory * @see ObjectPoolFactory * @see KeyedObjectPool * @see BaseObjectPool * @since Pool 1.0 */ public interface ObjectPool { /** * Obtains an instance from this pool. *

* Instances returned from this method will have been either newly created with * {@link PoolableObjectFactory#makeObject makeObject} or will be a previously idle object and * have been activated with {@link PoolableObjectFactory#activateObject activateObject} and * then validated with {@link PoolableObjectFactory#validateObject validateObject}. *

*

* By contract, clients must return the borrowed instance using * {@link #returnObject returnObject}, {@link #invalidateObject invalidateObject}, or a related method * as defined in an implementation or sub-interface. *

*

* The behaviour of this method when the pool has been exhausted * is not strictly specified (although it may be specified by implementations). * Older versions of this method would return null to indicate exhaustion, * newer versions are encouraged to throw a {@link NoSuchElementException}. *

* * @return an instance from this pool. * @throws IllegalStateException after {@link #close close} has been called on this pool. * @throws Exception when {@link PoolableObjectFactory#makeObject makeObject} throws an exception. * @throws NoSuchElementException when the pool is exhausted and cannot or will not return another instance. */ T borrowObject() throws Exception, NoSuchElementException, IllegalStateException; /** * Return an instance to the pool. * By contract, obj must have been obtained * using {@link #borrowObject() borrowObject} * or a related method as defined in an implementation * or sub-interface. * * @param obj a {@link #borrowObject borrowed} instance to be returned. * @throws Exception */ void returnObject(T obj) throws Exception; /** *

Invalidates an object from the pool.

* *

By contract, obj must have been obtained * using {@link #borrowObject borrowObject} or a related method as defined in * an implementation or sub-interface.

* *

This method should be used when an object that has been borrowed * is determined (due to an exception or other problem) to be invalid.

* * @param obj a {@link #borrowObject borrowed} instance to be disposed. * @throws Exception */ void invalidateObject(T obj) throws Exception; /** * Create an object using the {@link PoolableObjectFactory factory} or other * implementation dependent mechanism, passivate it, and then place it in the idle object pool. * addObject is useful for "pre-loading" a pool with idle objects. * (Optional operation). * * @throws Exception when {@link PoolableObjectFactory#makeObject} fails. * @throws IllegalStateException after {@link #close} has been called on this pool. * @throws UnsupportedOperationException when this pool cannot add new idle objects. */ void addObject() throws Exception, IllegalStateException, UnsupportedOperationException; /** * Return the number of instances * currently idle in this pool (optional operation). * This may be considered an approximation of the number * of objects that can be {@link #borrowObject borrowed} * without creating any new instances. * Returns a negative value if this information is not available. * * @return the number of instances currently idle in this pool or a negative value if unsupported * @throws UnsupportedOperationException deprecated: if this implementation does not support the operation */ int getNumIdle() throws UnsupportedOperationException; /** * Return the number of instances * currently borrowed from this pool * (optional operation). * Returns a negative value if this information is not available. * * @return the number of instances currently borrowed from this pool or a negative value if unsupported * @throws UnsupportedOperationException deprecated: if this implementation does not support the operation */ int getNumActive() throws UnsupportedOperationException; /** * Clears any objects sitting idle in the pool, releasing any * associated resources (optional operation). * Idle objects cleared must be {@link PoolableObjectFactory#destroyObject(Object) destroyed}. * * @throws UnsupportedOperationException if this implementation does not support the operation */ void clear() throws Exception, UnsupportedOperationException; /** * Close this pool, and free any resources associated with it. *

* Calling {@link #addObject} or {@link #borrowObject} after invoking * this method on a pool will cause them to throw an * {@link IllegalStateException}. *

* * @throws Exception deprecated: implementations should silently fail if not all resources can be freed. */ void close() throws Exception; /** * Sets the {@link PoolableObjectFactory factory} this pool uses * to create new instances (optional operation). Trying to change * the factory after a pool has been used will frequently * throw an {@link UnsupportedOperationException}. It is up to the pool * implementation to determine when it is acceptable to call this method. * * @param factory the {@link PoolableObjectFactory} used to create new instances. * @throws IllegalStateException when the factory cannot be set at this time * @throws UnsupportedOperationException if this implementation does not support the operation * @deprecated to be removed in pool 2.0 */ @Deprecated void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException; } commons-pool-1.6-src/src/java/org/apache/commons/pool/ObjectPoolFactory.java100644 0 0 2654 11701070263 24321 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * A factory interface for creating {@link ObjectPool}s. * * @param the type of objects held in this pool * * @see ObjectPool * * @author Rodney Waldhoff * @version $Revision: 1222388 $ $Date: 2011-12-22 13:28:27 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public interface ObjectPoolFactory { /** * Create and return a new {@link ObjectPool}. * @return a new {@link ObjectPool} * @throws IllegalStateException when this pool factory is not configured properly */ ObjectPool createPool() throws IllegalStateException; } commons-pool-1.6-src/src/java/org/apache/commons/pool/overview.html100644 0 0 10536 11701070263 22640 0ustar 0 0 Overview of the org.apache.commons.pool component

Generic Object pooling API with several implementations.

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

The org.apache.commons.pool.impl package contains several pool implementations. {@link org.apache.commons.pool.impl.StackObjectPool StackObjectPool} is useful for supporting reuse of a limited number of instances while allowing new instances to be created as needed to support high demand. {@link org.apache.commons.pool.impl.GenericObjectPool GenericObjectPool} has many configuration options and can support a limited set of objects such as would be useful in a database connection pool. {@link org.apache.commons.pool.impl.SoftReferenceObjectPool SoftReferenceObjectPool} has no limit on the number of objects in the pool, but the garbage collector can remove idle objects from the pool as needed. There are also keyed versions of the first two.

Here is a simple example of pooling HashMap's. First create an {@link org.apache.commons.pool.ObjectPoolFactory ObjectPoolFactory}

    public class HashMapFactory
        extends {@link org.apache.commons.pool.BasePoolableObjectFactory BasePoolableObjectFactory}
    {
        /**
         * Creates an instance that can be returned by the pool.
         * @return an instance that can be returned by the pool.
         */
        public Object makeObject()
            throws Exception
        {
            return new HashMap();
        }

        /**
         * Uninitialize an instance to be returned to the pool.
         * @param obj the instance to be passivated
         */
        public void passivateObject(Object obj)
            throws Exception
        {
            Map map = (Map)obj;
            map.clear();
        }
    }

A class that makes frequent use of a Map could then use a pool as shown below:

    public class Foo
    {
        private {@link org.apache.commons.pool.ObjectPool ObjectPool} pool;
        public Foo()
        {
            {@link org.apache.commons.pool.PoolableObjectFactory PoolableObjectFactory} factory = new HashMapFactory();
            pool = new StackObjectPool(factory, 1000);
        }

        public doSomething()
        {
            ...
            Map map = null;
            try
            {
                map = (Map)pool.borrowObject();
                // use map
                ...
            }
            finally
            {
                if (map != null)
                {
                    pool.returnObject(map);
                }
            }
            ...
        }
    }

The above example shows how one would use an {@link org.apache.commons.pool.ObjectPool ObjectPool}. The other supplied implementations or another special purpose pool would be used similarly.

commons-pool-1.6-src/src/java/org/apache/commons/pool/package.html100644 0 0 5710 11701070263 22343 0ustar 0 0 Package Documentation for org.apache.commons.pool

Object pooling API.

The org.apache.commons.pool package defines a simple interface for a pool of object instances, and a handful of base classes that may be useful when creating pool implementations.

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

The pool package separates the way in which instances are pooled from the way in which they are created, resulting in a pair of interfaces:

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

{@link org.apache.commons.pool.ObjectPoolFactory ObjectPoolFactory} defines a simple factory for ObjectPools, which may be useful for some applications.

The pool package also provides a keyed pool interface, which pools instances of multiple types, accessed according to an arbitrary key. See {@link org.apache.commons.pool.KeyedObjectPool KeyedObjectPool}, {@link org.apache.commons.pool.KeyedPoolableObjectFactory KeyedPoolableObjectFactory}, and {@link org.apache.commons.pool.KeyedObjectPoolFactory KeyedObjectPoolFactory}.

commons-pool-1.6-src/src/java/org/apache/commons/pool/PoolableObjectFactory.java100644 0 0 12345 11701070263 25163 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * An interface defining life-cycle methods for * instances to be served by an {@link ObjectPool}. *

* By contract, when an {@link ObjectPool} * delegates to a {@link PoolableObjectFactory}, *

    *
  1. * {@link #makeObject makeObject} * is called whenever a new instance is needed. *
  2. *
  3. * {@link #activateObject activateObject} * is invoked on every instance that has been * {@link #passivateObject passivated} before it is * {@link ObjectPool#borrowObject borrowed} from the pool. *
  4. *
  5. * {@link #validateObject validateObject} * is invoked on {@link #activateObject activated} instances to make sure * they can be {@link ObjectPool#borrowObject borrowed} from the pool. * validateObject may also be used to test an * instance being {@link ObjectPool#returnObject returned} to the pool * before it is {@link #passivateObject passivated}. It will only be invoked * on an activated instance. *
  6. *
  7. * {@link #passivateObject passivateObject} * is invoked on every instance when it is returned to the pool. *
  8. *
  9. * {@link #destroyObject destroyObject} * is invoked on every instance when it is being "dropped" from the * pool (whether due to the response from validateObject, * or for reasons specific to the pool implementation.) There is no * guarantee that the instance being destroyed will * be considered active, passive or in a generally consistent state. *
  10. *
*

*

* {@link PoolableObjectFactory} must be thread-safe. The only promise * an {@link ObjectPool} makes is that the same instance of an object will not * be passed to more than one method of a PoolableObjectFactory * at a time. *

* * @param the type of objects held in this pool * * @see ObjectPool * * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222388 $ $Date: 2011-12-22 13:28:27 -0500 (Thu, 22 Dec 2011) $ * @since Pool 1.0 */ public interface PoolableObjectFactory { /** * Creates an instance that can be served by the pool. * Instances returned from this method should be in the * same state as if they had been * {@link #activateObject activated}. They will not be * activated before being served by the pool. * * @return an instance that can be served by the pool. * @throws Exception if there is a problem creating a new instance, * this will be propagated to the code requesting an object. */ T makeObject() throws Exception; /** * Destroys an instance no longer needed by the pool. *

* It is important for implementations of this method to be aware * that there is no guarantee about what state obj * will be in and the implementation should be prepared to handle * unexpected errors. *

*

* Also, an implementation must take in to consideration that * instances lost to the garbage collector may never be destroyed. *

* * @param obj the instance to be destroyed * @throws Exception should be avoided as it may be swallowed by * the pool implementation. * @see #validateObject * @see ObjectPool#invalidateObject */ void destroyObject(T obj) throws Exception; /** * Ensures that the instance is safe to be returned by the pool. * Returns false if obj should be destroyed. * * @param obj the instance to be validated * @return false if obj is not valid and should * be dropped from the pool, true otherwise. */ boolean validateObject(T obj); /** * Reinitialize an instance to be returned by the pool. * * @param obj the instance to be activated * @throws Exception if there is a problem activating obj, * this exception may be swallowed by the pool. * @see #destroyObject */ void activateObject(T obj) throws Exception; /** * Uninitialize an instance to be returned to the idle object pool. * * @param obj the instance to be passivated * @throws Exception if there is a problem passivating obj, * this exception may be swallowed by the pool. * @see #destroyObject */ void passivateObject(T obj) throws Exception; } commons-pool-1.6-src/src/java/org/apache/commons/pool/PoolUtils.java100644 0 0 262533 11701070263 22727 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Timer; import java.util.TimerTask; /** * This class consists exclusively of static methods that operate on or return ObjectPool * or KeyedObjectPool related interfaces. * * @author Sandy McArthur * @version $Revision: 1222670 $ $Date: 2011-12-23 08:18:25 -0500 (Fri, 23 Dec 2011) $ * @since Pool 1.3 */ public final class PoolUtils { /** * Timer used to periodically check pools idle object count. * Because a {@link Timer} creates a {@link Thread} this is lazily instantiated. */ private static Timer MIN_IDLE_TIMER; //@GuardedBy("this") /** * PoolUtils instances should NOT be constructed in standard programming. * Instead, the class should be used procedurally: PoolUtils.adapt(aPool);. * This constructor is public to permit tools that require a JavaBean instance to operate. */ public PoolUtils() { } /** * Should the supplied Throwable be re-thrown (eg if it is an instance of * one of the Throwables that should never be swallowed). Used by the pool * error handling for operations that throw exceptions that normally need to * be ignored. * @param t The Throwable to check * @throws ThreadDeath if that is passed in * @throws VirtualMachineError if that is passed in * @since Pool 1.5.5 */ public static void checkRethrow(Throwable t) { if (t instanceof ThreadDeath) { throw (ThreadDeath) t; } if (t instanceof VirtualMachineError) { throw (VirtualMachineError) t; } // All other instances of Throwable will be silently swallowed } /** * Adapt a KeyedPoolableObjectFactory instance to work where a PoolableObjectFactory is * needed. This method is the equivalent of calling * {@link #adapt(KeyedPoolableObjectFactory, Object) PoolUtils.adapt(aKeyedPoolableObjectFactory, new Object())}. * * @param the type of object * @param keyedFactory the {@link KeyedPoolableObjectFactory} to delegate to. * @return a {@link PoolableObjectFactory} that delegates to keyedFactory with an internal key. * @throws IllegalArgumentException when keyedFactory is null. * @see #adapt(KeyedPoolableObjectFactory, Object) * @since Pool 1.3 */ public static PoolableObjectFactory adapt(final KeyedPoolableObjectFactory keyedFactory) throws IllegalArgumentException { return adapt(keyedFactory, new Object()); } /** * Adapt a KeyedPoolableObjectFactory instance to work where a PoolableObjectFactory is * needed using the specified key when delegating. * * @param the type of key * @param the type of object * @param keyedFactory the {@link KeyedPoolableObjectFactory} to delegate to. * @param key the key to use when delegating. * @return a {@link PoolableObjectFactory} that delegates to keyedFactory with the specified key. * @throws IllegalArgumentException when keyedFactory or key is null. * @see #adapt(KeyedPoolableObjectFactory) * @since Pool 1.3 */ public static PoolableObjectFactory adapt(final KeyedPoolableObjectFactory keyedFactory, final K key) throws IllegalArgumentException { return new PoolableObjectFactoryAdaptor(keyedFactory, key); } /** * Adapt a PoolableObjectFactory instance to work where a KeyedPoolableObjectFactory is * needed. The key is ignored. * * @param the type of key * @param the type of object * @param factory the {@link PoolableObjectFactory} to delegate to. * @return a {@link KeyedPoolableObjectFactory} that delegates to factory ignoring the key. * @throws IllegalArgumentException when factory is null. * @since Pool 1.3 */ public static KeyedPoolableObjectFactory adapt(final PoolableObjectFactory factory) throws IllegalArgumentException { return new KeyedPoolableObjectFactoryAdaptor(factory); } /** * Adapt a KeyedObjectPool instance to work where an ObjectPool is needed. This is the * equivalent of calling {@link #adapt(KeyedObjectPool, Object) PoolUtils.adapt(aKeyedObjectPool, new Object())}. * * @param the type of object * @param keyedPool the {@link KeyedObjectPool} to delegate to. * @return an {@link ObjectPool} that delegates to keyedPool with an internal key. * @throws IllegalArgumentException when keyedPool is null. * @see #adapt(KeyedObjectPool, Object) * @since Pool 1.3 */ public static ObjectPool adapt(final KeyedObjectPool keyedPool) throws IllegalArgumentException { return adapt(keyedPool, new Object()); } /** * Adapt a KeyedObjectPool instance to work where an ObjectPool is needed using the * specified key when delegating. * * @param the type of object * @param keyedPool the {@link KeyedObjectPool} to delegate to. * @param key the key to use when delegating. * @return an {@link ObjectPool} that delegates to keyedPool with the specified key. * @throws IllegalArgumentException when keyedPool or key is null. * @see #adapt(KeyedObjectPool) * @since Pool 1.3 */ public static ObjectPool adapt(final KeyedObjectPool keyedPool, final Object key) throws IllegalArgumentException { return new ObjectPoolAdaptor(keyedPool, key); } /** * Adapt an ObjectPool to work where an KeyedObjectPool is needed. * The key is ignored. * * @param the type of key * @param the type of object * @param pool the {@link ObjectPool} to delegate to. * @return a {@link KeyedObjectPool} that delegates to pool ignoring the key. * @throws IllegalArgumentException when pool is null. * @since Pool 1.3 */ public static KeyedObjectPool adapt(final ObjectPool pool) throws IllegalArgumentException { return new KeyedObjectPoolAdaptor(pool); } /** * Wraps an ObjectPool and dynamically checks the type of objects borrowed and returned to the pool. * If an object is passed to the pool that isn't of type type a {@link ClassCastException} will be thrown. * * @param the type of object * @param pool the pool to enforce type safety on * @param type the class type to enforce. * @return an ObjectPool that will only allow objects of type * @since Pool 1.3 */ public static ObjectPool checkedPool(final ObjectPool pool, final Class type) { if (pool == null) { throw new IllegalArgumentException("pool must not be null."); } if (type == null) { throw new IllegalArgumentException("type must not be null."); } return new CheckedObjectPool(pool, type); } /** * Wraps a KeyedObjectPool and dynamically checks the type of objects borrowed and returned to the keyedPool. * If an object is passed to the keyedPool that isn't of type type a {@link ClassCastException} will be thrown. * * @param the type of key * @param the type of object * @param keyedPool the keyedPool to enforce type safety on * @param type the class type to enforce. * @return a KeyedObjectPool that will only allow objects of type * @since Pool 1.3 */ public static KeyedObjectPool checkedPool(final KeyedObjectPool keyedPool, final Class type) { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (type == null) { throw new IllegalArgumentException("type must not be null."); } return new CheckedKeyedObjectPool(keyedPool, type); } /** * Periodically check the idle object count for the pool. At most one idle object will be added per period. * If there is an exception when calling {@link ObjectPool#addObject()} then no more checks will be performed. * * @param the type of object * @param pool the pool to check periodically. * @param minIdle if the {@link ObjectPool#getNumIdle()} is less than this then add an idle object. * @param period the frequency to check the number of idle objects in a pool, see * {@link Timer#schedule(TimerTask, long, long)}. * @return the {@link TimerTask} that will periodically check the pools idle object count. * @throws IllegalArgumentException when pool is null or * when minIdle is negative or when period isn't * valid for {@link Timer#schedule(TimerTask, long, long)}. * @since Pool 1.3 */ public static TimerTask checkMinIdle(final ObjectPool pool, final int minIdle, final long period) throws IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (minIdle < 0) { throw new IllegalArgumentException("minIdle must be non-negative."); } final TimerTask task = new ObjectPoolMinIdleTimerTask(pool, minIdle); getMinIdleTimer().schedule(task, 0L, period); return task; } /** * Periodically check the idle object count for the key in the keyedPool. At most one idle object will be added per period. * If there is an exception when calling {@link KeyedObjectPool#addObject(Object)} then no more checks for that key * will be performed. * * @param the type of key * @param the type of object * @param keyedPool the keyedPool to check periodically. * @param key the key to check the idle count of. * @param minIdle if the {@link KeyedObjectPool#getNumIdle(Object)} is less than this then add an idle object. * @param period the frequency to check the number of idle objects in a keyedPool, see * {@link Timer#schedule(TimerTask, long, long)}. * @return the {@link TimerTask} that will periodically check the pools idle object count. * @throws IllegalArgumentException when keyedPool, key is null or * when minIdle is negative or when period isn't * valid for {@link Timer#schedule(TimerTask, long, long)}. * @since Pool 1.3 */ public static TimerTask checkMinIdle(final KeyedObjectPool keyedPool, final K key, final int minIdle, final long period) throws IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (key == null) { throw new IllegalArgumentException("key must not be null."); } if (minIdle < 0) { throw new IllegalArgumentException("minIdle must be non-negative."); } final TimerTask task = new KeyedObjectPoolMinIdleTimerTask(keyedPool, key, minIdle); getMinIdleTimer().schedule(task, 0L, period); return task; } /** * Periodically check the idle object count for each key in the Collection keys in the keyedPool. * At most one idle object will be added per period. * * @param the type of key * @param the type of object * @param keyedPool the keyedPool to check periodically. * @param keys a collection of keys to check the idle object count. * @param minIdle if the {@link KeyedObjectPool#getNumIdle(Object)} is less than this then add an idle object. * @param period the frequency to check the number of idle objects in a keyedPool, see * {@link Timer#schedule(TimerTask, long, long)}. * @return a {@link Map} of key and {@link TimerTask} pairs that will periodically check the pools idle object count. * @throws IllegalArgumentException when keyedPool, keys, or any of the values in the * collection is null or when minIdle is negative or when period isn't * valid for {@link Timer#schedule(TimerTask, long, long)}. * @see #checkMinIdle(KeyedObjectPool, Object, int, long) * @since Pool 1.3 */ public static Map checkMinIdle(final KeyedObjectPool keyedPool, final Collection keys, final int minIdle, final long period) throws IllegalArgumentException { if (keys == null) { throw new IllegalArgumentException("keys must not be null."); } final Map tasks = new HashMap(keys.size()); final Iterator iter = keys.iterator(); while (iter.hasNext()) { final K key = iter.next(); final TimerTask task = checkMinIdle(keyedPool, key, minIdle, period); tasks.put(key, task); } return tasks; } /** * Call addObject() on pool count number of times. * * @param the type of object * @param pool the pool to prefill. * @param count the number of idle objects to add. * @throws Exception when {@link ObjectPool#addObject()} fails. * @throws IllegalArgumentException when pool is null. * @since Pool 1.3 */ public static void prefill(final ObjectPool pool, final int count) throws Exception, IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("pool must not be null."); } for (int i = 0; i < count; i++) { pool.addObject(); } } /** * Call addObject(Object) on keyedPool with key count * number of times. * * @param the type of key * @param the type of object * @param keyedPool the keyedPool to prefill. * @param key the key to add objects for. * @param count the number of idle objects to add for key. * @throws Exception when {@link KeyedObjectPool#addObject(Object)} fails. * @throws IllegalArgumentException when keyedPool or key is null. * @since Pool 1.3 */ public static void prefill(final KeyedObjectPool keyedPool, final K key, final int count) throws Exception, IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (key == null) { throw new IllegalArgumentException("key must not be null."); } for (int i = 0; i < count; i++) { keyedPool.addObject(key); } } /** * Call addObject(Object) on keyedPool with each key in keys for * count number of times. This has the same effect as calling * {@link #prefill(KeyedObjectPool, Object, int)} for each key in the keys collection. * * @param the type of key * @param the type of object * @param keyedPool the keyedPool to prefill. * @param keys {@link Collection} of keys to add objects for. * @param count the number of idle objects to add for each key. * @throws Exception when {@link KeyedObjectPool#addObject(Object)} fails. * @throws IllegalArgumentException when keyedPool, keys, or * any value in keys is null. * @see #prefill(KeyedObjectPool, Object, int) * @since Pool 1.3 */ public static void prefill(final KeyedObjectPool keyedPool, final Collection keys, final int count) throws Exception, IllegalArgumentException { if (keys == null) { throw new IllegalArgumentException("keys must not be null."); } final Iterator iter = keys.iterator(); while (iter.hasNext()) { prefill(keyedPool, iter.next(), count); } } /** * Returns a synchronized (thread-safe) ObjectPool backed by the specified ObjectPool. * *

Note: * This should not be used on pool implementations that already provide proper synchronization * such as the pools provided in the Commons Pool library. Wrapping a pool that * {@link #wait() waits} for poolable objects to be returned before allowing another one to be * borrowed with another layer of synchronization will cause liveliness issues or a deadlock. *

* * @param the type of object * @param pool the ObjectPool to be "wrapped" in a synchronized ObjectPool. * @return a synchronized view of the specified ObjectPool. * @since Pool 1.3 */ public static ObjectPool synchronizedPool(final ObjectPool pool) { if (pool == null) { throw new IllegalArgumentException("pool must not be null."); } /* assert !(pool instanceof GenericObjectPool) : "GenericObjectPool is already thread-safe"; assert !(pool instanceof SoftReferenceObjectPool) : "SoftReferenceObjectPool is already thread-safe"; assert !(pool instanceof StackObjectPool) : "StackObjectPool is already thread-safe"; assert !"org.apache.commons.pool.composite.CompositeObjectPool".equals(pool.getClass().getName()) : "CompositeObjectPools are already thread-safe"; */ return new SynchronizedObjectPool(pool); } /** * Returns a synchronized (thread-safe) KeyedObjectPool backed by the specified KeyedObjectPool. * *

Note: * This should not be used on pool implementations that already provide proper synchronization * such as the pools provided in the Commons Pool library. Wrapping a pool that * {@link #wait() waits} for poolable objects to be returned before allowing another one to be * borrowed with another layer of synchronization will cause liveliness issues or a deadlock. *

* * @param the type of key * @param the type of object * @param keyedPool the KeyedObjectPool to be "wrapped" in a synchronized KeyedObjectPool. * @return a synchronized view of the specified KeyedObjectPool. * @since Pool 1.3 */ public static KeyedObjectPool synchronizedPool(final KeyedObjectPool keyedPool) { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } /* assert !(keyedPool instanceof GenericKeyedObjectPool) : "GenericKeyedObjectPool is already thread-safe"; assert !(keyedPool instanceof StackKeyedObjectPool) : "StackKeyedObjectPool is already thread-safe"; assert !"org.apache.commons.pool.composite.CompositeKeyedObjectPool".equals(keyedPool.getClass().getName()) : "CompositeKeyedObjectPools are already thread-safe"; */ return new SynchronizedKeyedObjectPool(keyedPool); } /** * Returns a synchronized (thread-safe) PoolableObjectFactory backed by the specified PoolableObjectFactory. * * @param the type of object * @param factory the PoolableObjectFactory to be "wrapped" in a synchronized PoolableObjectFactory. * @return a synchronized view of the specified PoolableObjectFactory. * @since Pool 1.3 */ public static PoolableObjectFactory synchronizedPoolableFactory(final PoolableObjectFactory factory) { return new SynchronizedPoolableObjectFactory(factory); } /** * Returns a synchronized (thread-safe) KeyedPoolableObjectFactory backed by the specified KeyedPoolableObjectFactory. * * @param the type of key * @param the type of object * @param keyedFactory the KeyedPoolableObjectFactory to be "wrapped" in a synchronized KeyedPoolableObjectFactory. * @return a synchronized view of the specified KeyedPoolableObjectFactory. * @since Pool 1.3 */ public static KeyedPoolableObjectFactory synchronizedPoolableFactory(final KeyedPoolableObjectFactory keyedFactory) { return new SynchronizedKeyedPoolableObjectFactory(keyedFactory); } /** * Returns a pool that adaptively decreases it's size when idle objects are no longer needed. * This is intended as an always thread-safe alternative to using an idle object evictor * provided by many pool implementations. This is also an effective way to shrink FIFO ordered * pools that experience load spikes. * * @param the type of object * @param pool the ObjectPool to be decorated so it shrinks it's idle count when possible. * @return a pool that adaptively decreases it's size when idle objects are no longer needed. * @see #erodingPool(ObjectPool, float) * @since Pool 1.4 */ public static ObjectPool erodingPool(final ObjectPool pool) { return erodingPool(pool, 1f); } /** * Returns a pool that adaptively decreases it's size when idle objects are no longer needed. * This is intended as an always thread-safe alternative to using an idle object evictor * provided by many pool implementations. This is also an effective way to shrink FIFO ordered * pools that experience load spikes. * *

* The factor parameter provides a mechanism to tweak the rate at which the pool tries to shrink * it's size. Values between 0 and 1 cause the pool to try to shrink it's size more often. * Values greater than 1 cause the pool to less frequently try to shrink it's size. *

* * @param the type of object * @param pool the ObjectPool to be decorated so it shrinks it's idle count when possible. * @param factor a positive value to scale the rate at which the pool tries to reduce it's size. * If 0 < factor < 1 then the pool shrinks more aggressively. * If 1 < factor then the pool shrinks less aggressively. * @return a pool that adaptively decreases it's size when idle objects are no longer needed. * @see #erodingPool(ObjectPool) * @since Pool 1.4 */ public static ObjectPool erodingPool(final ObjectPool pool, final float factor) { if (pool == null) { throw new IllegalArgumentException("pool must not be null."); } if (factor <= 0f) { throw new IllegalArgumentException("factor must be positive."); } return new ErodingObjectPool(pool, factor); } /** * Returns a pool that adaptively decreases it's size when idle objects are no longer needed. * This is intended as an always thread-safe alternative to using an idle object evictor * provided by many pool implementations. This is also an effective way to shrink FIFO ordered * pools that experience load spikes. * * @param the type of key * @param the type of object * @param keyedPool the KeyedObjectPool to be decorated so it shrinks it's idle count when * possible. * @return a pool that adaptively decreases it's size when idle objects are no longer needed. * @see #erodingPool(KeyedObjectPool, float) * @see #erodingPool(KeyedObjectPool, float, boolean) * @since Pool 1.4 */ public static KeyedObjectPool erodingPool(final KeyedObjectPool keyedPool) { return erodingPool(keyedPool, 1f); } /** * Returns a pool that adaptively decreases it's size when idle objects are no longer needed. * This is intended as an always thread-safe alternative to using an idle object evictor * provided by many pool implementations. This is also an effective way to shrink FIFO ordered * pools that experience load spikes. * *

* The factor parameter provides a mechanism to tweak the rate at which the pool tries to shrink * it's size. Values between 0 and 1 cause the pool to try to shrink it's size more often. * Values greater than 1 cause the pool to less frequently try to shrink it's size. *

* * @param the type of key * @param the type of object * @param keyedPool the KeyedObjectPool to be decorated so it shrinks it's idle count when * possible. * @param factor a positive value to scale the rate at which the pool tries to reduce it's size. * If 0 < factor < 1 then the pool shrinks more aggressively. * If 1 < factor then the pool shrinks less aggressively. * @return a pool that adaptively decreases it's size when idle objects are no longer needed. * @see #erodingPool(KeyedObjectPool, float, boolean) * @since Pool 1.4 */ public static KeyedObjectPool erodingPool(final KeyedObjectPool keyedPool, final float factor) { return erodingPool(keyedPool, factor, false); } /** * Returns a pool that adaptively decreases it's size when idle objects are no longer needed. * This is intended as an always thread-safe alternative to using an idle object evictor * provided by many pool implementations. This is also an effective way to shrink FIFO ordered * pools that experience load spikes. * *

* The factor parameter provides a mechanism to tweak the rate at which the pool tries to shrink * it's size. Values between 0 and 1 cause the pool to try to shrink it's size more often. * Values greater than 1 cause the pool to less frequently try to shrink it's size. *

* *

* The perKey parameter determines if the pool shrinks on a whole pool basis or a per key basis. * When perKey is false, the keys do not have an effect on the rate at which the pool tries to * shrink it's size. When perKey is true, each key is shrunk independently. *

* * @param the type of key * @param the type of object * @param keyedPool the KeyedObjectPool to be decorated so it shrinks it's idle count when * possible. * @param factor a positive value to scale the rate at which the pool tries to reduce it's size. * If 0 < factor < 1 then the pool shrinks more aggressively. * If 1 < factor then the pool shrinks less aggressively. * @param perKey when true, each key is treated independently. * @return a pool that adaptively decreases it's size when idle objects are no longer needed. * @see #erodingPool(KeyedObjectPool) * @see #erodingPool(KeyedObjectPool, float) * @since Pool 1.4 */ public static KeyedObjectPool erodingPool(final KeyedObjectPool keyedPool, final float factor, final boolean perKey) { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (factor <= 0f) { throw new IllegalArgumentException("factor must be positive."); } if (perKey) { return new ErodingPerKeyKeyedObjectPool(keyedPool, factor); } else { return new ErodingKeyedObjectPool(keyedPool, factor); } } /** * Get the Timer for checking keyedPool's idle count. Lazily create the {@link Timer} as needed. * * @return the {@link Timer} for checking keyedPool's idle count. * @since Pool 1.3 */ private static synchronized Timer getMinIdleTimer() { if (MIN_IDLE_TIMER == null) { MIN_IDLE_TIMER = new Timer(true); } return MIN_IDLE_TIMER; } /** * Adaptor class that wraps and converts a KeyedPoolableObjectFactory with a fixed * key to a PoolableObjectFactory. */ private static class PoolableObjectFactoryAdaptor implements PoolableObjectFactory { /** Fixed key */ private final K key; /** Wrapped factory */ private final KeyedPoolableObjectFactory keyedFactory; /** * Create a PoolableObjectFactoryAdaptor wrapping the provided KeyedPoolableObjectFactory with the * given fixed key. * * @param keyedFactory KeyedPoolableObjectFactory that will manage objects * @param key fixed key * @throws IllegalArgumentException if either of the parameters is null */ PoolableObjectFactoryAdaptor(final KeyedPoolableObjectFactory keyedFactory, final K key) throws IllegalArgumentException { if (keyedFactory == null) { throw new IllegalArgumentException("keyedFactory must not be null."); } if (key == null) { throw new IllegalArgumentException("key must not be null."); } this.keyedFactory = keyedFactory; this.key = key; } /** * Create an object instance using the configured factory and key. * * @return new object instance */ public V makeObject() throws Exception { return keyedFactory.makeObject(key); } /** * Destroy the object, passing the fixed key to the factory. * * @param obj object to destroy */ public void destroyObject(final V obj) throws Exception { keyedFactory.destroyObject(key, obj); } /** * Validate the object, passing the fixed key to the factory. * * @param obj object to validate * @return true if validation is successful */ public boolean validateObject(final V obj) { return keyedFactory.validateObject(key, obj); } /** * Activate the object, passing the fixed key to the factory. * * @param obj object to activate */ public void activateObject(final V obj) throws Exception { keyedFactory.activateObject(key, obj); } /** * Passivate the object, passing the fixed key to the factory. * * @param obj object to passivate */ public void passivateObject(final V obj) throws Exception { keyedFactory.passivateObject(key, obj); } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("PoolableObjectFactoryAdaptor"); sb.append("{key=").append(key); sb.append(", keyedFactory=").append(keyedFactory); sb.append('}'); return sb.toString(); } } /** * Adaptor class that turns a PoolableObjectFactory into a KeyedPoolableObjectFactory by * ignoring keys. */ private static class KeyedPoolableObjectFactoryAdaptor implements KeyedPoolableObjectFactory { /** Underlying PoolableObjectFactory */ private final PoolableObjectFactory factory; /** * Create a new KeyedPoolableObjectFactoryAdaptor using the given PoolableObjectFactory to * manage objects. * * @param factory wrapped PoolableObjectFactory * @throws IllegalArgumentException if the factory is null */ KeyedPoolableObjectFactoryAdaptor(final PoolableObjectFactory factory) throws IllegalArgumentException { if (factory == null) { throw new IllegalArgumentException("factory must not be null."); } this.factory = factory; } /** * Create a new object instance, ignoring the key * * @param key ignored * @return newly created object instance */ public V makeObject(final K key) throws Exception { return factory.makeObject(); } /** * Destroy the object, ignoring the key. * * @param key ignored * @param obj instance to destroy */ public void destroyObject(final K key, final V obj) throws Exception { factory.destroyObject(obj); } /** * Validate the object, ignoring the key * * @param key ignored * @param obj object to validate * @return true if validation is successful */ public boolean validateObject(final K key, final V obj) { return factory.validateObject(obj); } /** * Activate the object, ignoring the key. * * @param key ignored * @param obj object to be activated */ public void activateObject(final K key, final V obj) throws Exception { factory.activateObject(obj); } /** * Passivate the object, ignoring the key. * * @param key ignored * @param obj object to passivate */ public void passivateObject(final K key, final V obj) throws Exception { factory.passivateObject(obj); } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("KeyedPoolableObjectFactoryAdaptor"); sb.append("{factory=").append(factory); sb.append('}'); return sb.toString(); } } /** * Adapts a KeyedObjectPool to make it an ObjectPool by fixing restricting to * a fixed key. */ private static class ObjectPoolAdaptor implements ObjectPool { /** Fixed key */ private final Object key; /** Underlying KeyedObjectPool */ private final KeyedObjectPool keyedPool; /** * Create a new ObjectPoolAdaptor using the provided KeyedObjectPool and fixed key. * * @param keyedPool underlying KeyedObjectPool * @param key fixed key * @throws IllegalArgumentException if either of the parameters is null */ ObjectPoolAdaptor(final KeyedObjectPool keyedPool, final Object key) throws IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (key == null) { throw new IllegalArgumentException("key must not be null."); } this.keyedPool = keyedPool; this.key = key; } /** * {@inheritDoc} */ public V borrowObject() throws Exception, NoSuchElementException, IllegalStateException { return keyedPool.borrowObject(key); } /** * {@inheritDoc} */ public void returnObject(final V obj) { try { keyedPool.returnObject(key, obj); } catch (Exception e) { // swallowed as of Pool 2 } } /** * {@inheritDoc} */ public void invalidateObject(final V obj) { try { keyedPool.invalidateObject(key, obj); } catch (Exception e) { // swallowed as of Pool 2 } } /** * {@inheritDoc} */ public void addObject() throws Exception, IllegalStateException { keyedPool.addObject(key); } /** * {@inheritDoc} */ public int getNumIdle() throws UnsupportedOperationException { return keyedPool.getNumIdle(key); } /** * {@inheritDoc} */ public int getNumActive() throws UnsupportedOperationException { return keyedPool.getNumActive(key); } /** * {@inheritDoc} */ public void clear() throws Exception, UnsupportedOperationException { keyedPool.clear(); } /** * {@inheritDoc} */ public void close() { try { keyedPool.close(); } catch (Exception e) { // swallowed as of Pool 2 } } /** * Sets the PoolableObjectFactory for the pool. * * @param factory new PoolableObjectFactory * @deprecated to be removed in version 2.0 */ @Deprecated public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { keyedPool.setFactory(adapt(factory)); } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("ObjectPoolAdaptor"); sb.append("{key=").append(key); sb.append(", keyedPool=").append(keyedPool); sb.append('}'); return sb.toString(); } } /** * Adapts an ObjectPool to implement KeyedObjectPool by ignoring key arguments. */ private static class KeyedObjectPoolAdaptor implements KeyedObjectPool { /** Underlying pool */ private final ObjectPool pool; /** * Create a new KeyedObjectPoolAdaptor wrapping the given ObjectPool * * @param pool underlying object pool * @throws IllegalArgumentException if pool is null */ KeyedObjectPoolAdaptor(final ObjectPool pool) throws IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("pool must not be null."); } this.pool = pool; } /** * Borrow and object from the pool, ignoring the key * * @param key ignored * @return newly created object instance */ public V borrowObject(final K key) throws Exception, NoSuchElementException, IllegalStateException { return pool.borrowObject(); } /** * Return and object to the pool, ignoring the key * * @param key ignored * @param obj object to return */ public void returnObject(final K key, final V obj) { try { pool.returnObject(obj); } catch (Exception e) { // swallowed as of Pool 2 } } /** * Invalidate and object, ignoring the key * * @param obj object to invalidate * @param key ignored */ public void invalidateObject(final K key, final V obj) { try { pool.invalidateObject(obj); } catch (Exception e) { // swallowed as of Pool 2 } } /** * Add an object to the pool, ignoring the key * * @param key ignored */ public void addObject(final K key) throws Exception, IllegalStateException { pool.addObject(); } /** * Return the number of objects idle in the pool, ignoring the key. * * @param key ignored * @return idle instance count */ public int getNumIdle(final K key) throws UnsupportedOperationException { return pool.getNumIdle(); } /** * Return the number of objects checked out from the pool, ignoring the key. * * @param key ignored * @return active instance count */ public int getNumActive(final K key) throws UnsupportedOperationException { return pool.getNumActive(); } /** * {@inheritDoc} */ public int getNumIdle() throws UnsupportedOperationException { return pool.getNumIdle(); } /** * {@inheritDoc} */ public int getNumActive() throws UnsupportedOperationException { return pool.getNumActive(); } /** * {@inheritDoc} */ public void clear() throws Exception, UnsupportedOperationException { pool.clear(); } /** * Clear the pool, ignoring the key (has same effect as {@link #clear()}. * * @param key ignored. */ public void clear(final K key) throws Exception, UnsupportedOperationException { pool.clear(); } /** * {@inheritDoc} */ public void close() { try { pool.close(); } catch (Exception e) { // swallowed as of Pool 2 } } /** * Sets the factory used to manage objects. * * @param factory new factory to use managing object instances * @deprecated to be removed in version 2.0 */ @Deprecated @SuppressWarnings("unchecked") public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { pool.setFactory(adapt((KeyedPoolableObjectFactory)factory)); } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("KeyedObjectPoolAdaptor"); sb.append("{pool=").append(pool); sb.append('}'); return sb.toString(); } } /** * An object pool that performs type checking on objects passed * to pool methods. * */ private static class CheckedObjectPool implements ObjectPool { /** * Type of objects allowed in the pool. This should be a subtype of the return type of * the underlying pool's associated object factory. */ private final Class type; /** Underlying object pool */ private final ObjectPool pool; /** * Create a CheckedObjectPool accepting objects of the given type using * the given pool. * * @param pool underlying object pool * @param type expected pooled object type * @throws IllegalArgumentException if either parameter is null */ CheckedObjectPool(final ObjectPool pool, final Class type) { if (pool == null) { throw new IllegalArgumentException("pool must not be null."); } if (type == null) { throw new IllegalArgumentException("type must not be null."); } this.pool = pool; this.type = type; } /** * Borrow an object from the pool, checking its type. * * @return a type-checked object from the pool * @throws ClassCastException if the object returned by the pool is not of the expected type */ public T borrowObject() throws Exception, NoSuchElementException, IllegalStateException { final T obj = pool.borrowObject(); if (type.isInstance(obj)) { return obj; } else { throw new ClassCastException("Borrowed object is not of type: " + type.getName() + " was: " + obj); } } /** * Return an object to the pool, verifying that it is of the correct type. * * @param obj object to return * @throws ClassCastException if obj is not of the expected type */ public void returnObject(final T obj) { if (type.isInstance(obj)) { try { pool.returnObject(obj); } catch (Exception e) { // swallowed as of Pool 2 } } else { throw new ClassCastException("Returned object is not of type: " + type.getName() + " was: " + obj); } } /** * Invalidates an object from the pool, verifying that it is of the expected type. * * @param obj object to invalidate * @throws ClassCastException if obj is not of the expected type */ public void invalidateObject(final T obj) { if (type.isInstance(obj)) { try { pool.invalidateObject(obj); } catch (Exception e) { // swallowed as of Pool 2 } } else { throw new ClassCastException("Invalidated object is not of type: " + type.getName() + " was: " + obj); } } /** * {@inheritDoc} */ public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException { pool.addObject(); } /** * {@inheritDoc} */ public int getNumIdle() throws UnsupportedOperationException { return pool.getNumIdle(); } /** * {@inheritDoc} */ public int getNumActive() throws UnsupportedOperationException { return pool.getNumActive(); } /** * {@inheritDoc} */ public void clear() throws Exception, UnsupportedOperationException { pool.clear(); } /** * {@inheritDoc} */ public void close() { try { pool.close(); } catch (Exception e) { // swallowed as of Pool 2 } } /** * Sets the object factory associated with the pool * * @param factory object factory * @deprecated to be removed in version 2.0 */ @Deprecated public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { pool.setFactory(factory); } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("CheckedObjectPool"); sb.append("{type=").append(type); sb.append(", pool=").append(pool); sb.append('}'); return sb.toString(); } } /** * A keyed object pool that performs type checking on objects passed * to pool methods. * */ private static class CheckedKeyedObjectPool implements KeyedObjectPool { /** * Expected type of objects managed by the pool. This should be * a subtype of the return type of the object factory used by the pool. */ private final Class type; /** Underlying pool */ private final KeyedObjectPool keyedPool; /** * Create a new CheckedKeyedObjectPool from the given pool with given expected object type. * * @param keyedPool underlying pool * @param type expected object type * @throws IllegalArgumentException if either parameter is null */ CheckedKeyedObjectPool(final KeyedObjectPool keyedPool, final Class type) { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (type == null) { throw new IllegalArgumentException("type must not be null."); } this.keyedPool = keyedPool; this.type = type; } /** * Borrow an object from the pool, verifying correct return type. * * @param key pool key * @return type-checked object from the pool under the given key * @throws ClassCastException if the object returned by the pool is not of the expected type */ public V borrowObject(final K key) throws Exception, NoSuchElementException, IllegalStateException { V obj = keyedPool.borrowObject(key); if (type.isInstance(obj)) { return obj; } else { throw new ClassCastException("Borrowed object for key: " + key + " is not of type: " + type.getName() + " was: " + obj); } } /** * Return an object to the pool, checking its type. * * @param key the associated key (not type-checked) * @param obj the object to return (type-checked) * @throws ClassCastException if obj is not of the expected type */ public void returnObject(final K key, final V obj) { if (type.isInstance(obj)) { try { keyedPool.returnObject(key, obj); } catch (Exception e) { // swallowed as of Pool 2 } } else { throw new ClassCastException("Returned object for key: " + key + " is not of type: " + type.getName() + " was: " + obj); } } /** * Invalidate an object to the pool, checking its type. * * @param key the associated key (not type-checked) * @param obj the object to return (type-checked) * @throws ClassCastException if obj is not of the expected type */ public void invalidateObject(final K key, final V obj) { if (type.isInstance(obj)) { try { keyedPool.invalidateObject(key, obj); } catch (Exception e) { // swallowed as of Pool 2 } } else { throw new ClassCastException("Invalidated object for key: " + key + " is not of type: " + type.getName() + " was: " + obj); } } /** * {@inheritDoc} */ public void addObject(final K key) throws Exception, IllegalStateException, UnsupportedOperationException { keyedPool.addObject(key); } /** * {@inheritDoc} */ public int getNumIdle(final K key) throws UnsupportedOperationException { return keyedPool.getNumIdle(key); } /** * {@inheritDoc} */ public int getNumActive(final K key) throws UnsupportedOperationException { return keyedPool.getNumActive(key); } /** * {@inheritDoc} */ public int getNumIdle() throws UnsupportedOperationException { return keyedPool.getNumIdle(); } /** * {@inheritDoc} */ public int getNumActive() throws UnsupportedOperationException { return keyedPool.getNumActive(); } /** * {@inheritDoc} */ public void clear() throws Exception, UnsupportedOperationException { keyedPool.clear(); } /** * {@inheritDoc} */ public void clear(final K key) throws Exception, UnsupportedOperationException { keyedPool.clear(key); } /** * {@inheritDoc} */ public void close() { try { keyedPool.close(); } catch (Exception e) { // swallowed as of Pool 2 } } /** * Sets the object factory associated with the pool * * @param factory object factory * @deprecated to be removed in version 2.0 */ @Deprecated public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { keyedPool.setFactory(factory); } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("CheckedKeyedObjectPool"); sb.append("{type=").append(type); sb.append(", keyedPool=").append(keyedPool); sb.append('}'); return sb.toString(); } } /** * Timer task that adds objects to the pool until the number of idle * instances reaches the configured minIdle. Note that this is not the * same as the pool's minIdle setting. * */ private static class ObjectPoolMinIdleTimerTask extends TimerTask { /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */ private final int minIdle; /** Object pool */ private final ObjectPool pool; /** * Create a new ObjectPoolMinIdleTimerTask for the given pool with the given minIdle setting. * * @param pool object pool * @param minIdle number of idle instances to maintain * @throws IllegalArgumentException if the pool is null */ ObjectPoolMinIdleTimerTask(final ObjectPool pool, final int minIdle) throws IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("pool must not be null."); } this.pool = pool; this.minIdle = minIdle; } /** * {@inheritDoc} */ @Override public void run() { boolean success = false; try { if (pool.getNumIdle() < minIdle) { pool.addObject(); } success = true; } catch (Exception e) { cancel(); } finally { // detect other types of Throwable and cancel this Timer if (!success) { cancel(); } } } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("ObjectPoolMinIdleTimerTask"); sb.append("{minIdle=").append(minIdle); sb.append(", pool=").append(pool); sb.append('}'); return sb.toString(); } } /** * Timer task that adds objects to the pool until the number of idle * instances for the given key reaches the configured minIdle. Note that this is not the * same as the pool's minIdle setting. * */ private static class KeyedObjectPoolMinIdleTimerTask extends TimerTask { /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */ private final int minIdle; /** Key to ensure minIdle for */ private final K key; /** Keyed object pool */ private final KeyedObjectPool keyedPool; /** * Create a new KeyedObjecPoolMinIdleTimerTask. * * @param keyedPool keyed object pool * @param key key to ensure minimum number of idle instances * @param minIdle minimum number of idle instances * @throws IllegalArgumentException if the key is null */ KeyedObjectPoolMinIdleTimerTask(final KeyedObjectPool keyedPool, final K key, final int minIdle) throws IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } this.keyedPool = keyedPool; this.key = key; this.minIdle = minIdle; } /** * {@inheritDoc} */ @Override public void run() { boolean success = false; try { if (keyedPool.getNumIdle(key) < minIdle) { keyedPool.addObject(key); } success = true; } catch (Exception e) { cancel(); } finally { // detect other types of Throwable and cancel this Timer if (!success) { cancel(); } } } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("KeyedObjectPoolMinIdleTimerTask"); sb.append("{minIdle=").append(minIdle); sb.append(", key=").append(key); sb.append(", keyedPool=").append(keyedPool); sb.append('}'); return sb.toString(); } } /** * A synchronized (thread-safe) ObjectPool backed by the specified ObjectPool. * *

Note: * This should not be used on pool implementations that already provide proper synchronization * such as the pools provided in the Commons Pool library. Wrapping a pool that * {@link #wait() waits} for poolable objects to be returned before allowing another one to be * borrowed with another layer of synchronization will cause liveliness issues or a deadlock. *

*/ private static class SynchronizedObjectPool implements ObjectPool { /** Object whose monitor is used to synchronize methods on the wrapped pool. */ private final Object lock; /** the underlying object pool */ private final ObjectPool pool; /** * Create a new SynchronizedObjectPool wrapping the given pool. * * @param pool the ObjectPool to be "wrapped" in a synchronized ObjectPool. * @throws IllegalArgumentException if the pool is null */ SynchronizedObjectPool(final ObjectPool pool) throws IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("pool must not be null."); } this.pool = pool; lock = new Object(); } /** * {@inheritDoc} */ public T borrowObject() throws Exception, NoSuchElementException, IllegalStateException { synchronized (lock) { return pool.borrowObject(); } } /** * {@inheritDoc} */ public void returnObject(final T obj) { synchronized (lock) { try { pool.returnObject(obj); } catch (Exception e) { // swallowed as of Pool 2 } } } /** * {@inheritDoc} */ public void invalidateObject(final T obj) { synchronized (lock) { try { pool.invalidateObject(obj); } catch (Exception e) { // swallowed as of Pool 2 } } } /** * {@inheritDoc} */ public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException { synchronized (lock) { pool.addObject(); } } /** * {@inheritDoc} */ public int getNumIdle() throws UnsupportedOperationException { synchronized (lock) { return pool.getNumIdle(); } } /** * {@inheritDoc} */ public int getNumActive() throws UnsupportedOperationException { synchronized (lock) { return pool.getNumActive(); } } /** * {@inheritDoc} */ public void clear() throws Exception, UnsupportedOperationException { synchronized (lock) { pool.clear(); } } /** * {@inheritDoc} */ public void close() { try { synchronized (lock) { pool.close(); } } catch (Exception e) { // swallowed as of Pool 2 } } /** * Sets the factory used by the pool. * * @param factory new PoolableObjectFactory * @deprecated to be removed in pool 2.0 */ @Deprecated public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { synchronized (lock) { pool.setFactory(factory); } } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("SynchronizedObjectPool"); sb.append("{pool=").append(pool); sb.append('}'); return sb.toString(); } } /** * A synchronized (thread-safe) KeyedObjectPool backed by the specified KeyedObjectPool. * *

Note: * This should not be used on pool implementations that already provide proper synchronization * such as the pools provided in the Commons Pool library. Wrapping a pool that * {@link #wait() waits} for poolable objects to be returned before allowing another one to be * borrowed with another layer of synchronization will cause liveliness issues or a deadlock. *

*/ private static class SynchronizedKeyedObjectPool implements KeyedObjectPool { /** Object whose monitor is used to synchronize methods on the wrapped pool. */ private final Object lock; /** Underlying object pool */ private final KeyedObjectPool keyedPool; /** * Create a new SynchronizedKeyedObjectPool wrapping the given pool * * @param keyedPool KeyedObjectPool to wrap * @throws IllegalArgumentException if keyedPool is null */ SynchronizedKeyedObjectPool(final KeyedObjectPool keyedPool) throws IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } this.keyedPool = keyedPool; lock = new Object(); } /** * {@inheritDoc} */ public V borrowObject(final K key) throws Exception, NoSuchElementException, IllegalStateException { synchronized (lock) { return keyedPool.borrowObject(key); } } /** * {@inheritDoc} */ public void returnObject(final K key, final V obj) { synchronized (lock) { try { keyedPool.returnObject(key, obj); } catch (Exception e) { // swallowed } } } /** * {@inheritDoc} */ public void invalidateObject(final K key, final V obj) { synchronized (lock) { try { keyedPool.invalidateObject(key, obj); } catch (Exception e) { // swallowed as of Pool 2 } } } /** * {@inheritDoc} */ public void addObject(final K key) throws Exception, IllegalStateException, UnsupportedOperationException { synchronized (lock) { keyedPool.addObject(key); } } /** * {@inheritDoc} */ public int getNumIdle(final K key) throws UnsupportedOperationException { synchronized (lock) { return keyedPool.getNumIdle(key); } } /** * {@inheritDoc} */ public int getNumActive(final K key) throws UnsupportedOperationException { synchronized (lock) { return keyedPool.getNumActive(key); } } /** * {@inheritDoc} */ public int getNumIdle() throws UnsupportedOperationException { synchronized (lock) { return keyedPool.getNumIdle(); } } /** * {@inheritDoc} */ public int getNumActive() throws UnsupportedOperationException { synchronized (lock) { return keyedPool.getNumActive(); } } /** * {@inheritDoc} */ public void clear() throws Exception, UnsupportedOperationException { synchronized (lock) { keyedPool.clear(); } } /** * {@inheritDoc} */ public void clear(final K key) throws Exception, UnsupportedOperationException { synchronized (lock) { keyedPool.clear(key); } } /** * {@inheritDoc} */ public void close() { try { synchronized (lock) { keyedPool.close(); } } catch (Exception e) { // swallowed as of Pool 2 } } /** * Sets the object factory used by the pool. * * @param factory KeyedPoolableObjectFactory used by the pool * @deprecated to be removed in pool 2.0 */ @Deprecated public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { synchronized (lock) { keyedPool.setFactory(factory); } } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("SynchronizedKeyedObjectPool"); sb.append("{keyedPool=").append(keyedPool); sb.append('}'); return sb.toString(); } } /** * A fully synchronized PoolableObjectFactory that wraps a PoolableObjectFactory and synchronizes * access to the wrapped factory methods. * *

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

*/ private static class SynchronizedPoolableObjectFactory implements PoolableObjectFactory { /** Synchronization lock */ private final Object lock; /** Wrapped factory */ private final PoolableObjectFactory factory; /** * Create a SynchronizedPoolableObjectFactory wrapping the given factory. * * @param factory underlying factory to wrap * @throws IllegalArgumentException if the factory is null */ SynchronizedPoolableObjectFactory(final PoolableObjectFactory factory) throws IllegalArgumentException { if (factory == null) { throw new IllegalArgumentException("factory must not be null."); } this.factory = factory; lock = new Object(); } /** * {@inheritDoc} */ public T makeObject() throws Exception { synchronized (lock) { return factory.makeObject(); } } /** * {@inheritDoc} */ public void destroyObject(final T obj) throws Exception { synchronized (lock) { factory.destroyObject(obj); } } /** * {@inheritDoc} */ public boolean validateObject(final T obj) { synchronized (lock) { return factory.validateObject(obj); } } /** * {@inheritDoc} */ public void activateObject(final T obj) throws Exception { synchronized (lock) { factory.activateObject(obj); } } /** * {@inheritDoc} */ public void passivateObject(final T obj) throws Exception { synchronized (lock) { factory.passivateObject(obj); } } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("SynchronizedPoolableObjectFactory"); sb.append("{factory=").append(factory); sb.append('}'); return sb.toString(); } } /** * A fully synchronized KeyedPoolableObjectFactory that wraps a KeyedPoolableObjectFactory and synchronizes * access to the wrapped factory methods. * *

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

*/ private static class SynchronizedKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory { /** Synchronization lock */ private final Object lock; /** Wrapped factory */ private final KeyedPoolableObjectFactory keyedFactory; /** * Create a SynchronizedKeyedPoolableObjectFactory wrapping the given factory. * * @param keyedFactory underlying factory to wrap * @throws IllegalArgumentException if the factory is null */ SynchronizedKeyedPoolableObjectFactory(final KeyedPoolableObjectFactory keyedFactory) throws IllegalArgumentException { if (keyedFactory == null) { throw new IllegalArgumentException("keyedFactory must not be null."); } this.keyedFactory = keyedFactory; lock = new Object(); } /** * {@inheritDoc} */ public V makeObject(final K key) throws Exception { synchronized (lock) { return keyedFactory.makeObject(key); } } /** * {@inheritDoc} */ public void destroyObject(final K key, final V obj) throws Exception { synchronized (lock) { keyedFactory.destroyObject(key, obj); } } /** * {@inheritDoc} */ public boolean validateObject(final K key, final V obj) { synchronized (lock) { return keyedFactory.validateObject(key, obj); } } /** * {@inheritDoc} */ public void activateObject(final K key, final V obj) throws Exception { synchronized (lock) { keyedFactory.activateObject(key, obj); } } /** * {@inheritDoc} */ public void passivateObject(final K key, final V obj) throws Exception { synchronized (lock) { keyedFactory.passivateObject(key, obj); } } /** * {@inheritDoc} */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("SynchronizedKeyedPoolableObjectFactory"); sb.append("{keyedFactory=").append(keyedFactory); sb.append('}'); return sb.toString(); } } /** * Encapsulate the logic for when the next poolable object should be discarded. * Each time update is called, the next time to shrink is recomputed, based on * the float factor, number of idle instances in the pool and high water mark. * Float factor is assumed to be between 0 and 1. Values closer to 1 cause * less frequent erosion events. Erosion event timing also depends on numIdle. * When this value is relatively high (close to previously established high water * mark), erosion occurs more frequently. */ private static class ErodingFactor { /** Determines frequency of "erosion" events */ private final float factor; /** Time of next shrink event */ private transient volatile long nextShrink; /** High water mark - largest numIdle encountered */ private transient volatile int idleHighWaterMark; /** * Create a new ErodingFactor with the given erosion factor. * * @param factor erosion factor */ public ErodingFactor(final float factor) { this.factor = factor; nextShrink = System.currentTimeMillis() + (long)(900000 * factor); // now + 15 min * factor idleHighWaterMark = 1; } /** * Updates internal state based on numIdle and the current time. * * @param numIdle number of idle elements in the pool */ public void update(final int numIdle) { update(System.currentTimeMillis(), numIdle); } /** * Updates internal state using the supplied time and numIdle. * * @param now current time * @param numIdle number of idle elements in the pool */ public void update(final long now, final int numIdle) { final int idle = Math.max(0, numIdle); idleHighWaterMark = Math.max(idle, idleHighWaterMark); final float maxInterval = 15f; final float minutes = maxInterval + ((1f-maxInterval)/idleHighWaterMark) * idle; nextShrink = now + (long)(minutes * 60000f * factor); } /** * Returns the time of the next erosion event. * * @return next shrink time */ public long getNextShrink() { return nextShrink; } /** * {@inheritDoc} */ @Override public String toString() { return "ErodingFactor{" + "factor=" + factor + ", idleHighWaterMark=" + idleHighWaterMark + '}'; } } /** * Decorates an object pool, adding "eroding" behavior. Based on the * configured {@link #factor erosion factor}, objects returning to the pool * may be invalidated instead of being added to idle capacity. * */ private static class ErodingObjectPool implements ObjectPool { /** Underlying object pool */ private final ObjectPool pool; /** Erosion factor */ private final ErodingFactor factor; /** * Create an ErodingObjectPool wrapping the given pool using the specified erosion factor. * * @param pool underlying pool * @param factor erosion factor - determines the frequency of erosion events * @see #factor */ public ErodingObjectPool(final ObjectPool pool, final float factor) { this.pool = pool; this.factor = new ErodingFactor(factor); } /** * {@inheritDoc} */ public T borrowObject() throws Exception, NoSuchElementException, IllegalStateException { return pool.borrowObject(); } /** * Returns obj to the pool, unless erosion is triggered, in which * case obj is invalidated. Erosion is triggered when there are idle instances in * the pool and more than the {@link #factor erosion factor}-determined time has elapsed * since the last returnObject activation. * * @param obj object to return or invalidate * @see #factor */ public void returnObject(final T obj) { boolean discard = false; final long now = System.currentTimeMillis(); synchronized (pool) { if (factor.getNextShrink() < now) { // XXX: Pool 3: move test out of sync block final int numIdle = pool.getNumIdle(); if (numIdle > 0) { discard = true; } factor.update(now, numIdle); } } try { if (discard) { pool.invalidateObject(obj); } else { pool.returnObject(obj); } } catch (Exception e) { // swallowed } } /** * {@inheritDoc} */ public void invalidateObject(final T obj) { try { pool.invalidateObject(obj); } catch (Exception e) { // swallowed } } /** * {@inheritDoc} */ public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException { pool.addObject(); } /** * {@inheritDoc} */ public int getNumIdle() throws UnsupportedOperationException { return pool.getNumIdle(); } /** * {@inheritDoc} */ public int getNumActive() throws UnsupportedOperationException { return pool.getNumActive(); } /** * {@inheritDoc} */ public void clear() throws Exception, UnsupportedOperationException { pool.clear(); } /** * {@inheritDoc} */ public void close() { try { pool.close(); } catch (Exception e) { // swallowed } } /** * {@inheritDoc} * @deprecated to be removed in pool 2.0 */ @Deprecated public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { pool.setFactory(factory); } /** * {@inheritDoc} */ @Override public String toString() { return "ErodingObjectPool{" + "factor=" + factor + ", pool=" + pool + '}'; } } /** * Decorates a keyed object pool, adding "eroding" behavior. Based on the * configured {@link #factor erosion factor}, objects returning to the pool * may be invalidated instead of being added to idle capacity. * */ private static class ErodingKeyedObjectPool implements KeyedObjectPool { /** Underlying pool */ private final KeyedObjectPool keyedPool; /** Erosion factor */ private final ErodingFactor erodingFactor; /** * Create an ErodingObjectPool wrapping the given pool using the specified erosion factor. * * @param keyedPool underlying pool * @param factor erosion factor - determines the frequency of erosion events * @see #erodingFactor */ public ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, final float factor) { this(keyedPool, new ErodingFactor(factor)); } /** * Create an ErodingObjectPool wrapping the given pool using the specified erosion factor. * * @param keyedPool underlying pool - must not be null * @param erodingFactor erosion factor - determines the frequency of erosion events * @see #factor */ protected ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, final ErodingFactor erodingFactor) { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } this.keyedPool = keyedPool; this.erodingFactor = erodingFactor; } /** * {@inheritDoc} */ public V borrowObject(final K key) throws Exception, NoSuchElementException, IllegalStateException { return keyedPool.borrowObject(key); } /** * Returns obj to the pool, unless erosion is triggered, in which * case obj is invalidated. Erosion is triggered when there are idle instances in * the pool associated with the given key and more than the configured {@link #erodingFactor erosion factor} * time has elapsed since the last returnObject activation. * * @param obj object to return or invalidate * @param key key * @see #erodingFactor */ public void returnObject(final K key, final V obj) throws Exception { boolean discard = false; final long now = System.currentTimeMillis(); final ErodingFactor factor = getErodingFactor(key); synchronized (keyedPool) { if (factor.getNextShrink() < now) { final int numIdle = numIdle(key); if (numIdle > 0) { discard = true; } factor.update(now, numIdle); } } try { if (discard) { keyedPool.invalidateObject(key, obj); } else { keyedPool.returnObject(key, obj); } } catch (Exception e) { // swallowed } } /** * Returns the total number of instances currently idle in this pool (optional operation). * Returns a negative value if this information is not available. * * @param key ignored * @return the total number of instances currently idle in this pool or a negative value if unsupported * @throws UnsupportedOperationException deprecated: when this implementation doesn't support the operation */ protected int numIdle(final K key) { return getKeyedPool().getNumIdle(); } /** * Returns the eroding factor for the given key * @param key key * @return eroding factor for the given keyed pool */ protected ErodingFactor getErodingFactor(final K key) { return erodingFactor; } /** * {@inheritDoc} */ public void invalidateObject(final K key, final V obj) { try { keyedPool.invalidateObject(key, obj); } catch (Exception e) { // swallowed } } /** * {@inheritDoc} */ public void addObject(final K key) throws Exception, IllegalStateException, UnsupportedOperationException { keyedPool.addObject(key); } /** * {@inheritDoc} */ public int getNumIdle() throws UnsupportedOperationException { return keyedPool.getNumIdle(); } /** * {@inheritDoc} */ public int getNumIdle(final K key) throws UnsupportedOperationException { return keyedPool.getNumIdle(key); } /** * {@inheritDoc} */ public int getNumActive() throws UnsupportedOperationException { return keyedPool.getNumActive(); } /** * {@inheritDoc} */ public int getNumActive(final K key) throws UnsupportedOperationException { return keyedPool.getNumActive(key); } /** * {@inheritDoc} */ public void clear() throws Exception, UnsupportedOperationException { keyedPool.clear(); } /** * {@inheritDoc} */ public void clear(final K key) throws Exception, UnsupportedOperationException { keyedPool.clear(key); } /** * {@inheritDoc} */ public void close() { try { keyedPool.close(); } catch (Exception e) { // swallowed } } /** * {@inheritDoc} * @deprecated to be removed in pool 2.0 */ @Deprecated public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { keyedPool.setFactory(factory); } /** * Returns the underlying pool * * @return the keyed pool that this ErodingKeyedObjectPool wraps */ protected KeyedObjectPool getKeyedPool() { return keyedPool; } /** * {@inheritDoc} */ @Override public String toString() { return "ErodingKeyedObjectPool{" + "erodingFactor=" + erodingFactor + ", keyedPool=" + keyedPool + '}'; } } /** * Extends ErodingKeyedObjectPool to allow erosion to take place on a per-key * basis. Timing of erosion events is tracked separately for separate keyed pools. */ private static class ErodingPerKeyKeyedObjectPool extends ErodingKeyedObjectPool { /** Erosion factor - same for all pools */ private final float factor; /** Map of ErodingFactor instances keyed on pool keys */ private final Map factors = Collections.synchronizedMap(new HashMap()); /** * Create a new ErordingPerKeyKeyedObjectPool decorating the given keyed pool with * the specified erosion factor. * @param keyedPool underlying keyed pool * @param factor erosion factor */ public ErodingPerKeyKeyedObjectPool(final KeyedObjectPool keyedPool, final float factor) { super(keyedPool, null); this.factor = factor; } /** * {@inheritDoc} */ @Override protected int numIdle(final K key) { return getKeyedPool().getNumIdle(key); } /** * {@inheritDoc} */ @Override protected ErodingFactor getErodingFactor(final K key) { ErodingFactor factor = factors.get(key); // this may result in two ErodingFactors being created for a key // since they are small and cheap this is okay. if (factor == null) { factor = new ErodingFactor(this.factor); factors.put(key, factor); } return factor; } /** * {@inheritDoc} */ @Override public String toString() { return "ErodingPerKeyKeyedObjectPool{" + "factor=" + factor + ", keyedPool=" + getKeyedPool() + '}'; } } }commons-pool-1.6-src/src/site/resources/images/pool-logo-blue.jpg100644 0 0 10640 11701070263 22304 0ustar 0 0 ÿØÿàJFIF``ÿÛC  !"$"$ÿÛCÿÀF¯"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷+ÿÚáU…ìÖ—íÊÍ ªØJ@*ÅHá}A¨?᤾ÿÐzïÿóñ5ñŒ¿äoÖëþýÕ“_D²š nÿ¯‘à¼Î²{#ï_øi?„¿ô»ÿÁ|ßüMðÒ è=uÿ‚ù¿øšø*ŠÙ4;¿ëä/í:Ý‘÷¯ü4—Â_ú]ÿà¾oþ&øi?„¿ô»ÿÁ|ßüM|EÙ4;¿ëäÚu»#ï_øi?„¿ôºÿÁ|ßüMðÒ_ è=wÿ‚ù¿øšø*Š?²hw×È?´ëvGÞ¿ðÒ è=wÿ‚ù¿øš?á¤þÿÐzëÿóñ5ðUdÐîÿ¯iÖì½᤾ÿÐzïÿóñ4ÃIü%ÿ õßþ æÿâkàª(þÉ¡Ýÿ_ þÓ­ÙzÿÃIü%ÿ õ×þ æÿâhÿ†’øKÿAë¿üÍÿÄ×ÁTQý“C»þ¾Aý§[²>õÿ†“øKÿAë¯üÍÿÄÑÿ %ð—þƒ×ø/›ÿ‰¯‚¨£û&‡wý|ƒûN·d}ëÿ %ð—þƒ×ø/›ÿ‰£þOá/ý®¿ð_7ÿ^ð—ök×üká˜|Cªkh6wh²Y'ÙIJ¡ÏÎ˹BƒÁ’sÐqŸ'ø‡á©|ã]WÃ3^Ãzú|æ#<@…q€AÁèpyàädõ8ÄœÜ#&Úþ»ÏŠ„Tågýw>Öÿ†’øKÿAë¿üÍÿÄÑÿ %ð—þƒ×ø/›ÿ‰¯‚¨­¿²hw×ÈËûN·d}ëÿ 'ð“þƒ×ø/›ÿ‰«š'Çÿ†Æ©c­Ü=ÄÛ¶±™A–<íô¿?«¬øGÿ%Lÿ¶¿ú%êe•QQnïúùʳ’VFOŒ¿änÖì!?þŒjÉ­oÈ߬ÿØBýÕ“^¤vG›-ØQEÄv >x»âóÛøoNÅ =Ôϲr ›×Ž€í_Jø'öNðÝŽk·º´ÊÛ½ ð‘ò“ËžsÈ+ÛŠðŸülñO¾ÏáO ÚéÖ5ËÎÚ‹tÃr€x?)a´`xÅ}å=òè¾}KT¸%llL×2Ë…'be™»„טWÄSi'dö¶ç­£Bjí]­û-y7ì½àkƒ£]Ûxi§‚GYìäÔ]2»í‚Iãž8®ïJð?ÁÏi }£ø[Â:…Œ™A=œ du£‚?1_Ÿ…ÍÞ±¬Ü^J­5ÝõÃJÁbò;@êI$ûšû¿öYð&¥à†& uÄwÚÉ¿š1öe(ªvr} Çlœñ´=„½£æõ4ÂWöÓqä\¾‡ÎµOÂ='áÆ¡¦j~’q¥jfD6ó>óo"m8 NæV ß$m9'#!^ËûY|G³ñçŽá³Ñ§KEG‚ —•šV#Ìu=Ôí@}¹èkOàGìïªxÞÎx¢{A™wÛ¤jÍґîàB'Bƒ¸t!«Ñ¥YÑÃÆUÞ§ZJ­w+CÁ诧> ~É÷¶67º‡ƒüDÚ‰‰Lé÷p•À*%Sµ˜ó•GAžõó4±É ¯¨ÑÈŒUц ‘ÔØÖÔqë+ÁÜÆ­ ”]¦¬2ŠÝð/„µïøŽ ö/wy/Ì{$H1™º*ŒŽ}H$€~œ‡öFÑÛÃQG7‹¯ã×zË:Û£ÚŽz¸~œg^p:TÖÅÒ Ò›*Ž­dÜò5lx#EoøÇFÐÍÚ7ÐÛ3F¹eWp‡ÐyãŠê~4ü(×þêð[ê2Ç}§Ý‚mo¡B¨äuFî¸àã'‚0O8é¿c=!5OŽw.Ì™e=à¡8 û~÷?€§:ñö.¤]Õ… 2öªœ–·>Ðñ~±eàÏj:ËE¶×I±i$gbáv8ë_š•íΣ¨Üê²™®®¦y¦€ »Ìxã’M}³ûnk-§|M5'UÔa¹Æ3)>ÿ2(ükáêáÊiÚ››Ý³·3©zŠ‚Š(¯TóºÏ„òPôÏûkÿ¢^¹:ë>ÿÉCÓ?í¯þ‰zšŸ .ŸÄŒŸÈݬÿØBýÕ“ZÞ2ÿ‘¿Yÿ°„ÿú1«&œvDËvQE1¯À­ø‡âÿ…ô¾ 6 “H î"ýëŒ{ª_w|gÐ5ß|<Ô<5áëˆmnµ#¼—± %Á”ð 9PW®îÝG…~ÁÞÒ%¶×|W$r¾­ ¢Æ6o¹Lªço«9=€ÆNzÿÚsãv¥ðçPµð燬í%Ôî­>Ò÷3å…º—*¸AÁ'ku<`ps^.S­ŠP¦µü9ìác Xg9½gÀß ~|ÒÏŠüI©Cs¨Û!'Q½ùDg+ C?1ÇÜü8¯øûûBê>5·¹ðß…£›Lðü„¤Ó1ÅÅêw ¸‡Ÿ”HêpJ׎ø³Å!ñf¦u/ê÷z•ÑèÓ>BEQÂŽ:QÒ,.5]ZÏL´Ü^NDBîÁGêEwRÁ¥/iYóKðG\]ãìé.Xþ,÷/Ù7á~2ÕŠüKddðý„€[Ã*ü—ÓÄiÆGF$/ 0¯Jý«>6ÞøVàx'Á× TƲ__!RmTò± í!’G F99_]‚ßKøWð…ÒÖÖ~ÒÞM£Ì襘œ`nwÉ'ŽZ¿>¬­üAãïGn¯.¡­ë7Ÿ3°'s¹åŽÑò¨'  öÉBغҫ?†;5¯…¤©Câ–çèÀ½KPÖ>x_QÕ&–{É´ôóe•‹<„|¡˜’I$I=IÍ|=ñSH“[øõâ=Ãow=Ö·<0A9iL‡xç Ý»ž€ ô¯¶üK«é_~$ÒÈg‡DÓ¢´µGm­s* H×Áf$N0+Á¿b ¾½â½{âF²EÍÔ2´0;“q/Ï,˜Çk1ޏ¬p•=’«_§C\T=£§G¯S×¼០|øQy¨^º<ÐÃöRñ@]ÊËn#Œ¨¹'=YyWìÿñsÆ?>?Èu·‹IžÊãÊÓ#b`·Q´©í¹þP7·÷›§íÛâû—ÕôZÏ"ZÅÛïHÛ+³Œÿ(V8éóƒÉaOÝ%Æ«ãÛ´’8#§Ø† rÊÒ¸È䪠ƒŒïª•4°Ò¯WYHN£xˆÑ§¤bvŸ·²ÿ…;l× yãW„Zžs¿d™éþÎî¼~8®3öÐyñ7‰ä†3þªÂ 9Ü:É"ýîáX?¶çbÖ|Sgà:Pöº93^²C\°áz õrÊ×¶þÈÞþÁø!¥K%¹†çT’KùlîÞvÆÝxÌiÇ¿®iJôp ?´ÇUƶºCû{ë)7ˆ¼5áøæmÖ¶²ÝË?/ï*ïû¦úïÏÌ•ê?µV«.«ñ×Ä%ä/£Çk##PGýõ¸þ5åÕêàáÉB+Èó1sç­'æQEtœá]gÂ?ù(zgýµÿÑ/\uŸÿä¡éŸö×ÿD½MO…—OâFOŒ¿äoÖì!?þŒjÉ­oÈݬÿØBýÕ“N;"e» (¢˜»¿c-& ?àuìK‰5;»‹™Nz•Â?H…|åû`kvz߯«Ï°ÞCw¬VlÑ…uÜ]sÐÌAô*×5+fÆa»Ô%•GÊÌGQšÂ®zX§¶—2[.†õ1Ë_e7»êXE»Ôõ%]Ïqwu67;夑Rǹ'©¯Óéö~𕆖¯6z]ŒpofªF€d“ì2I¯Ëúß½ñ§Œo´ÖÓ/|Y¯\زíkiµ^"= Æ? Ó„xžT’3Âb–í«¶CãN-kÆÚÿR¸¹BF W‘˜~†±¨¢»’²±ÈÝÝŠ( A]gÂ?ù(zgýµÿÑ/\uŸÿä¡éŸö×ÿD½MO…—OâGQâ¿…>"›Å¬Ëy¥{Ù˜$™Ár¹YŸð©|Gÿ?ºOýý“ÿˆ¢ŠÆ3•‘rŠ»øT¾#ÿŸÝ'þþÉÿÄQÿ —Äóû¤ÿßÙ?øŠ(§Ï!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*øT¾#ÿŸÝ'þþÉÿÄQÿ —Äóû¤ÿßÙ?øŠ(£žAʃþ/ˆÿç÷Iÿ¿²ñÂ¥ñüþé?÷öOþ"Š(çr ÿ…Kâ?ùýÒïìŸüEt¿ >ø‚ÓÇ:uÄ—šYDórY3ÌN?¹ïEœ¹YT⹑ÿÙcommons-pool-1.6-src/src/site/resources/images/pool-logo-white.png100644 0 0 26722 11701070263 22511 0ustar 0 0 ‰PNG  IHDRæQÆ¥ÚvbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ^ňV IDATxœí]ypUUÒÿ½,05K•²d!PóU©€ ›È@qÁ…e@âˆ"ŽÊ¸[ ŠÒÒQK@ÄÁbQ1 EÙ"«€¬ƒ,aÉ‚ É{y9ߨ׾}ûÜ÷‚úóÍëª[ï½ûnŸÓ§Oÿºû,÷Þ€1Æ Ä/¯!«‹@ëû-ÕA<ÑÖ!yýøüþ«©¬Úõ—#³xYZ¹²þËíÏhdþ9º±•ÿkÚŸîÑsãÆÎAÔ¨Q#´oß™™™HKKóê©ìÇßZc6n܈cÇŽañâÅ®ÿ233‘™™‰öíÛ»Ê÷k M¡ÇÇ¢E‹Ð¡CdffzÊÛ´i6n܈M›69mÌÎÎvÕm£÷Þ{›7oƱcÇ\¼™™™ÖŽ“òJ¹7mÚ„Å‹c„ jÛ/^ŒM›69ufff"''ÇÓš6oÞìÒ5ñ6lØ0*ymýKå“I6hذ¡SO$Ó‹zÒMNNŽÓ—T&Ùõ#dgg#'''b}~6$õ 999èСƒ£ó#F`„ Vçí÷Ûùn"ÐĉMÆ ß#;;Û:tÈTVVZ`0h‚Á  …B¦ªªÊ„Ãa‡Í„ ¢ª£aÆ&77·ÆõTUU™… šœœ§¬… šªª* …L04ëׯ7íÛ··Öݾ}{sðàAsñâEÏñÒK/ùÊO¼.¾ŠŠ SQQá’; ™Ã‡› &˜ÌÌL§ ’•ä?~¼oC‡õÔwñâEsàÀ3tèP_=/š¬\^Þ—_|ñ…KîH6³nÝ:SYYéªOëOj{AA6l˜«íï¼óŽ£—ýë_&77×׆æÏŸïÑ‹­/¨}Çw•‘““crrr\mÍÎÎvl(Z»$½…ÃaS]]mª««1ÆX¹qãFWã‡n :tÈdgg{>oÞ[¤  ·mÛÖ¬\¹Ò|ûí·Neee¦¬¬Ì|õÕWjÛÞxã ÀôìÙÓšÓ§O;GII‰)--5;wî4 4ððòkOŸ>mJKK=qÚä4hÙ½{·9sæŒGÞçŸÞÃ÷øã›ž={fôèѪ¬¥¥¥fÖ¬Y*¯v}yy¹£ã½{÷º ²OŸ>®˜÷çÙ³g¾œ3gŽªÛ¯¾úÊÓŸ0šƒ¦ú³²²Ì®]»”––š’’SRRbÚ´iãá{ã7|Û·jÕ*çÚvíÚ9ÑO³Ó³gϺ®×š=¨§kògãÆèر#ýÄ7ß|ƒ ÀƒêêjTWW;ßéóرchÑ¢$Íœ9={öðÓDA @aa!ºvíê\×®];¬^½ÚùýczíT­ZµÂ‰'Ôºø„D\\âââè\èÊ+¯L”2öêÕ ³gÏVÛF4zôhÌœ9ÓÓ¾=z`Ú´iÎoÞF’aæÌ™=z´‹/??­[·v~“Œ$o||<òóóñðÃ{êœ={6îºë.¬\Þ¶mÛzôÓ¦MC=|å½ë®»°mÛ6çšÔÔTlÙ²ÅÃÃemÙ²%Š‹‹köïßïL‚Hå÷‘#Gâõ×_wÉÙ³gOÌœ9Ó%Õ¬º™5kzöìé²U’ÁƒÂÂBôêÕËÅÃû×Aí5j¦OŸÈÊʼyó<6JuÀC=„¥K—¢´´ÔU—Ôÿ.@1cð׿þÕ)hذa(Ãá0ª««‡QUU…ªª*„B!„B!$''ãúë¯÷(ªE‹ƒ®# áÿø‡ëºÇÜ)“¡PÁ`ÐUW(rÅé¹çžC0Dee%*++^ª3 ÆKž6mÚ`æÌ™ÎuÄË¿WVVâŽ;îðÔתU+Lš4 Ö£²²RuXGŽq•O×r¹Ãá°‡ïùçŸG=\òJY+**\Nè©§žB—.]T¹ ­Zµrñ×Q0ÄÔ©S] ÌÊÊBrr²µ?é ~yöÙg‘ššêªsÙ²eØ´i“«.ΣéfôèÑèÖ­›ªj[zz:RRR\|Û¶mSû‚êâ3¯[·nuÚÂq@m«ªªB0tœ·?MápØÁ•t"æ¤I“püøqGììlŒÕÕÕª ¤èiÓ¦¹>UUUhÑ¢>úè#çÚ‘#G¢ºº>ú¨+eæC!c òòò=È¡•Ïë$¹xšœ`ŒÁñãÇ] ±íÛ·w*£†Òy•àIJJBUU•'ÿ&V¬XáR E-^’+–+øŽ;îðsçήN“à”DࢶQ;egÚ€ ]iW>¨$c ‚Á K/@ ÎaÓ&¯ ˜äÑ90ä˜ÇLª—ä¥k¹ÁQäâzŠÔŸÍ›7GJJ N:å*kÛ¶m¸ýöÛ=²ÚtCÑÔÌ@  f"\^Ì„„téÒ/¾ø¢ëúQ£FaéÒ¥xæ™gвeKµ…B®þ• ¤úx½3 °aÃWåiii*(98¥·&eËÁ0ý.))ñ(¥ººÚe ¶»l„–r@aa!š5kæ1"® ^7@ô)댘θàG0ÆÇÇ;Ÿ¶6sðÇÅŹ¼}¤ˆÉÁÉ_^n<2BØ —x‰ˆG ¸}È ÊˆB縬T^‹-<åíØ±7ß|³«/âââ\²QËIºáõh“÷é„2—:uê ÿþ˜7ož‹§°°}úôA«V­0qâD$%%¹Ú¨MZÅÇÇ{Ú¢á†(6oÞ쪘Ò2žkVÉKç8x·oßîQ ¥¼D6ÀSC¸ò’““qúôiWy'Nœ@“&M<|~““×)êñìë€:5>>^5â•íKHHpÎÙ¢‚«P_ð¶j¼4‘Ž„!9/ÉNú/**ò\kË~¸£Öfƒ“““=e:uÊ ¯7Úl‚Û¨‚äuMºü¨’=77§NÂÊ•+=¼;vì@—.]Я_?Üwß}HJJrþ³ iÈAðC“-Áãš}"¥Úfž¤1ÊimN”3Ûˆwº–«K¥ò¶lÙŸ~ú©Gn®h´ºi–OF ^¯ÆK†Æ—Kòj“G®9&³éŠ”×M²j΀?¤#©®®vÆ·6^ ÐQÄ”C žM´lÙÒ•H`~©,–¼¤Í异–VŽ;ÉÉɘ?¾Úî·ß~+W®Ä=÷܃¾}ûz²5-rË$3O¯ÕáÒÔ°Œ˜rvIæñÚ˜E®ÛHZ¹r¥Z¾Œ ZZ¢ÉÍg%‘¡k3f¶ze]dÚä˜f蜗§Ð²n›¼rÊ^›ðˆ$«×&¯6ß ÑÇìY"³¥ßl6â²òå3IápØ×~4G¨µ×'ÜÜ\Ì™3GîPRR‚)S¦ ++ ÅÅŬH9´ô•ú øq¹DþY\\l˜Ú›ÌÇ,4€Ž·FMù𩆠èIIIžhOåH¢èª¹¹ýH¦lÑðʈ ÐR6mÎ,žÕhÑÌÏh‰Ÿ;Íq?E.mýZê—Ë¥ÙFrr²ÇÑÒ¡éÆæh¸ð#Ù²¼p8ŒŒŒ ,_¾Ç·–SZZŠbÕªU*^xÖ"ǘœt´X²d‰gŒi‹–¤d>íÏgЭ[7µž•+Wª^JS0Õcó²c·u&72­##ª&G´@–@‘É66•Æ#'WlzÑÆu?WÞN:y®[»v­šýða´[Ò°Œd~©ºÌXdû´zdÛ¨<®kž=…ÃaôíÛùùùèÛ·¯ª¯ÒÒRL›6 'OžT41΃ììlÏ3gÎTS,-br(wíÚ…„„$&&"11 ž°k×.5ŲMVðYONÍ›7÷DžfJ"%ók£5à§Á½ß5‘ Ë"ÇcÉÿ5`ùÕé'«—·“{ø:uêx®Ý½{·'ó± üúðïOIrL×DãÌefs€²ÜúõëcРAÈËËCçÎ=å–––"//O 6;¶ô6¸tóª¤ÂÂBlÛ¶Í3¢ï2G&%ÇÅÅaÅŠ¾§š¨¬¬Ì‰~c,Yî'Ÿ|â*§E‹HII±êǦ›£òsJ¶ÉKc Ƈ÷Þ{Ï·üúõëãÙgŸÅÓO?í){ݺuj&iÜ ü1Û·o¯Þñž››‹'Nx@£…¨Q;vìÀÀ1cÆ 0ù&j¢¢¢"¹@b–êÑÖÐn¿ývÕûù¥ ~ Àj¬r’‹_¡s@Ky"MiMäæ2Éé{Í0¹¬|©Šèšk®Aݺu=×ðÁêøÌ6öÖúóŽ;îðÈÄ£µ$p¸¼¶9>¢épÏž=j¹òèܹ3²²²\¼eeeêD’6{,³CGÚ!C†x„>uê&Nœˆ“'OZÇ6\ÙÛ·oÇÀqýõ×£M›6®)ãøøx´iÓ×]w§žÏ>ûL¦N-ZþíoCjjª ê¸hˆwJ4©¬-bÚ:Y–k»¦&òjA»NîH’ߣ‘WÊø—¿üÅs}AAAD;átêÔ)×wJJ xàÓóKÁI›ì5éIëׯ÷\x‡2@½{÷öðˉH-“©N* \¦5W­Z…Ç{ »ví²¦šÕÕÕ˜3grrrpòäI¼þúëžôŠŽ×^{ÍSG^^ž³3Hz?éIŒ1®íx©©©xê©§¬Àˆ¦S¥âmÑE^c«Ë/I~NÑÒV–_}2Í•rÛ"Š_›zôèÆ»®///ÇÒ¥KU`Jðl­üç?ÿ©‚²&}XSÝD*ñâÅjŸóÉθ¸8×hÒ¤‰:«ì7ÉI‡k¹d̘1ª`%%%2dúõë‡×_Ÿþ9Ö®]‹5kÖ`Ò¤I¸óÎ;ñÒK/^{í5¤¦¦Z=Xƒ 0yòdÏ/¼ð‚ó]NÈðssçÎu6O§¦¦:›ïýÀá§tÍèdäÔÈ~õF Þh(šúøuܨäùË5ÞáÇ{RÚ7ß|eeežI5yœ:uÊÌ)S¦àºë®³¶+Z5¯¦I‹/FII‰l88Ïœ9ãâëØ±£gv×/­åNËå&³²²ðÆo¨Â—ræ%K–`ìØ±xá…0jÔ(,\¸ÐÙ7iÒ$tíÚ5âZ`÷îÝñÊ+¯¸Î}ýõ×7nœó[FMc >ùäǤ¦¦bñâÅHMMU +O*ŒÈ ôŸ¼á€ºM–a3„Ó§Oû‚Ñ£ÖéG¼ eeeª¼6ä(“±]W·n]Œ;ÖÎgžyååå¼Yò¾ûîs®Ÿ:u*ºwﮎåx_R™œ´!ŒÐÝ»w׸}À¥Ö©S§z¢&EJæ|àðtêÔÉ5æäÙŸ-ëôŒ1¹P½zõrÝ™ %%%áÅ_Äm·Ý¦z­cºvíŠyóæ¹ÂAA €¥K—º:uíÚµxä‘Gðä“O¸t£r^^RRRÔÉÎøøxÏ&}ª«¼¼Ü7Ò|öÙgÞ’’¬]»6b„ÍËËóð©ú9Éq Ïmy¶(¿víZïš5k| Îiò®Y³ÆWÖ@ €ºuëbܸqèСƒs¾¼¼ļyó°ÿ~—úr÷îݘÝyè7Þˆ§Ÿ~Ú¹ŽÈ÷Cü&¡PÈÐZíܨ¬¬ÄáÇ1xð`|õÕW¾ggg£oß¾hذ!jÕª…Zµj9ë– )߸ ñÖ[oaáÂ…#EóæÍñÄOàúë¯w¼5„ß$ …°jÕ*”””`ݺuØ»w¯Z^½zõдiStìØÑ5ËxðàAìß¿_|ñ¾þúk«<7Ýtn¸áÔ©SW_}5`ß¾}8pà ¬¼III¸é¦›Ð¸qcÔ©SW\qöíÛ‡}ûöá‹/¾P£¤§§£iÓ¦hܸ±“&—î:pàÖ¯_oÕaRR:wîŒÆ£qãÆ¸òÊ+\zœÌþýû}y322йsg\y啸ꪫpÅW8VF§}ûöaöìÙm”””„þýûãá‡vl… “¶SRîܹEEExÿý÷­º©W¯:vìˆÆ;¢¼¼Ć PPP`•%==7Þx#:vìè´-`üøñ(//GRRâââ''';7]c°jÕ*§Mwß}7úôéãà‰/Q«V-üîw¿s?ªKrÍÑÜ/^Ä7ß|ƒmÛ¶aõêÕNtª[·.7nŒÎ;#!!Á)¬víÚ® â©ÓÈ´ú‚Á vî܉]»v¹ :..7ß|3Z¶l‰F¹€OeÊ-}Á`#GŽôÌæòOÁ{õê…k®¹À¥Ç[ìß¿ß:3(g›4i‚»îº Æ,]ºûöí‹ÈKŸ”üü|G>-8qÞ'žxÂiÛøñã]^œ—¡M¤ñ¶Ö”·gÏž¸úê«]ÀÔÖOKJJGÃËÌÈÈ@‹-кukW_’'ÇÍûrÁ‚ؽ{·ïä—uĈ0ÆàÀX¶l™uß¶lé…ê9pàRRRРAGÖ={ö ´´»vír–y’’’ЬY3ÜrË-꺿Ôa¦víÚ(k×®í.`r㦨yñâEçñô¸þÜòœ\Ùä eÇñ9òñr y˜„„Gh*›Ìóv¾ÛÄ•³ €hr®¼øøxW›ÈÉHG@{Aù.(¾ã‰gÜ)ÉçØ¯¶Ï˜ˆO8)Oà§ÝV$+ç¥vjSõ¤_Ò'µ—œ)µ•Ëʷב^%¨¹±q9)2ÐÁÛÉë”%¶5Lî$¹l²NÒ9^oÕC¶'íZ>vÔ6ÊH;$} 5`&Øfš8èä£/\¹p à¡)‹§´rüFçùõ¼ ºNóŠÕÕÕ®Îä×ó6p°qOÉ¿Óõ¼C%mãIm’!Ò„Š¯ü~óöi¼ZÙ¶ß²Úo?Yåd‹\¤—À”‘U:GÙN™"Ëá—•ƒ€çV;žyØÚ,õÎë†lKMT¦Lg%´¾LàÉA­÷7Êhú‘ˆÏ|d?iÑ•ôÂu#o?ä:¥L‰Ú íÐf¼N:.?·snË[\\7 š < åÀäÞOŽs¸’ù! Ÿ7P¦štžRfî #E~6á£u¦$96‘g •ÇÏK€ðNㆠKzTî wÖÁÏqG"³ ’™ˆœ)Ô¼·Ló¹^嘘ë‹+Õ#‡ rü,û€ëq+²©L²?Þ×ÜVµèÄõ&ûŒ×cã•Y‡tø<èH½K`J€’þ¸’µˆ™˜˜¨n ¨Æ.fóØrð,# 4kã>Î/;W’”…R.“ô|~"ǧ$›L½ùøœOTiŽENø¥†RVâÑ:™÷­Œ.‘<8祶jU¶U:05m}MF$õGe‡Ãa—íHç,çJxĤa–­/´y?Yyô”N‰Û£¦t¨ \(™²H´s¥j³ƒŸj¦ß<"²åúÒøm‘Êæ^J[o"'#Óhn9!FuñN”¼Ü€4ç£9º&#!!Áã…5pp>ÞV™ZimåÀŒ–WK…ù¡9y5g«ãúàíç+Z_ʈNíÓúBê•ø5`Jòrl™‚¼û‘Þ“ -Ã|4ÀÔŒ„Wî—òÐX†—+•Å (%(xgÈÕ¢L½ÉX‰‡OpICÐxy;¹ãÑ:OÊN©—tV¼. jéŒlYo+×1?ɬ­ Ë1¦ä—ãÍhûRꀘëƒÀIíãcSÙ>^õ¥£g›y´ñ¿äåm’iäåFÀë‘NŒÚ-SKéH$/9h͉Èvjã/™ÆÊ”Vö£(µ>àÙÙŒ_HPÙú‚÷ƒ<¸Œ¼í;' ìò“þwRY®(:ÇA)#&u– ˜Ò ËIéý¨A(dø¶´@~ÚRXN¼îl _v¦4r®;. }§küxm†*Z’–f|š“#^)«t˜6ÉûÚ¦+í ÿ$y¹~)®Ì~¸“ŒÔ—6ú¥Ú\Ív¥ùeÒ‘ÊHl˜T¹ôâT¨–ÚØ<¸-ÍÒŒ‡ê—eK…IÒÀèLîiy$¡ÿµ6kÊçrIC 2lQ[F­ù§ôÈšÙ꼑‹ÊáòÚ"ŠÆ'e”N‘ÎKýØ o‹”C+[‚I‚’·OêHsZ~ýÃ.Ý‹¼eËÌ™3Ç·O¥#ÔœF/X‹œÒkqƒÖ¢™ÖY 5ÃãeÓµ‘:T–¥u'é|(2ÛÂA)Ab“-Rúñòz4Ùùg¤ú¤G§>“eD+ï–-[\¯j$ÒtÄëÈÊÊòD`ig~˜š-FŠXZÛ¢éGÍnK7xów…òYmj'»¤tþ®ˆÉOjž†/˜jJŽÔ ÍëðjËOiRf›ò¥¡,Ô~¿r5Ò¢¯3`J^)³fè~²^®¼ÑðÒ¦¸¸ØóÒÚh(++ ƒ B›6mf”÷ÕjÀ¤ˆI‡ÜÃlŒÁ—_~‰?ü'Ožt®ËÎÎFff&5j1­Õ@yüøq,Z´›6mrÎeff¢C‡ÈÌÌôµåí—mÒÆ”Úl<9"úä(ªÉŸÅHR4cLù4ÀP(„]»v¹xºtéâzJ"=K–¾ççç£mÛ¶èÑ£¶nÝ c Ž?Ž÷ßýúõÃUW]…#FàèÑ£®‰"9Ä7·;v :uŸÿüg¼ú꫎,‹/ƈ#ЩS'tìØ7nŒ8¥¥²¶Iùä?.“çÆ„_¸¿bô_LšAîܹÓóúôôtÏ#Lé6l† c Þ{ï=,Y²3gÎÄŠ+°{÷n´k×0yòdtîÜGޱ‰Ž¼¼<üÏÿü6mÚ„ñãÇãðáÃX°`,X€ÊÊJäææ6oÞŒo¼‹-RÁ®=‹ëA^ÏÓzJí9Z±ˆ£_œ¸±É—µ>÷Üs®kéÉå2†B!Lœ8+W®Lœ8Íš5sEœ””|òÉ'Îî¡ââbÜrË-8zô¨ †p8Œ 68†Š!C†x€;nÜ8×+)ï¿ÿ~,Z´È,Þ.™ÊÊHÍydT·-—Ä€£“mr„§eÜ0OŸ>Áƒ»^ÁP¿~}L:U5Þ;wbáÂ…€fÍš!==Ýú»Y³f9e£ÿþÖòþûïw®ðÀ8r䈚ŽjÀäÀ“ÔÖ0I§±1fŒ~Ù–fÍš…ÜÜ\|úé§XµjV¯^iÓ¦áÞ{ïu½ö"==S¦LA½zõ<+»Þ¡zÏ=÷¨ £ÈÚªU+´iÓÆ¹~ëÖ­˜2eŠ+=…B˜ àü˜>}ºó»uëÖ…B.#Áñè£âÙgŸuþÿòË/qäÈgƒ>' ˜rœKë¿‘v1Å€£_Œºuë†[o½Õy×|7 à~2v¿íºuë\eRT¥´“¯W0»víêâÙ¶mB¡†ÂÂBœ8qÂù?))ɵvJåÉ ˜=z`ùòåß–-[н{wO»ùëA¸)£¤v{šÐX*£_üR5ú_’|u¡¶ÂSZJJŠ‹/??ßYzÙºu«ë?âã‡63œœœìâ[¶l™:{¬S›¶-1i‹˜1úÕHF ¾È/÷™Òwí]¦|â„Êà7»´lÙÒy-ðÓ.$Î-D.^/——ˆÞÉÿ…B®k)=å$—R¤´º$Å€£_•´ÉAIÀ²¹ø4‰ü4ÆäüœøR†ü/ ¡¢¢Â÷N™@ à;cœ×ôñ2eÄ”Ë"Ü1ùé(¶Á Fÿç$Á!o«²=bã믿vMøÐú¨ÜÄ Ë¯_¿¾u9cûöíÎ;`åN#žÖJ`&%%¹êæ3³œ¨N푟‘&}ˆbÀŒÑ/N¶ôˆG*~{WBB222\×–••9€%#×¶ÜÉ:š5kæ€(==ÝõßÉ“'`òÃör^^&w ~ xÔŒv|Í)ÌýŸ’¼½‹€Iw’4oÞÜuýÚµk=ã@L™ˆºtéâœÓ€ùÙgŸ9‘R‹–|˧.]ºX·çqÒ&}4púQ ˜1úÕIŽ'm LLLtíÎ.³¼¼Üµ¬¡mk[½zµÃCÛîèšk¯½ÖÎwß}׳ oµ ‡ÃXµj•«L™Ø¢µ¶™€øø§Å€£_œ´ÙVùT{ÊÄÄD$&&¢V­ZhÔ¨ú÷ïï*oÍš5êÓÝÉøùllóæÍ¨Ë¯{ì±Ç\e®[·Î•¶j5áîï½÷^ÐäŽN¶hYŠ3F¿ i3žüÞCù¸Zµj9}衇\ë’¯¾ú*JJJ<›è }µ0vìX—tMÓ¦Mqà 78ç÷îÝ‹>øÀµ_–§°EEE(**äææzÖ4yùÚ¹š¬ÝjfŒ.›Þÿ}×ï>úÈõÛ6žä“=FŠ˜5óòò\à|ä‘GPVVæ‘aÍš50ÇŽk<õÔSèÔ©“ó{öìÙX¿~½+VWWãôéÓÎ0·Þz«“Û–;øæ|ž[Û.‡âG5êg—£ÿ*:~ü8{ì1Ï.ƒâü£3#ÊŸ\@O&ˆw111Ñ(3ÜŸþô'tíÚÛ·oÇ©S§pþüy¼óÎ;¸páΟ?ÇcüøñÈËËCRR&Mš„:øî5Æ S§N¸páöíÛذa¶oߎßÿþ÷8zô(>ýôSŒ3.\ÀàÁƒ‘››k}ÏìÞ½Ó§OÇ… œÿKKK‘‘‘?üáÎ9þtÛë)ù;~|ø£qzå•W°qãFîñ›v›Suu5²³³Ñ¤IgÇ`íÚµQ«V-Ô®]Û'+• …°lÙ2|üñÇÎý™À¥uÊŒŒ Ü|ó͸í¶Û\oÌ"ùø=¡rü¸wï^`Æ ®H|à 7 ##·Þz+RSS]ïsåå†Ãa<óÌ3Î9222p÷Ýwp?dŒ2ƒÚµk»tA*>>>ÌEOr§ªª ¨¬¬t6°Ó2EN&¥¬d”ôÛ˜4kZYYéyŽŽœåå;ø†Lmïª|l¦Œfr|+Ÿe QidùœbÀŒÑÏ"i¸üÉoô˜Fùô;ùIÑI{N,E%húŸG«hÄ#©mƒG_>¶ä@"¿7ÅÞ]OÚk)¥¼D1`Æè!H!ŠÀ)'9l/3æÑ‡€D¼<å×J§@¼2Ú–2´È¦EP~ ç£ótN–-S¤èfŒ~i©+ˆ\À” ”Ÿ|Ã:ñÚ^3/ïÜÑ‘øù^[ 4üàK<‘À£¥Ò¼LÞúŸG~ vþfŒ.›l[í(ºÑ|œÇ'U´ˆID –åI`òÇvh†NTÓ²]~cN-•àäí’ãlY~ ð3ß]£ÿ^Ò"%i¢ð¾J'y¤”é¢1Æõz:™ÆÅÅyîÔ€c{RY¶Ck£ß9þ©mÝ£ÿåÏþSRYÃŽøׯèßD2…• ¤ÙUžÆñ¨é7>¤±¥V'YK¹\~QŽƒ/}øÍøF*/OK“¹ƒâNIFÍß20?ÀOm!ü 4F-²‘ÒK8xýÒYâàJmeÝñññêã;4ù¨, RÀ»!^K?kZ&•+o¦ë´TV¶ÿ· LNRóãg±(úo!Š <ÊɵBºŽ"(‘¼)Z%ŸÀÑ"&Õ‡=³¬ò:ÛAÿzÚ©¥Î¼L’3Ò˜Vº\Žá™×à 0‰¨õ1Pþˆ§j2•×Qš)×ñäfvm¹„_OcM^ßId{úœ”Ñ–ÚjãK$™Òòöi€åeÊò©M<¥• ¤Ïÿ4`Æè7D6`òõHiØ2bHƒ”  ð:øš¤íáɑƃœ"ME[®,O~—ü¶ñ%ðŸ1cô žÎRdäÀ¡ÔVŽÕ¸AjŸÚX§ËÀOŒ¦kå8NÖ%SM?`òï~ejß%I~mæ˜@Ißy9ÿ NªßPIEND®B`‚commons-pool-1.6-src/src/site/resources/images/pool-logo-white.xcf100644 0 0 51314 11701070263 22500 0ustar 0 0 gimp xcf fileæQBBD/ gimp-commentCreated with The GIMP¦Ñž'ÆPéMPoolÿ     ‹&BOMgÅM{»€€€?þ8U U1û8Uqâÿ ÿýª8/þÿÿøqâÿÿýÆ.þÆÿÿþUþªÿÿýâ-þªÿÿþUþÆÿÿþâ-þªÿÿþUþ8ÿÿþq,þªÿÿþUÿþÆ,þªÿÿþUþªÿÿ-þªÿÿþUþªÿÿ-þªÿÿþUþªÿÿý8ªªýU ýqªªýq8þªÿÿþUþâÿÿþªùUâÿƪÆÿÿýùÆÿ⪪ÿÿýÆ8þªÿÿþUþ8ÿÿþqûªÿâ8ùÆÿÿâûUÿÿqþÿÿþUþªÿÿþUþâÿÿþâûÿÿ8úâÿÿâû8ÿÿþÿÿþUþªÿÿþUýÆÿÿýâû8ÿÿÆþ8ÿÿþÆûâÿÿþâÿÿþþªÿÿýƪUUþÿÿýÆûÆÿÿUþÆÿÿþqûqÿÿªþqÿÿþÆþªÿÿªþÆÿÿüÆ8þ8ÿÿþþUÿÿþÆûâÿÿqÿþªÿÿþUþÿÿ ÿþ8ÿÿþUþªÿÿþªÿÿþUþÆÿÿ þâÿÿûUqÿÿþUþÿÿþªÿÿþUÿ þªÿÿûUªÿÿþUþUÿÿþªÿÿþUÿ þªÿÿûUªÿÿþUþUÿÿþªÿÿþUÿþ8þªÿÿû8ªÿÿþþUÿÿþªÿÿþUþÆÿÿþUþªÿÿþqÿÿþªþUÿÿþªÿÿþUþÿÿþªûªÿÿªþ8ÿÿþUÿÿþªÿÿþUþÿÿþÿþ8þÆÿÿþqûªÿÿþªÿÿþUþÿÿþqûÿÿÆþ8ÿÿþÆûÆÿÿþªÿÿþUýâÿÿþûÿÿþªÿÿþqû8ÿÿqÿþªùâÿÿâûUÿÿUþªÿÿþUûâÿªýªÿÿþqýÆÿÿøUUÆÿâ8þÿÿøÆUUÿÿqþqª ªþ8ýUªÿÿüâªU ü8âÿÿüªq†††ý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ÿÿþqÿÿþý8âÿÿýªªq&k<Drop-Shadow#2Ì     „D{k<“’k<§ÊT3* &ø"ù  ôô   ó ò ð ó í Ú  !"!!  Û  $&()*))('&$#"  ð !&+.022ë10/.,+*(%" ð !'-269::ê98654320-*&! Ø &-39=@BBA@?=<<;:852-(" ð ")18?DGHHèFECCBBA@=:5/)# þë $-5=DIMNNMKJHHðGEA<60)"    ýûë &/8@HMQRRQOMLLîMNMKHC=6/(!ó  × (1;CKQTVVTRPOOPQRRQNIC<4-&!õ × (271,(%#!!ø ýÙ  *4>HPVZ[[YWUSTUWYZZXTOIB<61-*(''ò(''&$#!  Ù  *4>HQW[\\ZWUTTUWYZZXUQKE@:630/--./.ú,+)('&&þ'Ê  *4?IRX\^][XVTTUVXYYWUQLGC>;86433233455654320/..þ/Ø  *4?IRY]^^\YVTSSTUVVUSPMIEB?=;9877ó89:<<==<;98877ê  *4?IRY]_^\YUSQQðRSSRPNLIGECA@>=;;ú<=?ACDDøCBA@@??ç  *5@JSZ^_^\XUQONMNNáMLKJIHGFEDB@?>>?@CEHJKLLKJIHGFç  *5@JSZ^_^[WSOLJIHHIéHGECA@@ACEILOQRSSRQPOMÍ  *5@JSZ]_]ZUPLHECBAABBDEGHJKKJHECAABDGKOSVXYYûXWUSÝ  *5?JRY]]\XSMHC?=;::;=?BEHJLLëJGDBABDHLQUY\^__^][XÆ  *5?IRX\\ZVPIC>9643357:>CGJMNMKHECBBDHMRW[_abcba_\Æ  *4?IQWZZXSLE>83/-,-.16;@EJMNNLIFCBBDHMRW\`bdedca^Æ  *4?HPVYYUPIA:3.)'&&),17=CHLNNMJGDBBDGLQV[_bdeedb_Ë  *4>GOTWVSME=5.($! !#'-3:AGKNNMJGDBBCFKPUY]`bccýa_Ë  )3=FNSUTPJB91*#"(/6>DILMLJGECBCFINRVZ]_``ý_]Ö )2BEFEDB@??@ACEGHJKLMNOOÆ $-5=BFGFB<4,$%,28=@ABA?>=<<=>?@ABCDEFGHÔ "*18=AB@<70(!  &-27:<=<;:9889ù:;<=>@Ò &-38;<:72+% !',0467765443221ú23467Æ "(-14530,&    %)-/0110/.-,++*))()*+-/Ø "'*,-,)%!  "%()**ð)('&%#"!! !"#%'è  #%&%# ô !"##ñ"!ó ö ô øûç  õ øüé  ô ø  ü ê õ  ò  ì ÷ý þûú  þ   í# úùùø  ö ÷ õ ç  ç   æ  ç  #%%#! þå !%)++)&" ä  &+.00/+&  å $*/35640*$ û   å !'.37::84.'  ú æ$+17;>>;71*" úæ!'-4:>@A>93,$ ùç!%*06<@CC@;5-% ø !!ç"#%).39>BEDB=6.& ÷!"#$%&&'((è)+-267/& ö()*++,-..//é026:>CFHGD?7/' ó/0011233456655é67:=AEGIHE?80' 767ü89;<<;ê<>ADGIJIE?80' ü>=<;;û<>?ABBAëCDGIKKIF@80' ûECA?>>ú?ACEFGGFëGHJKLLJF@90' ÚKHECA@@ACFHJKLKKJJKLMNMKG@90' ÚPLIFCAABDGJMNOONNMNNOONLGA90' ïTPLHDBBCEHLOQRRQPPðOLGA90' òXSNIECBCEHLORSSþRQQðOLHA90' òZUPKFCBBEHLORSSRQðOLHA90' î[VQKGDBBDGKNQRSSRQQðOLGA90' ò[VQLGDBBDFJMOQQPðNKG@80' òZVQLHDBBCEHKMNNMNðMJF?8/' ðWTPKGDBABDFHJJKJJíKLLKHD>7.& òSPMIFCA@@ACDEFFíGHIHFB<5-% óNLJGDA@?>?@@AA@ëABCDEDB?93+# GùECA?=<;;<;:ë;<>?@@>;60)" @ú>=;:8776þ544ë5679::962,& Ú899876543210/..--./134431-(" Ú012211/.-,+*)('&'')+,-.-+(# ñ(**++*)('&%#"!  ë!"$%&'&%" ñ "##$##"! ü  ò ñì üùûó ûù  î  ü   ý þð ýø   Ï5×commonsÿ     B×^'®'º×z!}&$€€€ý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Ì     ÿÿÿúÿÿÿú9(nõ8(ŠPÑPÝõ8(¦2ö=£HzU  þþþþ øúùù ô  í     ù  ò ÷ ø ø ×  øî ÷ôøí  !#$%%÷$# ó!"##$%%ù$" Ð  "$&')*+,,+*'%"!#$&'())*+,,ú*(&#!é !$&(*+-.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ÿ     ÿÿÿÿQ,dQ°R¨R´RÀ,dQäRRR"R2RBRhRxRˆR˜ÿÿÿùÿûúôÿþÿ:ÿý Åÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ&ÿüþýüÿ>ÿýþýÿ>ÿüþÿüÿQÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ0ÿ0ÿ0ÿ0ÿ–2K% commons-pool-1.6-src/src/site/resources/images/uml/borrowObject.gif100644 0 0 52357 11701070263 22706 0ustar 0 0 GIF89a•û÷1!)1))9!9)9!)9)9))9)1B!BBB!B)B!B!)B!1B)1JJ!R !J)R)RJ!R!J)R)R1J!R!J!!R!!J!)J- P+J)!R)!J))R!)R))J!1R!1J)1R)1J)9B19J59R)9R19] !cZ^Z)c)c)c1c!Z)c)Z1c1Z!Z!Z!!so)m )lk1s 1k1o5~)„1„)Œ+{1{"x6ƒ5Z)Z)!c!!Z!)Z))c!)Z!1c!1Z!9c!9k!1k!9s!5k!B{!9{!BZ1!c))k)1Z)9c)9c)Bk)=s)B^1-Z19R1BZ1BZ9)b5Big;€~R”)”1œ) 1 5”9 9JIŒŒZŒŒc”Œc””c””kœ”kœ”sœœkœœs¥œs¥¥s¥¥{­¥{­­{­­„µ­„µ­Œµµ„µµŒ½µŒ½½Œ½½”ƽ”ƽœÆÆ”ÆÆœÎÆœÎΜÎÎ¥ÖÎ¥ÖέÖÖ¥ÞÖ¥ÖÖ­ÞÖ­ÿÖïÿÖ÷ÞÞ­çÞ­ÞÞµçÞµçÞ½ÿÞÖÿÞçÿÞïÿÞ÷ÿÞÿççµïçµçç½ïç½ÿçÎÿçÖÿçÞÿççïçï÷çïÿçïÿç÷ÿçÿïï½÷ï½ïïÆ÷ïÆÿïÆïïÎ÷ïÎÿïÎ÷ïÖÿïÖÿïÞÿïçïïï÷ïïÿïï÷ï÷ÿï÷ÿïÿï÷½÷÷½ÿ÷½ï÷Æ÷÷Æÿ÷Æ÷÷Îÿ÷Î÷÷Öÿ÷Öÿ÷Þ÷÷çÿ÷çç÷ïï÷ï÷÷ïÿ÷ïï÷÷÷÷÷ÿ÷÷÷÷ÿÿ÷ÿ÷ÿÆÿÿÆ÷ÿÎÿÿÎïÿÖ÷ÿÖÿÿÖÿÿÞÿÿçïÿï÷ÿïÿÿïçÿ÷ïÿ÷÷ÿ÷ÿÿ÷çÿÿïÿÿ÷ÿÿÿÿÿ,•ûþÿó×Ïß¿uëöùÓ—ÏŸ¿uÿþé[Hq¢ÅŠ/jô—á?‡ Bô—OŸÂˆ(Sª\É2¥ÃûöéÓWС:„ènÜ™±'ÏŸ>ƒZŒR¡Èê&–kÉ´©Ó§PB¨o)‘é²Jʨ׮`¿Š Kö¢AèˆÚ<q([˜(÷E” wîJºq#z4òœ^¿rñFú2¦ÄšR§æ­[—.^Çv#C–¹qe¼# ~9﹓ƒC‹Žêq¦D©D)[V½¸uå׌a ^½úñ]•³sã¾Ìúß4„}ÿK»®cLû®z,Žzyºæ;Bg29Ý£ÿ¨A=¸¸a}ÿnþ§¦79DÒ—G?ÏþàsõRÍOOßžùòäD÷¥; Q]ÚÜ(`J8-tŽ>ÐÕOMG¡Wß{çA8}õE8¡…ð9w¡|fˆa…îAÇ!{ø©s(‘—ŽL&™ç"B/¾'!}¾§rÏ탎_‰7`Sçý³âGÿi4øçà‹ Á褌!¦÷œtT®'d“ëqˆ_`&¡øß?†9˜qþCWf ¾4%[JZIá•'¶G#|sÊIâ’NbY#juòy§pVùbDèÄôÜ?%µÓL3\>ʘ¤“±ˆã ÓOxb¶LF¡Ñ>åØÓ"¤¨Fšêªª¶Êê«þ­‚·¨~:¢4P§¸:U:àùÍ{j+ª´QªZ¥Ç&K¬«ÈÖ¦l³Ì¦ªO=ùšÕŠÑÜ“Î3æ˜sÏ·æ¤îµä–Kî¸æ^;®9ût›Ž4âfï?ý˜˜+K Á„\4Å¥sO8â¤+ðÀl°¹áv«ð=æÀn0Ò wïÄ+õº¿åR“5ŒpÁè rº#ìqÉå¢|®Çå~{¼µ(1dÌðDb„1ƒ 6„ñ„OŒá³ÐAmtÑH­´ÏdÜ<ÎeœcÆ6”¡¸jLõÒI-ô7S†å˜W®ùå›gÎù瞇Þùèr· ùé’§¹ÙO8QF°1K/ÏôÒ /¶÷âLî¼÷îûïÀ÷¾{/³÷â‹/³”Áq×4\Å £Ä3Ï4ƒ{ðØg¯ýöÜïŒ/Ä+¡ñv‚çzã?Ò3ÆñàÛ>KñÜÇ/ÿüô×oÿïÎÈòÌ,ZCÆ3Îø†»Ñ ‚C€, ÈÀ:°Ý˜/œÁ p8ÃÍèÅØE>­äyÙØœ>ð„(L¡ W˜Àoð€ßh†}ñ„!•bü¡† žÃotƒ…þ@ ¢‡HÄ"ªP†¾è‚4fpȃïxG7º!y¸ãòèFßáŽ-ºC‹\ô"»Å/–Ñ‹Æ7bƒo,#†½`Á=fc¾Íˆ(ëÆžáC0†±Œcã9H.’4d!͘H-þR”¢<¾Ñ‹0¤<7¼ù6ÆÄxpÑìè"ɨÈD2’”§¤)YJT²2•ˆtå"_IËYÚ²‘’|†ŸpÀwh£í؆#£Øv¼˜ÈL¦2—ÉÌd¾#îvy¼ƒ÷èUà$„C ìÆ6šIÎršóœè&ýø(R2 æ@N&ïÅa„]þD&;ÒÉÏ~úóŸ ¨9¯éŒ.# l'0ÇéÇb ÔœîÐÆ5y7J±1¸‡=Ê÷)¶œ'àœb0JÒîs‹ZlÇI)ù™Ì“žç/ÝÌk”ô¦8Í©NghÁž Ý'6‚¹Åc*Ó¨ÈDê?‹!m|#Sƒ5»± 9b2pù"ß: "ÓyÀƒûLêQÇêL²Šµ¬h=«ZV0:Ô˜ßEöóÒ:zóž T)Xà L¥s§:õ«_»LÁ.“ñìFøvÚ˜ZÌç_£hÌcRö²FÍl_7kTy #†²˜Â2¦H@'d³ƒ÷Ê‘J6E'ÄÙþëe+;YËÚ–¶˜ÅímsËÛÝîV¥}õãI3¨„­Ö5L†yI5¾9¼ª4‘µ.eÿJ]ÍVw³×Í®u·‹ÛÊZ¶»ÚÅ.wÃë]é‚·îð©0þ×X°B6š¸DiQÙIßËÒ·ïG3œÑ,¾ÃzA0‡^( ä!ßÄçI‰9ßË÷Á †p$%\_ ·Š\l/(¯™<ãw@È™ˆA–[|Ó‘Sup„W^8¸žÌ'„‡yM³ØÅQ¬"7äáŒ6rãËà…ÌÚ{)DÄÔYG‚¹ÜuÅ =3þ;qÌf·:™Í`í¢£(ÛotXXæÎ—_"æ›Q‹þÅqšÍLašÐmVñ má5ÿxÉg§‡apŠÝ€"S#*_¾ƒÌÖü´³8êPKT¢¶=ue¿qåwÀ ˜–µ ¬òzDþQÏÌk_J´VÔ"ª×‰êvvÕÚÇ5šETÇ8¿Ü¸r±=ýë¢f#¿Æ¸ô5{1W<çy4š‘Ë:rÝë5÷z‹Wδ5·êO5Ûï F¨+›l'»ÓRõ•;½Åd'Û—[ä71%Šo)~QÊWžò³‘]ÔScöÜg&ªOm1Kïú™ï¸q{j*F“Ýð†<þ p_œáï˜Ç7Ø¡ afÑÆŠ0€æQEL™q—b6ðýï5ÆCéÖ\†cþaš¯£7'é{mMbp>±wG €ï)€Ú˜röñþMEyÈÛóˆ= cXSÚ d€}Ë^‘ø]fVtü±{—Œh·mÄÙžßüjãœð§ Ú œp Ñ” ›@ îp ›ð¡ ò¦ œÀ § ©À Ç š ò pe¥  } §°·PE­Ð ·Ð ™ © –ð §Ð Çmèòð ¡Ð ¥ © ­  ÄFºp •'Æà|¼–³õ7v–Y}Õyítƒœ¦ ðEÆ Üà ÔWEårû6jXA Ð\ìàYT$E¼à\7O†!vºVlÇrDW~ÔÜ@}Þ00Êòà _˜Eþñ@ES–E—÷ [8Æ@"Ç WGjÖd U×ióЇ¡VLï·uW¡ñuÉ‘k•…g·Eu Î÷o­€x  ­` ­0 Äð ’yÆ ¯p ‰À © ©` ¤À‹·@‹ŠÐw¹°ˆ‰ ˆð “ ÚðÆ  –p “ ¹`Œ¡@ ’p ±€§` Ú°‹¹°ÂX +X • ¤p ·ÀÂÈ Ý ðöpüX…Í0dR¨RYDSÍfMÔ—_Ä E  X4›Ø‡ßà ¶ç±'ó {´pmS$EÝ7âVâ„^ú·E ÐþÖJèþÞˆÞ²— ô à "'{Æ@{ÞÐ6É 6É‘ô@~i @r›~$Ç €XE·pLïWC¢èu!$$Õ`^Ä`9zRÔ P œ` œÐ ÜPw›ð Üð —ò` àßÀóð Ø ™ðŠðuw¶·  wÙ Üò @ ¡ð U¤ 卽‚ÚP ué¡  S—ÝЋoé Æp óÐ ôè­–N8Ye O kUEL%m ùð¦ $7jÊ@{N‰”É ‰ß¿‰”ò`Ç9žÔ}d6’Xy\shs8÷p•RDp}þèj4 r óžÞéÀ“³‡‘È“å)Ì`àà à`Ùß¶÷ @ˆ×G‰Ø—tZwIY)¤H‡_¹’®yfOçKz‰oœ îP ¤Ð‹ÞP © Ÿ` Aø  ( ‡Ç ª  ñ  ¥ ÉV‹+(ª ÊÀò€ ¯ð”š` S– ð mÇÐ  Ú °E©ð óÐ Ah ¤—Ü  š0 ±ÐnayvƤ^ö÷\j÷yópƒÿ¦ ë÷Cùõ”`ˆc~MÙæ)ž  99±•ES6|.p¶–5gË`Læ]~z·÷“R©žó`þôP“ôp”h“²—¨ìYˆß9ó{³‘ô)ßÙ‡ÞÐ H9“"cîD’J[™]Iveׄªˆ®€qlÇ É¶ Ù€— ˜ÇðšÀÆ—¯€ðwé  ï›€òV –` ˆ°ƒ~À Š •¸:ˆ` ¸š˜Ð¹`¬}W~¨}Ùi ˆ  Õª ŒÐ ÍʃSf ~§+¯Õe¥oµv"ÉŸ7ï@}·§F^8r‚H}¹‰Hù 4‰”Ú'†6æ pøRá&n¦ˆjµEà‚jA}¸ˆc*ñ0¦ààà… “…ø‡~(rƒ*•á'“"7þrR©œÉ9I³7“óPoÖ  ªƒQ ¦xªË—ŠgæìpéfHç×–؆S¶ˆþxЖlæW~k¨„ÖôqJEÙVEiÔ´éjK mqÇ´¬–_¢@ R:¥OXPêC›Æy g9Ö”~¸¯Ù›#'{“Ô›Né ’sÖ ¼`IÅgÈ÷ ’6Y“·é§0”™œk‘ƒj‘Di8eÐG~Xd¹ß °bˆE±'•u딘*EÏÅRq¨³M1\é•> ´?»åÆk&c Ö|@whçvc¢–}-¸  J¥Qôk›TTÄÛÀnÙÐ~óz mX[ExG½Wþ;j ’T{Q5ºó°±ßµ’Üð} ÷t×m‹Ø²`E–FÆl‹xy»rj´ˆÚðo.èqjô›Ù kžºmÑ©ºOÁºtxŠý¨Š²›v×À´k»REò  ù儽 Á½f³v¸ÀZ¥]0 ³ÉV€—z ëd.8´ûöoæ÷iÒÖŸ§ UÄr.ü Ûef§ÇW)©dËtSÕEÚùyùå²Ç îµU4JKÛE—eΧEü¦ kHEÎéIdÆsì½¼ZªE…Š lòú`ˆ;¾e,– |vðvƲ+–l\lºÅÁÝ…Z@q´ l¾TY[Ë„ voÄpeþoùútFp)·rP´ WöEÍ6L`{s»VÆ‚ì}MEF¨Æñ«l—˜_éÛ×¶†ºirM›¿—z©WÁûxoœvº ºÅ-1¥èº`Œ¶ËÇN¶VÔU›ñ–¿VXIÕ˽¼Ë»œÇ©<Æ×W>EnùªiNkMëkÓÆy¿¦ ×àpQl~î`SóÕ 3ðÈ^†ÃÃ@yJÒuOÔi2ÜNyìKF'Q×¶p—z…¬§öcólL>GÊÒ—È®<6˱\õgªôš LÉhk^Oƹc•Åo猠 ÝЩŒËÈœY±YqYÇÄT…<¾E…oßGzØlYùkþYêÝk£Ö¤wwö*Ú¤§Ì L¦jÿVmöL[Õ¶&Ç|zdÔ¸–ôuÛ´Xc€ Ñ¿uÓ©,Q˜l¯²þÅÎ-QÜÜ7xÌÆ,șۧt"LIÝÖÙ,aÜ]Yû´O¤ÔÚ"mv †ÆrLJ”µNk8ל'Û¥ ßÇÛr<Ûÿ¥D3À Yxî°Þµ)JRôl¡Q_©’aDF¦EîÅÒïG.u܇ò¡13àCîGÝI…MS£dL¢ä]PV¿LÅWlE£dY–O¢TàÎ%iÔ pŠä8±ÔÐá)¹Wê}F!F*ã4þG0~F3ŽØîà~LcJvøäPŽäÎÎ1þäKã æGá˜æ Pð p »ÐXÅ”HÝÑèUØâTFB+ØlÜcÝPà ecþÈG§e/cC|–GæÀ„ OÈÕwnçæÖQd èeL]ØŒ^[•d{Màà xð <ÞãàñX#–¶ ذW¶èª^é¬ÎÆ”¾¼tÎÜ«>ë­^ë«.Q4Üæ€Mô Èl!)NÂ>RÛ°Oã´¼ |RÈpìÌLÍc?NZóÐ Ï2!*Û$æéÀM4EÈ>îÏ^îÎ~îãNuË^~LÙâ.lmîä.’Z´¼ËQß²àEGMWA 4à ¤J¿—’äŽîò¾ð ßð _ìï¾}¢Q¯£v:½kìñå_·èºØ³çïç/?µhjŒÛôö9î([[Ç)‚ªM…a$JBº†*8£ÔYgòéGóÈcÐS£ ˜Ý,¤«Â W¤ðŧxC¤‡j‘EDïKTç§ö)ÇŸzB4òH£ÞKçǙҧ8ã`TqÊ«ÌÑE¼°B ×PJ+Á¼’Ê1ÃÄr¨ƒbÐÀQ[ñ8ôÖ)ÄÑþ£Æ a¶ƒ“Í <H§l´‘D‘Ä‹Á‹RÑOFût”OHáLÍDÚK°¯”Q9ýÑ(÷ÑçSCK.Á¢’T¢4ÝóUWc}Ö6ßã«QjÆJÖMgå•Ö^ƒ•ô¨à‚TÔõ•MrKÂR_grÂ(…bóOSë"T¼iÇö×X]õ“””W›z“®k³uWDc*ÚoéöÞåDN¹ÃSY{Á xàoct<£Ô$j¼-sª3"LÊÆc+^Ñ)¾ }©t¡,®Ü„'9d¨ÐøÍë¢øÆ~€«V(„7–y©T‹êQO-©•söùFUþ§­f ryù¨ž×ÕyiŸµl¸fd§j/‹6oAjlwæLG„ræ ׉ë‹l¹X {m ™’Së8×.æ@§J«åv—â:Ñãë8:÷]JM×!Za¨^ØÓ¶ÇkPµµùLµX»¶å2ðÉlk{Û÷Z·“aíB1ÃËnÔv¡n1Šæ±Ðj7Çš±ñˆBÁ ñXž>½-/M :¢4#9‡`3£Rù.-õ‘†IÌÖ"ÿø¿KÞåˆN1ä„™É=²<Åi9þA 4”«4Šr@#dQ’•³¤e^¾ær°'•‰¬e%1”tühþ„b/9)¨ŒK˜V´ä1yÉM˜Â$&/Ÿ)¢ÉIs™P A1¯ÉÊÓ¬Cy³æ7Í)7‡jRÁä¦7Ï9ÊÊMè4§œƒ;ß Mjì–J»g?õÖ6EÉ 5Ô¨g9ýI3ž­G(°çA£(ιSˆ¥¨¡ôh¢ 1Ô å¡kÐq¡ü`.½ä/þ±jL”¤+…纠òÑŽ”¥‡ªXTÝÌÔþ0${ R•Ž5SpÚ¡’.rÛF“¢'5‹6A»ãS­j´uè#M½* œ §]Åá“þ‘§äÃvT%«P«H°ŠÕ©+¥X0ý~äƒ=mÝþpαÖtRU²ä«NWfW¼ê5¥…å'XñšË¹2v‰äjJÊVÉrô­p½k? ›Ù£ Ãa=edAkt¤IsjðNËRã #auJ{N[-}€uékCä_¤ãPa•o [;tè–· E˜eUSPãšÇ…ë¸Á\úgÚèÒrt6¥&t™Û¢â »W3UÒÌ{´ÄQlj“î>Ç›]Zö,(Á¤†x_ûÃuôr¾qÓ|‡)Qv`ì$J0Ù9ÛÜpR(¯µl$Ñt`˜žÔ2‹2a7xÿpÖ:ÜA%1¿äÜÙ;|á¼@cc¢¥°…],·-Õhl·•Úþ„ÆÔPX¢p :,Û‘#¨=ÖzP5äsðÑLÔLXÅž0ƒœš¥ÃñÂF|ÞƒÚËu1ð?Tì.g®ËTóÆªøÃ·ZO\, T±x™*€Dzf37‹(êH󄨘dv8ó–w¬çQ.J‡§!MÑIxe…€´BšÐŸznsh- hS%—Èg.u¶šx õñ½ý!%ö$ˆÙ®ðǦegóÔvîdŽ€ŽpXË?þÇþ:l-ÿãNÀ?È!;/{aÙ^°}ŒíŸC¼ösŒÎ€~œ8U:"¨þó¨Ògž¸ÕH™wyNŒâë-ÆòŒsfƒæ 3„)äàu·@Tp}t2Ø_8²=ìcC[⦸ÃAœ‚'ÛÇ¢M:È!áaëCà©! $ÁÛ”Ma1†¬.5h,dcâAό껈ҩβÎë½¶)ªß’­u~#Ä ‚›òâÂä$O b^ëC†ä5ÁA¤Ž`/Ú) ç5£ýq€•sꦺ÷î­Ú†DÇÁÖö, ÁldÐ:f>9µõ¤;'3‘M…j¾³n»6ö#cÿ-”€§tÈ03]P£èÆwXÀëèpˆbyaJX¶“æ0j°žŽ-ÿbÿ¸4.þÝyûæÇ[V}P ñø‰6Ç—ž°OÓA€”ÊPT\Âщr¶f^³Y8ï{ãóm¤G·˜Ê‚À _Ø¢Ëúñ;ŠOi`Ë·0ìU¯¨lËiPv…—üaÊ€Ùøèµï&h™vž¦²)­ï»1‰n›¹Ã\|gÚ²$S ‰:64@a‚ô; Ü)̆ °¯ïb§Â‘µ'9Æ!DA9'6Æ­¨â¦uØÄOt’Pô”Q¹¨ )z’PôDüñ‡P$ 7i†+àB¨/¨É ꆧPMœAäûB£`4ãƒõ£8̶/\4ƒÆfD363;€=T2 ÃF;ÓF óÃ$;Ä2£¢>P%9[°ÔH£þxGxtÕ¹ØöhyŒŽ§¨/(@0„-þà‚5 Ú é[ö˜0½ÙFSB?\½”¼f+@ar€h0 û‹,?”H;Šc;1|4fóŸ ±©¹€(´*ã`5±a3X3ˆÉ™”Iš¼IœÌI›´É™ìIŸôIžäI¬I::Hƒ@ƒ3@¡üI§LÉ0ƒ4P3 ƒ:@¨¼,(A„@(.ð‚50ð9Hƒ3HÀ¸&øŒu°Q1eL ‘$G9ä6õÛ1`ëH“HŽ$Šfü±cµ=ôKS›¿ã›Ãjïò·i‰v꣎¸LÌT‰ÌÜLÎìLÏüÌÍL‰Ž¨ÂMÏŒÑĉþÐL[ø‚BBØ‚/à[¨µ‹Û†U`ƒÞ¸B¥B6ûH ;BeÛ¸ÁüH'ËH 3@âœHtp¨-,Éâ,3q,Bdõº¸öòMR°%ùipÇq-Û€QÛpõf]Çiò]AÚ²ehÆeiŽfjžfk®æZ¶R¬ZA=¬9LžŠI_gjU@•µ ¶`QŽŠTð…¹tž#ù˜b ”2Òoþ®1“ ãM®(>ΦbY‡f»5ÙrécK³4Žd~jh…f臞ӈþ™‰F™[Zœúm±øæ9«†Ð…bÍ9¨š³#wûÓv®T"å¢Û`=Í6^ä—Fä3ndIŽäCnš¾é™vh/¦-üðfÊ!W~fZÓ–@aDº]iƒV/q½¨…ÆéE†jHÞ驖ꚦê«väAÞ,¦Úbš«‘ VT¥Ùßuø$+&Y,öc/kæ,[§¶ §šëòH$º&»cPq˜Ÿ&›)ifx†·ïlŠR:¥]Jg¥ni@qâPC™ŽŠg˜(á¶Ìé‰Q¨uÐ(Ï>Ö®›ÛîŸZ{`é&ÑÛΙ”`5Z—í¾'=z)Z‘ª`ÕÉfnÁì~†NïrkÊVp%TT™r.çšB £Ê)øjg iê—'ƬWp泩ŸÎÓþfé9 iºZª­r¢tÎgXKm\U”'u 0}°˜Óð Ô[¥À„Òq)þª°ޱ oÇmj‚]Ù]:ΖñKjn ¶þÑÚuR¶9që,ÅŠçÃÛo¶&ŠhðhÄÉ m"n$‡$§ñâéÉNÞf¤p,ÏRlßz™d®ñЖŽ9X;*©¿0¢ŽßHÌ«iaPü-í•-¦ˆ!ÛÂo¶šlú]ûMƒÚPùìç=o†öØha p×n‘ÜjÔýVÄI˜^~Qü ¨ø ÖèX0õK7&äûìܵ" †M/Z5 çr_c–L×íçÖäa†]5 Ș[ÎÚ–q³+èŠËL VxjPHKŸ©yª¯bo«ÙYïý;%±Øà4¨5b/fOû«[?õ¦À+‹"ˆü“‰ÆÝ+i5‰·(‰ÌXþU ‚%®T ñEå¨ Î‡Ü•ø ÏçüÏÇZ}®†Ò·¸@}ÖP}“`}Êu}ÖýØÏªÑ_ØÚÏuÜÏOÕÐ||l h; é·B¹ø?‚kÙø'Ù”î¯Übw¤'ÐÀÍGÕ†ì&J[‡£ZŒË#&PvJÇÅ ô?2¢@\õOAöwÿ'jÔÖ¥û·.Ú:‚ Ó-dˆpÝ?†éÐEü÷ØBƒ«í£,á:}þ4ø¡B‚ ‚$8š?èÖ™ñß>ˆþ,òìéó'РB‡-úóæN‹ kÞ4êô)Ô¨R-&¥Êâºaf*ÅQþu/«­û 0ÝÀ‚gìó­?}ÿvR¤h1ÝNM«Î• Q"OŠ|çÂ;÷_]žxçîuë7bI‹‚}6L±â¼yþ³^ÈÂD§× YÎ9§²níšs[¥L_Ó®mvR¬ÔЬÛ×–«Áj7 RTé5±džrÕéËçïœÈçUãÆDœ7::ÓÍcž;œ|§ó˜xãžó—/zyÎÑ­÷™=nøîU'‡÷7^_ùóܧ¯7Ý^¦vñyÚ?ቖÝ?Ô$]:*¤Ö›U·IHÛ`¹4Û„jø_Ua¥•NyµŽ0>„ôœREd,Úe‹é½eZ]é3ŠÔùþL„Å$’‹ú¨³¦öOŒ>ÊÔ#‚7æ]‘J‰˜D.yd’pш˜8ÊepM‰N•Eþh‘‹IMT5s³WAÊ Õ`M­ã`Ssê9a^)ŠÅÛz7ÍT ÿàÈeŠÿÙ×4r…ÖV4/vu×NꔃÜab–hœHÊUOÓg×h‹YŠ)]þ‘zS§Ð|Û?¢DªZ¦^ºi¦ª^uO®bf—?äœÑ>î­SÇG°Êµ'³”9ë'†ÍJ+U‡»fµU?ýð•P5)(ØcOŽºWg:þ¦VDêTÔÓ_æ jPN½uêU¹>y†•>Ÿ¥Xﮘõ–Ð>ó¶Åï®(þ”¯¹»›Ü¿òîZaåTÝ:)¤¦(¬Ó6ÛadzYœ§Æ!;ÕçoÕlS?VébÆ*ÓHÖÚ™hl^Ù W¬f¤CýÞd³EÓVÔ@AC¶Ž¦3×Ürµ›&„ÂÅ"O[áMÑ$ˆÆ›RkTÓ¿± ±fÕ,ñ/ׂìÉþvÐg»Í¡ËúyUÏ M3P7kQwH˜[Òð¤.`ÐèÛ/»j[èO9f½µ´ƒ!JQC~9n~šl9Å„þUŸ$‡ž8Q£ÃvØè©£.:qÚ¥î꧇¾9sñ¸zU†ûÝïíqÿº…Þ!8Жc¾ç»v­sñLJÜõ‡gþ¿Ó:Õ¨!P’Ÿ]ú³r»\]^¦KνOþíä(ð¸"{Ù'wú’¦þü“žïïòÍ;¿á̦¥Süöö÷<ï`esÛË Ö1¼© oyz`ÜT—º …tx#Ùíj7$úq~‡‰ÓDvrèªOçðHêçAеå-’Kô'À 5XÿØ€ g¹Ä]‹+2ˆÖ·¡@qhËœâN×@ 1vsé™Ò¡ñµ…Eos ’üáùÌÅ4°Ãb)æ•q)‡:œSÿÒÀ3j¬kj1™ý‘2¶ clƒ›©F¡lÆL$ŸPÂ"2ñÀò ©À˜HùæêþHd•Pç„ùAÙx›‚Ä!ÕÐd‘b/¡lWÕ¨£(˦J¢|n[¤³Ùç2¦ÇŒå[ÛÜ–†«`(½|v‚®XŽÈZTùQu¢A±”Sñ£gN-7¾©ÞVîØ1³ « ÐËaF„U§ìŠ€00‘¹[qö1 ½PDœ€:0¯^Æ i’!ŽR:Eœ_R„Eûtç8!T€¹Í¬m:ÉVèRØj“šOØAæ¢-«YTOÁ«Ó×2ÖÃ/þ‚j1€?õ‰œw­‹œ¿àÒÈ9/êýŠ—ðÚfôi‘˜"Í–Ó(§H¥»ANÃmaþ ?¿Ù³t@T‰yW:ÆéB44,ªŽá(9Æ9vtdIQÐ?ÎÑ|µ«{êÓÏ6·D6Ó)ûP×[+rŽ€Ê¦3‰+/ÇI‘ˆó|åk>g€ìô²ž1ýG8ûúèsX;יטæóê«:ùšWqv °£H4ôÁ½À½„F8† ¯2ÀÛ${V)0eH¡©YK—«™ÆŠÌím\ÙÃõp \O×Ô64‰ó~ˆ95ÏzÎŲ5 O;Îq~ê,’ªd·K¥çÎŦ)ìv^EéU.㤋?¤Ú]2m—°À²óÞÊP­Xi\þA!¦­a¸C©N½Ø4MgˆdDÜbR½BikÀT_^ŒdÓsȧ;µ‹I± ÙøvQ½Ý9G/ãÛ@QÄ)æ\Ä©YG,¾2@Œc,$À/«~Ã*! Oç­®zsßÖÚ´(lË9òÑ•žÉ‘«„ümW)9+và“ ÎP[•ÂÍé(Ås.ŒèP Áàª)¶ˆ> 6‡Ç66Mˆ—tGõuGØ]2/µ³Î¸¨K½Ü1azIŽ^Ò˜—úè­MÇ…_MzI‘þq>•ÜG'`UÑéö¢—V£ ‘ã‰ûeÒ¹p13Yãª)ô,aóÔ2þZâÇ&ú  kA ¢Wò2µ3q±ZDœé½JVØ"¾‰fÛWŽ µÿ°cÓœ@ÛõTl^‘¤ÎŠ—H‡ºL[Øuœ;9Q5ŠÍü›‘ˆTc6abøÎlàÛÎ'A8Èd¬ŸùÃá/!¸®†Á(R^¹›fz#œ#W³–¡±e]è<'ÃÿbuÕ•£ïƒˆ-5ÎR­´"ﮈÐ:’¢D&´ HEä6†K¸·.•”jàÞöˆëXÀ^” YK­Õ"‘çµ,b-'vÒâ箹“Õ¤¨‘7…UœEõu=Šëm¹¦Äš¾ŠX;Q$V,5•iŸáõÛ>Ñ«wöþ&qK$fG2M¶hr1«“TèX|õ€Že¿?Ejëa3ãB¢9Í2{T"ä%—ÜäzOò§üê³·È;Æ'ù•Üd–+<¡@ %9ð5†A êE$øIM`´3Ö©¤JBOøÚw7AŠªñ‚8ê¨J?bˆ‘Oèb-ÿø)Òó‘¯(éCÿG'R|t ßælßQÚ'ôzj‡.R‡û"1¿?¸Õ>!ÿü)4 9Œ:ñC2ùòJLv7DÁ ª_ ÓýÜ›´•ÐÔÏMÀ±ÏÏÝî¹R6±ÐNPC-ØAK\ f n v ~ ¦.DK Jþdà ž`B„JCõTƒ0XÁB!dA¬@ œXTƒØØD:¤Æ"ý !l$à\¶Æéo0_W¬\A¤Á ˜˜f¡n!v¡~!†¡‚á˜A„@à ÐÁfaš!¤À|a¨@¤À¨ a Ä¡ÔA X¡ ¾!" Á\‚ ‚xÁA¤.ä!Ø (H: DiË,RpFà1`>žÙQZHõØ‚¨Þ0Ì"-Ö¢-Þ".æ¢.î"/ö¢/ÒÂ,žÒ0Ô‚/Þ"1VÃ*è¢0Ð" ã0,#þ2.£ê’0ò 0Àà)Ù+Ì` |AØÐâ5ÖÂà*¤XôD¶ˆâYTIÒ… a*^”1!G¤B à  b@‚ZÎä@ $A¤A&dA.$B2¤F¸Ä:¸`CNä ® B¦K C¸  êÚBð`-°Á7®5®ˆ Y Ä2â5PDwÄѤ !éQžÔ#kËõÀÑû\˜³$PšEQ¥Q¦ÙPšQPƦHSöÉÁ{4¥¨ñÌ„µA-°5x߬KõÄKZEÎÄ\´Ï:@ÍàÙdÙ¸"Oî[É’úðš[ò‰kþ¤G’RÞðåµ%5Á…ºËÕ<Î]Ú£µEGn¤ ¦mKNRFåW˜¡eéÕÅ:T`JfÜ€êÛy„n0±âÙPOq>`þŽQx,؆*Éø'„!‰$zѨóèOöåÉx§íù@BÈh÷äæ4 Jõœ$'•‡tèCí´Œb§p²¦eúe ^ž>ôC>¬ã’†æsúPläK-dÓDÆû-lféÆ\E”Ê ƒÎÐÙðH•’ƒ‰îçGA (Ù‰X挹$}ši³¼çp²‹‚g*¾‡%H›º¥ám‹ÑaQW¦AZLCBpdA, úéÔ¨“º…|âèq¦ˆ>ðÈ:tY–f&Á=`õ\FÆ ±I¦¶ ”fæªñÅ·0¬-)Z©è'¥Ú ¤€Xì p˜Úg¸ê«>O­ÉjwþåþˆV5Ôä‰B‡.‘4 ¤’Å X!²ÄÂLŠCž¥Ì±ÍçG1•ëD&d¸>¡ŸŒëڌȹdº¦k@¶+½.$7i ËäIŸZTaE´l(™iΦ^EêYA©-`c5|DE¦Cl+YÀ`õt%‰¼  bcH¼àã\c°vì:0,·¾`W’Å›TÅ^#Y\ì5Š›5ÞÇr%H€, B,ÉN,Éò`D†å' ŠÄZÄË6ìÇ6ìÚì›tåÍ=£9Âà4æiY9gBMÐ#>Þ‡ ì61Á C¬Ô5ì@˜EDZ€L€Bx€Œg5èÁ|ÀÄúÀ ÜÀ¤š ˜þE¨€ ÀMì xÀ îÀ¸íÇ®ÙÚnÀ ²­Ûš¬ä€ÜF$ÝÚí?à­ÞZßú­X®àáëá&nÛ¾­ãÎmÝúåîmßþmà&ç~@á®Ã Ì,ÓÌ œÁؤ€P" ÌAdÍbë¾9ËÏü«Œ:çŸOt%Ô,A¤ä ¾‰ÁH0„cŽÆ’~üÎÂD¾œ%@^o½€„'Lºâì÷†¯â‘¯ˆ˜¯ZX¤ÀÌïM°ow¸ïøš«üj$l‰¼ÉZR#ņ©6%êÝÞRHíÔÞã´:P·œ£0ä€d¤I V‡`pXLÃNþœÃ‰*•ñL‘öL’à4 [Ω‡YÞXIX‚ƒ ÿS¬¨0û Ès¸ðÇð“J<Ñ #FA¤ð `H™¤¢DPƒàlÝùNâÖ<"p=*ïnclñ?ö@`9Ëkqð™ æ’ˆDy´–{)HÆ’hÇ1q‡‘:Þ¸¨±·quˆ¤ñ÷ð[°±vékßH2bhK"©…Xo`„ê€2Økú+·§´Â'¬P„稠]pÔUáJv$It H]œÄ„”:àHp„j(kØ£¥I)G×ø¥²yF>´rWGyØ4ÌruÔ²uÜòþ¯ ò[¬røò+‡U,s¦À…œþà w‘‹T Yô1{ú])*´êê•mñÖ)F5l€ëÜ…?™¢˜ò¤ÔDXÍq`Ì çF É&×ÔoL\vÄóÚØˆ¸ÝÑ:ÃH>—WÀóµý3=S’RܳßÔ>SOA@C݈MÃx È£U1ŽF-^&jW|í:”‚yÞ¯ÏjôÓÊ‘?¡ @±ôQ‰†É)FIÈ4J;‘ÓN/ ;±JKN‹›NÆ õOóJ:iÄÀ½¥M€Õ %sjÖióG'¡òÖhx¥ÿÎ;ªb¢À½²¨ÃE»Ö«­'ƒ¦u¹®õY/þæ\”è:YhÏß}Õ¨HafµÐ…tÚ orâ4å¶pÕ™&¥MbçÒbÿfcƒ5d# oZÐ¥¶x05¤aîæ÷èõO å0çanu`CSi’gˆ¤™øÐŒ[žé0%† ecôQæ8vh«!™%äíöcr†Näƒs ‹½5T¿`è—%R0_ªŸªjoaoϾ&Ql¤š¾ÍŽ ÍöÐ=L‡dökO7x»…xçy{PtZ‡|äÒèkyóÜ®øO®ú(js©‡h…þèQ$-Üßd6y“Îáµáövxxå ¸c«7ؘµN('è|_·&þAôaŒ§™â¤“²[6UK6€;`¾¹a·Ì¶Êì\Q6xŒf÷‹R v}ÿ†‡ƒfíÄ}¨=çÅ,¡çÀdmk¸Ÿ&‹Û%ÞŒ’/¹’6ùŒÃõ+÷¿hÊìæµ+%!'ùƒ'éêí‰t†¦W,ñR¶m;9ÌðZ+‰õ7—i‹·yåih‹—TÝ^«Ø]M²hw…ŽÌi´Z“¯µ‚Â8Q4’ülÊ"-º>—NÛR·'±¿üÌ$½ëØrœblÊ)Ÿþ‘ ‘5±‰o?÷Œî–Fy9~Ë£ ²¦§ª#½£# AKrŽ¥ã³®OZ¯(JL‘þ© †Ê©ÆeùDßhJaLñ ©4Oô͆):U––sÍ[ GíDÆœVߌ–f)í zh²!%¸XŠm‰FÛ~ ‰ùƒwÍEíHÖe\Çt9¥~ À›ešL¸WuÑ ÷ˆ|¼Çµc ‹, 4¬˜®ûƒ ÁRhS†vsÇõCN”Us²:¤º„‚8CÇ:…«g‡f-‹§Y3>Kv¨ÓlmJнuÕÔ‹`»d-U$’`0û}IF’b;lìü¼£ƒȯT=9š¹;‡á|RŸyn!X—#ªª{ó•Á‘‘_*öX;\?õÒ=%ô¸!ÍJóÓ8¥þC,ÀMœ=‡81€îT›E$Ö/€- Ê5YÝ×SÈE€cÙ’8¥A Cßçô¬D>Ò<~¹¤ÃÝ€<‹ýz8]dô?0u¢wXó«—é§Œšê×€Ô˜«¹ë7Ž>­ƒ-UÜÉS!FB! J~DˆW¬ô~¬ØR¹œVLD»±0DL1UAXb } 5ôDADTdYNIVá/VOD/ycƒLùò:¼€å  1¿Íž¸ý8&ϯÞQn”f¶KÐrøCØ“xØ`„¾çÐùCàÜ?ðOßú¢ €†8þóþ@Ÿ:…<ü˜ÐŸG“ ?zÔø‘ãÊ><—² IrÕ=„&óÜJš2üw4¥G)™]÷©Ótýü%ôQmÝQ­Y"mªlX±cÉ–5{V,Wkµ¢ûG V´séÖµ{—.ۮ놙ɪWéºj8ÖíkzX)â‰)ž R[–‰#ùñÇ”–NÑ2EršU\[AäƒL9·Þy­>°K/åÒž#[Öü;eoÕJµ®5žôßS¨I—çó—NE5Û[Å"Ç{;Zµ_S®["7{xñãÃZ'ž £‘ŽBÇ¡ýú˯3ˆºë&üÒÉ*™Œ{ñ©h Zg¬œÃ Eò|ü1*ÔJî;®€<ɳÖùÊ©¾–+îŸt†ÑaÉªŽ¢P¤°¼òŸ,GüšÅúï?°ÊˆÌ¶Ž 3?‘ÒÔêÁ/à p&·ú3*9×q #> D'Ë}BôÅÏb¬ðˆ {*FÃBLn›I¹üÖ1CjŒË-ÉNﲸ§Šô”TR­ËjjШFÒâÐYGÂþÙ =°Œ¬µ«EÏ­t²ŒqØ=kQþ}ö„E®qú “«u:ÔLtu‹Ã/‡Eñ'Âüo!1Ñã ¶hb¤æ)ogí.Ò0_ŒN[!bòÖRýµ•8ïÀû—àëû+,¾Ö£Ž¹aR€ê¿iµDub§($W¬t„xáÓ1þvåe;a¤ç×ñ=øâ‡~`”þùèiÿÇ÷j†±¢A )Ä‹"a|±š†¦ïmN `ÔÃÓËuQ¹Ô×üW@®Ee/f3Ì^Öáƒ+H¡sðp` ^ƒ¤Cp€3¤@4ƒSP:  hè耆x°…)œF0B3Ô‚iÀA èP¤!sà¡ l8B:à` t "R`Ä&2±…,!Í ‚šaVþä! Fˆ† Ò¡„5xá kаPÝÁ—%9‰À½8i:0ª†-ØP‹ü©•œSe*Q) UrNvèç\ÙÊû¥´\¥,Õ—ËjÌ’•®Ìe-iKÙ¡2–¾æÒx¹Ëj˜ò•êSå0WéJXB“•­Dæ0¸™ÍûÙÂUàB!9/Ø‚ ܼ¥1eG˜‘®“>š”QÖ‚ÅÓ_A•zžH ƒ •2ß@ ZPƒ¡ UèB )ÚÁë˜8Xþî`JWÔ|î0‰O¼G$þ؉ª¬çÑž*9 ôgJ C¡Žš¦žBN4²Œ\…sO¡E–4XùÅ>X‹i^ô"3J­ lCý—>Ó³°•²î¥J•*v’º•¾¥ªÁÀÊ{TÐ?@•aSE rŠj©u„àžbE’ê¨ÃºJ>¥K(LTÕZW¼¨ãPëHYî’# 3|``…’PíÊ¿€A‹9ªjaÄTÁø¥J ã'][Ù¢)ÅW£FrÎñž9ÜÊuNÚeÅÚQ›¡jiµlc«ÒS±n«•­Ypòw= ùøG5PЯ¿°ŽNçÁUa1©t$d?Îþl„°¤Pè±ì1`äJZæŠõVÁ,<#³[4d+aíiW¬;Õ­%GRþ iÛ®û¿Áf˵¶z,ÂÚ;[#5%MÆ! (WÔÑÞÇ«öE?vÄÞú†§§Ïmj?§ûß[lÜñŠ–„ÄOŽú¨amo¿ á~P…¦JÝêO¸ÊU¸"¶k„ë!ù•b^’ƒ=9ÜÊÞŠ>øèG>R¥b÷..º•\py}\Ú´@×IcËŒ3LÞ ‹¥Ã:&‡‹|–Å¥¸Ä¯uRl«üà~ºõ¾þ%LP/Ë\Œ¬¥Gëò§®6ßÈÚ*®ã]sa‹žY¸VL쀼8}ti˳vþRœR¿¼u¾…ôTAk«”À˜,|3€ kYëlö98Rí¢ÇÒ”Â4Uºám2§±ëÕç¦D¼„Ý3}뻵wm²Å66ØI?…eþN·*˜k` ºŽ9ÖÕ¡´°S—ÚÙv!s™]œ’Á€ U4 ³+Ûf¥1j)Ý¥”Q}jejcRÂÈnt±ÉÍQxfY¿oI,¦'‚Õu8ÛI!°R¥ÐJ$ L ³Tô%¦\Î#ë7[è£"{§d'BòGlŸ³ØÒ'8(¸@˜‚í|V_]xSøM'ˆC$!( ÁqEjø ½!®¤ctޝ«½zѳ×6›•Ñ,yn6w°éþ*oâDµÎçU°Ï³oIo')¯ªÆw³÷”XýÀæNÙIAü¤Ý›y„Fˆ¶¾ï£èÃ(äh–V³õÜ€è?þ(‡Öâ§Ü ìIûÅÌ.#£ ]+Yg×ßþu†ˆ´YIi;~蓎Å UÒ‹(5^õ*£Ý®&öZËÓ§îZ pÔî¶Y iÏû¾ïMõX¨Ј.ðê[”˜‚Üç%g¸Í˜GB©Ø0Š!¿[Á#V[ÁE‰öR¹}¤r/Üüîê™—Tí5Önâó(,dJz¨¨Q ;XO˜Üf-ÒÐãâ|ØÃÀVªuD2À%Íç>ùRGpÓBªªŽÁ-ÒOY½þ®a¡k ‚-¸ù,¶%äœ'Uh¤æhÄwÊ'ñxçE wЫF¦G ÌAwšîh†çÙR0RÐ×a½U$ðE(z–‡yPw°Ç†çùj$°æ¦a‚a’`^À‡–஀ Tì@6+ØÄè"ݘkuÌàkþCEf°íý8o. þF§, ïÊ2Æ­°ÆåjÁ Þ ¸  RàlfH²|à> §, n+¨a6 –&ö ®bfAˆr@9nÀ nwú€±âs`°b~ ê+<à ƒú`tÀñPù0üð)QSþ…ëpñ0÷q Qó‡-1«0Qûðq qQOqiÖáz«H€¢„Áž„Xìãåfk-@K QYZVªÒ - Ûï󬑨,èú…^ø«V²ª Š Ø s¤Á•ÐéžB àJ­Çä#ƒ~ð‡Q–¦sªg±bÝ-Y…ßVCéñuò ª ý‘߃ óû"¢ê!w1R’"q'rã0§Ž^ö ÒF[Z¤­¨L¶ºÃ)æ[ø&U’‡ñŠPæÆ ÀG;OÑȹ2IÖ¦ Vp€g0:GRÀþ0°¯J9b$O„=œ29^eVOZp¦Xhg(¥*©C*¡ÛòäYºrY°2m¾de cõ¢gÀÒfÄ’*­ò(¤2+Ñ’ZÈr] ϬD†xâb³Xo"„+•¼¼ãk>ð)<à6 vlG|n°*®=–QÆ*í¥j22—b2Y2Ý‚ê/Ä,€¤¥&`X–Fso9öA{0 ç.âŽcäH66–¬6Y³)\S3c£2!.6hsRç "7ÿm7S3­8S¿„“6©øRB|ÖaÀ£'A'æ˜PshI0H€‚´E·LÒ#`ãï‚8ÃYôüŽÀÒ,)Bb<'bþýåß~Ó6j32œÃgÖSRòÁ=‰‚Þ,N LŽ0Dâ%ÓåÆÓ¡lÃÀt2Ù~J°3HfÒÈʰ„Müj B'ô2…«3Y†·–ÆÆŽcRbŽÛ a쀛ðhsB’^Þ^ÊZ(&d(Æg€/[p* ø^$dÐ æ~ô*‹åó*^Ѓ1uªb$LÎ-¨‘^”¾L,À’ÊAË‚%UMç°ql¸teÐ’M/²„¦HjÜ–ì‘ð(úæWHà ªÀ ¸À 2¥>ú yªAêˆ?à~`Ã:€$3OŲŽ£q€fARÑP÷4&@O#"Q0þUP uRµò„OëèR%UO±"P;¢Ì` ªõxDa&‰!>ÓŸJtèT(ضÑK³kç†î²êÌ·úçÊŽÕK­0ä^æàkÐŒt¶Tó+%°%J”0œ¼à *giìQ’µÊaÅäð'=J¯sžB–8ò”Šg—ÆäÒ;RxìÔw«–”C}’GxNÉ^;Ç䆿‘Fø•†a Φ>J´â®´Ûxm®ðeMW‘uçÂ4W­ðÍ@%ô†ÕóôMœâ°¢)m0•?êdh¢Ö` D`iTp¡"ûff[ÒðÞEw:&С6pfiä,õ*mþÞ Rr6mþrxˆvk'9Pô§LIv„¡†ÿ¬ÖX…9HTȰCZ³¥0VÙ‚U 婿Ķª8SÞp ”++>,Ϫ1æzde è€aªöÒ!<‰ì Âd!À.dØÂ¨r«LVopMN¨.pp wßø$w.½î¸Ü>²ˆ–À¬àðˆ^u³+9 +Kí‚XÇÃW˶¹¦°K 9>.µþ"Í–cÙPv>Ñ!Lâ"_‚g<ó!¼çühbCfDfôk; §-róÌ&,1ŽW>•—8·”-ˆf\ÂÃ:‹\g0;ç(Ä7¯ m0—ÍBóìl[¬X‡ÍþCM„õ¼´Ô}‘‘Ïœ¬WÉíÍ|æªò€€–q;¬Õüm·bôër£ ŒÐjdäb6®à o)Bf(¾$7ƒxoáÂQ.˜t$9¹ÎLŒ^R+üS·Ðø¼êd5”­:¶y7~É)\Xza¸Ó²ñçh¸k‡‹Ïí-´"vq)”ì&ÙtK[D%+”BËÍkm2†½m+ºƒ[˜7tä¶€RIta÷‚8+Eè| €òÄ8ˆ†Ô¼ö„å…8×·ŒW’9Äx-ÈxÎôâ/Ï¡ä/×ø£žã[<èðX­>³M‚Ží˜ÔÚXF°‹ñX¤zì/Gk'ýؼ ¹ yÑôK/Ùþ!ÙmÊwÔ¥þ49òöíPR"“»ì…g[:@Ð@™.~!Ø0_Š&CYuÎ)þ,9TyÐlußpBÓyå)>@:¸¥i¦®—)E±æ¬y§.6 ™Ãâ]àðŽ/vš‡ê™¿$š™Îj˜9`-›¯pe¥yœµ¹ÙÒwÄ9Ž9Ó)LçœÓâE|—°f9žÃFÏžM¹ÆæoŸïÙVšñA:ž€NDÅœ«Œ¾Æ›ËX[ÌO :™ˆ9þYÄæW€ê¶¡ËXHLGX%Ú’°ó/ ‹UlºÎÍ¢úAšÏì¤;EZ˜¡» bÕ¢_z7§§>ú¥OJZk¥þYºÊŠ‹AS:žÛmCC{šÖŒµtúÉx5×ìV¢3˜ÀzÒLl™Zl™XØ‚ª­ÚÇxRþ¡F J ¤«uÆqª½º“Ì*Òú-Öz£m7‰e>ª!  ™aã­¿&s¦U® †®g¢¯ÿ:¯-Ýlæ&’cd;Ž)E†a‡ûtèšò$°™«JÄ)t+±>›•™‚ì ¦l4ûŠ{´ß¢™Û¹+¦:µzš9ÐêúÖµýÇ–ƒF¬o{ÍÀ=ιܷQ4)¿¸·kùñâ¸M O¼øªÅ丷¹};BÚc¬{Í΋9({ÐFøBÉ{»ïâ&×´’‡k¼™ú½=‚îÒ;k Z}Ïz¡ ¾[ò˜é;l°t¾í* ;commons-pool-1.6-src/src/site/resources/images/uml/GenericKeyedObjectPool.gif100644 0 0 127600 11701070263 24576 0ustar 0 0 GIF89aíF÷ÿÿ{{{{„{„{{„{„„„{„„„”)”1œ)œ1œ9½Æ½Æ½ÆÆÆ½ÆÆÆ÷ÿÆ÷ÿÎÿÿÿÿÆÿÿÎÿÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,íFþ1H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€[*Ì€°a…NÌx±cÅG~,¹2åË“3[ÖŒy³çΠ9‹þ<:4éÓ¦S—^šµêÖ°_ËvM;víÙ¶sãÞ}ÛuauN¼øZás_μ9Wåt¡;ŸN½ºRér±[ßν;NärÁþ{O¾W¥M‘5€Øoƒ*Æ¡‡Š(¢ ( (¡…&Úþƨb•6º(a’)êhzjéd£’:ê©‘¦*iª†ÞÙ'}þ®ÚëE H`Á­àz«¹êê+¯»ö ¬®Ll®äjë®ÃâʳÂöš,³Ã.«À°Ñþ:-µÁv+-±Ýjn³ÙŠË«°Y¾úå¬Pâtí¯Ô -·ÍÒ[o¸ß{/¶ñzko¾» ®¼ý»,¸órK0¼ãzË®ºæ=줻û.l±Â ×û­¯¹ \p‹›m¯¶JK°¼å6ìoÆ*WœqºK)1‹91 ìÀÇæŒ¬Î<ïÌ/°ìóÎ>/[îÍ)k쯾=ã:tÇ(7M´Ô<;sÌÝ]ý–Ö1 ðÂÿÚ+6®Æ=¯ÇØ¢ÍòÔÔ¼±±ÒÂôž0ÝuÝrþ³0c}$×T~WÙð^ÜpÔþ}ëÌíó®ß›«Üs[`«ÙŽƒ¬kåã"4¯p›Ë°Ò*#¸ßÓ¾–ê ½+4ÕSÇÎ/ÉX²™CŽóãƒÏí±Ï·ßrœ-µ²µÏ]2ìÌË>5ë¨/=ZÓ'äºÞacoy´sW>ù­P,¶o»ÜÌV>å“‹¾ùÝS^¹ø½ºïþäák=Øÿö=’£¨Z•¥)Em*€ •¢ШÈPU…Q`¡X*FP˜Rà¤HUÀßPÐQ˜ d€À *R`dúR=³´ð>¢#ÝÚ2Ö±[uoqßÃÖülè«ü% ~þããUæ†hÃùÉ«|<¬Ÿƒh¾Éðp,³@õ0¼ÎY1o¢;Zµ²xÅŸëk2LYÒÆÈ, xކ]ÄWC†«^çO5¹^íEŽÏvÁRÞû<ß ¢ qÇC!Ê/‰xÄ•ü¾7-ùÑ{^¬£á>VÄäYuÜ—ÒzFŒ9alÜ[Ô:¹,Åy²^Š‹ÀFg0~¹’ÃbÞÌx+7&Å–0ʉ%÷I:Î@Äã÷Œ…¾BO‘È¢1s·Ìd “sùó&P<¦µl’×ÜÕ}ÉË‚/›ý²Ø Ç,SjëqCÙȈ5|™òb¡t™9»)6ÿ¹—tþÒ%ðIOr*îfî³5ÙWDÐýQní3¢2 ºÇòêœk(1‹yHbýnŸ§g·ì’k9¯ytû¨ì¾†,U.íxÝ£5›>Ž-¯‡êÔ$ÛÊ)»œÍvѲ>²Ó¯ôt—Üì'/ù·N;Zn^&­×+u'P› ìႪ59T~ºL›1yWFõVÔì…ó¨LÿÒW¼í©QaŤú„UÌ•‚.giÍä¾"ÇÕŒ%€…p¤É.GWU'šÌ …#MÑù­fŒ–=$W,Á*,æ-¨W•ä­8 *jT†ò[*F¹EQt’›Q[kEñ&¯µ–«­ =ª²©¯µB.­ SþlgXFjQvuy P{É[h]à‰ªÕÒl /ºÞ,X£ì¦`{ÓNJö“¼¼­G< RÙÉM|HÏÇ]³žô£Üýãù¶¥Ýñâê`}§kÉZÄö¡¼ã-ïL¿ÕS¢ÔIÛ⯫+þ¶2[/.´èÚR䂵YA+*Êœ`ð…l¹þ-pÑÎU[d‘Ôiܪ&õçÝŽQ”=hõˆ>ô•¯­%î#l+úá5 ¾®!MÜ]û QÅ2ñû6—â€î¸ÒåPne"GNR8Á Fêq—;Í~“¡e›–xÙû³Ÿ˜±+K–c…e´¿ ¸©Ã%[$‡dŽhõŒQcëþ"»Õâ‰rw}®MqASþ¸’|,«Ë%«µÉõÒpGö¬ÀÒ}.¥þ­Orþà¿1å…q0Ñ$Ã\«‚¼²TȲJ}åw?3xó’i'3pÌ€±ô:ŠkŠ5E{çlsH‡uxYËBKÖgSGT†‹£_™ÖOp(„|•Q˜mþS3’GaŒXiÇFÀG‡}gX>£8jƒe†8fSi5¸x!c‰DˆEt%XÉÕ+AxYçWWˆŠGzM†1j(Nhh‡«ÈŠ„h8Ù¢=¡‹VÑS'4Ad(¡Ò*DŒÆ)‰Ò*¡b)tB•B'TŒ„²ŒÄHBÐø ƒBÓ¨  Œ¬B)ÇŽqýG‹©hŽ}KÝE.AC‰rG\ãb\ªxŽ·(kc…^Á‹x¢Obt„üUC8ˆÅ'…k(W›}³ˆÀ•Fgõ-ø°6éx‡ô¸Y+hjN3ƒ+gvïLn\Y‹V5I‡(&Xø^3‹ŒC"‘d†Ãþ†ŠæJj”,Ç;ÙÆR3|R–†.K 刎Y”´èŠÍÒfüæv¢×kDù”9’¿¢:A•Sá‹Æ…k†oˆDÃ;¼„Ö6E8 ˆ}MPäòx6SyI•F)—Š7[´W9zÈÖ|s)’}9€Î‚ˆåá‹‘,óD}ÔF†Ý²<Ε|€fCF4õ€v#ywsu`úB^¼$‡Bu}šÜ´id—;†pLÆL‡ š!)šX„.‚I?5&„Ôhà()·i¸i›œñAÎ8 Ä)”Â@âX¢)”Ò($´ŒÂ @(ô(Î)*Óy(Ïh¸9†þ’qÛÕÕõÝiFë5tk…‚-ˆP"¶>¦~œéî ž 9¶âj{a•Rá‹Ó–|Ø…G_5GZ†¨F«ùdlƒn\TEºŸ°IŽS¸UQ¨?cUWÂ׆ÝÄ;ý¶š *6*Kc£`öy ]wVú¹w·wJ•Èj^µOÆr¢J¶¢j¬£9³Mðùž8z£½µ™²fequ†:š£BêEÆ¢qt’.A]IC—Š•h'âJaT~ Uz¥´¥+A¹ȉœÀ¨›¾)‘*ÙI¦cj¦ÑxŒàX(hŽ­B!”(×ù¥bš›Õ9Ò©¦Ð‰Œ{RŸHÚ6ƒeþ%“dï‰Q3E¤_E  ㎒9¤ª£Ãâ™Ú¤7e©—ªEŠÉ¨ŠÙ¡ké’øMb˜©-ySZ¥oe¤z¨,á5 3}ÚÃe¢„FÞ¥¡·Om“Xú &£¿²¥1¨Ê«{žz¬û)y²jyb&€Æ ¡­ ÚNÙ›ãA˜Õ'7@sYÚr )y™³…G™ÔRVl†ªÝZ„éj¥‹å™ 餗YãôDç‡3d“¥ª•þ(¯(•J¬œÇª+¡UI¹­ð¹8M;£•HlÅR“S˜ÓBM»³8ðJ‘z±ßiPË SÚš ë`9£Êò[Û‚6;£Ÿ­i‹Yþ‘pSqÖª!ü¨;áCë_QVNÞ•9 F>È”C`L´w$6Ë«½:£I»¡ž´±bœÊØAt*Õ)Ž"D›kZAž‚A“œœ‚ÒøŒ`*))ä¥c›¦£"¶}Цtжª’Ûi’Üi+[Éz"·P5vGÅdö&}‹ôiP¤lXú®ë¯Îf£ée~סЙ?92§*•œÊE«–˜ö:‹d¸©…3NÛ‹«Ô.v I;”D„d;Ç4HÄsLa8?ACD‰”º…””I/Þ#~ù±ó8:¡›˜$xÅ*­(ZiF–4š¤˜ex–ÈjF8„$k¼ýþmr›ˆtkºÍËG/ÆsærÒ´P/hl¬û³Ü[¡ÆT暟-Á‹–•3K%´ʆSê¼th<Ë®ŸÊ²þ’þû¬ñ{•£›¥›XÛBD°»C­ë;eQÞûºÄ´ˆt¾µ3Ì´/áê»qé¾üDG”êWòU5˜ë{úë<5¤®›¤.Œ±9z^R³YÓ}Kú³/xk…$±És:¶P¤wž —Gˆ‡¾¨ÂÌšÔB©SSV¡<úwdÙ„Ú³<8|’ £Ä:¬ÐÚ«²z+w•½ƒ9³ç4`¥:\û?‰Á50²š;SVó*•¿KÇḚvºêE<_`µÁþN-(›>OÊ­ÿûDØ4Çݺ¯‡e[4Œ#6<™µJ sQË{©?*FýQõÒÁPyÄü—0Âyd°”çžMt{ ›°ŒÓw<‡t=÷º­[cŒxi€kH$3ƒ_·ZTÊ·ð*Àÿ›È‹ŒÈ3©ËQ¡ªMÁl¦ÐƵþÁïÆ¼î<¡ÊdÅô"0̬Tž…É ÊŒF"-#)¥H×ÌH@´À<ä;µ‹ÁaÔà£PÞëL›/[ÆÉ¥Ä9=«IL:0+ƲÉ¥ Mç*È(ÓD€¸x>—9›”õ8eå1ôì-kݾvŒÓ‹—L¥lù¹Ô z¦vCE¾Èt—Þªq8³EæÚ²!<ÕL…ÏÆ+;ý$Í&aÖ ÕLGžü`ådš‚D–Ì…DWÙ†ÎRmЇ-‡œy.ç,H©;Á¼ÍÉ4ÁE­ÁM0æsªH²ulØ7m¯U¼|@5»7«tôw.ì#z¡·ºÝsx,×>õ~ ÄÔ–H¹þýÖ‡½ ()€GóÀŠ”P5 uÄ EÈÞëXu\P,̤„Ûo]…ðl]°M¤Ô9t;-ŠÁ§Ô¯ý½çëÝý­Ñ$[¸çxy$Ú¹-Õ‹-ë†ðxÍ[Ú@#e¿C2Iðö„ ‰‚”Ä+ÊŽ‹¾’à%ÝÛ&±[ÊT?ÛM{@,Á|»CKÍÚ|L¨·91eÈúUÛÎÞ†HŸ.1¼˜¸2FµÒõëDó[ÿ)&Ë*èføZÖ2É„ è:þÁ•—JÖ³ÜTwΗ]‰„É o•Ȧ^˜y`×kÛœžãRhÝm2å€BOƒd@‰ÌŠN˜ž6È<ž³„ŽÎ—æ®IëóFÚÕ¢­GWår|V*W_üÐ_.1…WÓlÖ²ŽŠŽ¢³Ûähè$T;3ÈÉõ+‡GÙëcbC³šŽ5»™jãìäÕÝ/"ŽIŽ¥Ðư¨i%%O!Ãqç‹^Øï #Ù_T;á>ÝžØqÕ×JÆj×lÕ¾"±*jã*¥e¤ÚQÌ™Ì×ÉN=H(?ñ Ùæx£ÐŒ„åÚí¬wâXžº(»d_¾äÜtǵöчãIÝ ÿ«sOòÜr¦\¬Ë³Ú†OËjzdįj.²,õß,Úˆo8ÿÞëÂÄÚ¡7ƒ|¶óÒMé†o»³v»M‡c%Þ]]†-úÐãþþö·­ŽW-åÚKå²Z³7‹`"»ÏþËÓ×óˆÄÕÙIƒÝº9©üO.îž®ø ö„åCKüæ¶[± EMáæi˜ïC“_[¨›Òø ,HXÁÂ*L((ÐaÇ #J|h°âD‹5nthÑ£ !EŽ$YÒäI”)U®dÙÒ%I/eΤYÓæM™1qî<©¢G´°¨@I 5Z!)Ó¤œ>U¨ôh‹Pœºt«@ OÅJ4ˆ¢Â²@;F̸–-F¸ϺµÀ€çNg±”*‘àØƒ¨Mº°j¡gíˆÐªbªŠÁŽ… •lQ†=2Dª"]ÐþŸCÏ]ºígíÞeÝÚuK¯eϦ}3vmš>ÛfÚpkSÆG…3½L|!ñ¯“%;Œt¹Ñªo›>ì›ziÒÙOk+×àjÜ+}^¦h(ZÔåI§¾X=¡f…œ³ ç ‘h…ó§/Ü}}»éîäâ.ÀÐþc¯‚ÛÂSpA”dðAyr0žD Ž §˜Cj0äÊzo¬÷£*Ä¿¢£1)šŽ¬ýÔH¸õÄn;el < EÊ ¾):ノ83l-óÊÏ¡]të1·lR2·ˆN ¾b´1.k¼²IÕrô2¼ ¿sÌÂS70´.Dã>4‘¸«šZ: Ýþ„2D(¡\’=“Ð;,G;m7Ìdp¼Aã#ï ÏÈãs.®à3Œ+ÎΫ¯#B3{«¬ò2ƒï>N4Ë@g,ÕI %sU—TeõU0a QAëè)ró°¯slC¥¦ Vć «² +2‹G¿Š"tÔK4SRÀÕšòÒ´>:5«¯ÈŒˆ²´!‹0Ô´!ùèr/%<—Çq‰’\­TZ-9:°ZYûU [Þ àÑDÍ¢m«,ïÛ{=£Ô! <Ú,ÏE!VO±G¹hÚhI­÷Y~ab¤ï¢5«  “ C KîRaVUþXäë¢q†ÔÄŸ Œ˜.Qþ;nØcÙ+Y`¤ Fzé—”~V‡ªü9@©ÎݖѵªkÑ& ÓîÚÒô¯KÛz/ß¡Ó6•À ¯ÅÑi—ò‚H×ÞØÕ>¦.2C&à'°$,:ÍèÔK>è¦^¶1³+úO¡×&ðB™¶¼ÌË38`ƒ+î±­üÄ•hì™ÿìHó&µ˜½©}$íHÓ ü_Ú d™_B†6EU¤ 7¾8uã‚ìq.?…4I‹çÊùÅë ·/Íã+¸@òÈíÅ^röv×üéïßÉ{0_Žòý?+Ó¢·åÑé=wz‰Áò6ðÇ·çXÿ‡+h@¤Ü|ÿjBêæ Nþ"b“U(C•©…AÙuIJ˜øébþ©´ Ç¿¸xähâ; M(Îy&)ÀÛ èb”o± ^›ZÂ>e¡ƒH°4†›g×än%vÉNŠÀ‘!Q'#3âȲ¶”ç'L¹“àÒ×™«dÑ8‚;ß®ØD<,6ŽcgóÜþö—?´¥ç,<¡lØØÆ~½q6Pƒ"žnÆ.ÆH©1äÊÌP¨ƒ¤ÁчyôR’¸bÇ>m©‡fÔRFÀ32Òf<ñ;$•ªÆcIQC ŒŒ±ã8Õ XôÍe°ÂÁ;ꩃjÓ^+ç³/8¾JޱdÕ,_Ó¹½x )— E»ã‘…o]þ\‹ 7ÖÓkÌ^þ)­Ñ%Èm%±%Lʶ3è±IzΊ“5$J}KNKá¢&ouN„!“HKºØ‰Fw*i„´=cYÍÖБ?)ãK /¨8}È\à s«†Rÿä`â6Hµ93ŒàÛ$´%å>¼ä(½2¬`QXTÖò*ãIê›3KÎ;W¹=‰RŸöMá8S“5ª(BÙͲè4NæDï(aa^P×BÅE!`ô¥­.B(63ž>¬œµ„ˆS ( Q.ìØ¥VŸeî…YèÒÌ8ó•Œ\M;ºzßfþÖ#—Nõ™[¡M¿„U».¯8Ñþ'92"ßX§3r,~.(Hp«¤ˆ™”á0T=G1³‡ð”«°•ÄÙÈ­HÜ‘”×¼ºNFíE>6Ü ã:%©§O-j/ãúZV>+#{ÍkƒjKBÚÚ¤sù™W›TÔœÓFÌ‹V ÜtP"áFÈuo³8¼¢Â5uÇœ+lSE&ÝT§yô‹È¸LƒŸ·”u³±Ãšk‹Ù$‚Ì ®Ð*ûÒêr‰"ó¼­ë¾ÜÖj÷;äbž¢+Ä÷¤€ôhI?z«þ†Ô¹*^aÚè1ëQñ¥j~U²£ Æon ›Î*¦ÝŠèL*%‹wÛuÅEEêsÖ¥0…ayßCÁXsŸþ½žÕ¼úáŒr\yž{sÈÍ7„eæ3Jèúé–ù±²Öýv…‰Ð”I˜µ©H~¤t 8J±²²¢¶ÉD¦gɱ…o¾º'c½¢ùr4ÎÉÁ(¹© eMRß=o[¿¶ãC¬È‰üj޵6Õ‰¢Í'‘›×øÙ·isΑ:Ÿwÿ2¬o×»›snŒ\vuÙƒT%sغ¤fÜ Ô¹IáœG›>µ^ u–|0«q¸5‡­Ï’ñ¹&j@|L¬¨WªL®ª˜0\œßq¼|2diÏë°TAÞ#Øxö[[—'ªcnq ±ôâQÏ1ÛIKáz4¸å­ëp÷S–û"«FS[Ìð «+þ©½?ú*h’$EÊ.‘å¡vÓÒÂ*pdž;æ8å`ÌãT½g~tw™¡É§xo›Ô÷—¨y‡·C7†° Wˆ“ìã'ò,5_}rw¡ÝÖ)ÉŒÓ>´8I4«~ÚíM* N(ýz¶qƬ›È\à®N©Âí>Ôp¦vLß+_Qü–Jc·Ùshô5éz­^ÈßÀ Úç0Ï>½‹ÅGæ ù"´öÑ×Òò‘Èí}0úè®°8=å(%¥¸Œcé„8¦“»ûZýo™·²èfGz¯™.¡Ãà íìxX‚=ÊÜܦ;KY‹»á·+7¹lñ¬r¶¦§Í¦²,.û§Åþä±ã¯¸?sëËùµŸëŠxK…XÜ÷‰¤ãø,ºš×s´:C^oºôè‹xâQhüU-ÞZ;ŽòYó”55p+¢¬Ó@ªNâEf*(3CÑú;Btí+Ÿ«ò1ðkô\fj¾ŒeŠLð°@?Yäñ¶NXÒôQ1³ƒiçì¾2@ì*5È8nŸú½¯ *°Â»¢ 0h³å (¬™Ž³â¼AŸá[¹¤ÍzÕAòXTY»úOc+É«³´R¥ ñZ§4ÊÁœ«@@ÛðÁÓsº¼<©ÐŠ÷‹Ê@“ˆ;Ì, Ñ”[K=™™Ô˜štŸÎ#$lBC?tÕE¯Û5Ud¸«D=äCäƒEjB·£Ê?KË9°‚0^Ñ_„¾ø›"ùBZÅ-äW¼%z¬{ÆNÁA<‹êH«3ŒÆ÷²ãÄ*Û'1:dœCô‘Å›ÒÃ!ÇYÑ)É;µÏ±ôkÁÛ yù¾lL?f{»s£Ù )-•“Äþ•et—C™]Z™tû– K“[±ì‹s‰°Ð"$ó#68£Cܵ4ÇVñÈ‚Â1„¼ža­DI,cCòR7>–Hlp{b¼›|·Ó0¿/¤’˜S²ÊÛ”Ki.+–Ô›Hû7 ‹º,’½ £·½þc8q„Ê»)ˆôAtdº«,“­j§m4Ÿ„ôJª£ûÊkK3K±äJ²\K´ü–Ÿ©€ªd¼7]r¬íÒÆ›1¹*ÍÃÂAÒ¼¯ ˆxAôXœ‘Èî²4\;•œC£É„Ìó— µÅdI©—ÑÀŽÍ¤.ö¦Î MÐôLcÃÉF1 ûþ~« ú9¾A©‚)‘ú#8í›Â„ê:^ò¥plÌ„8Éd‰¬¤¸áì«¶dKäÑc*‹5Ô"Eu,W²éõ2e\ŽÊ¥¦Ç£ø)AÕÑ£(B(åR¶Ý¢AÕ?c) ¬µID q¥élC¿4!Ì¿ƒÇ2.¼wtëfĺ¤¹&žâ>†FvÜÔ’„a¾G¿‚ËŒVëDÙgÐÖÞJ!¹:êà­‰âðë¥ÔnøÕ¨)L—Œˆ_ùn²àìJ™²;:—!#¸ÃIEÒbµ½™5¢¶¨IÅÀ&N±ë2Mã*çqµt¢c$ƒ!vl7euˆÏ®ît„œS 9æF´8­EQ0ÏødJ–‚{gpIo<#° —¿iôŠg’ŽûÉbƒÆîŽHââd”Ê'±LHIèÚDtÑqûÙ2¡žj$copê†p˹îhPÕAþC»~DæîŠ…‹i‹QŠøÛÑýsïŠùK(D¾¾rf•~KI5 Ùo?cµ';–1¦0^5+Ë+a俌Cîâ†(r#_šI’a¬ˆº?ù‹Š@¿E㢊ô6tµŒd9¬z¦ ‹\¹>0-wÉJg ½+Œ@g B”œgíy ·Šꦄ¤žÈ xK!ËË›¶Ÿ²hk¯¼2TWâ5Úst ãñ#¨”R0w~Š?ÇŠ¹{ dv¿ãú*v R¨&DnB¼>Z“l¢ ºt9©`¶r;8kÏ7?õu!ÞíZJì8&lÕQèî¯ÕˆëÉÍlþäc®IÏq’G»ðRõ´xÇò£†e‹xð=¯NOv9–mÏ7ÛDiS  rn#äôwþô®Ðð‹?,./wG×ðqÿô%‘èñrŠ¿•¢$ÃŽÔ3W¤â.jy:#ü«±‹0‹Œv_ó‡÷öÔ.&&a txÎÅO28Cg[üóÄømÇ|‰îþ&Ôlxþ²ž3OûÙvC=­[T‘'qA¨AegtÿjPFÿÓâ‰ÐM{@ux‚C#¡‡p¢/íÜ.I“íîP«\CÔÀ,.35v;ïU¿áH¬ŸûNöÔ’«5z÷ŽP×hu_¨’ß>Ôoù­Örjox®÷ðàZßwúâ>ùë»Qf0ÔW¤à¯nƒÏgþˆ ,T@p ƒ &dxP`… „(q" *¼Ø‘¡À fä’£Á…-šœ˜°e… >”r È:-L(Ñ¥N† 0-ZTѤJ—2mꔩ +_"ÌXÁgƬK˜•«þF `1j,)V£×²_Ï:ô¹uíÙ¸c¯†5Kr­Ù·UÕêÉõ!Mއ>-lø0âÄŠ3nìø1äÈ’'GÝiò¦Kšši¦\8Ò#fž 5?ÄIQj` ˜:½úeEÓ sŠÎœ¹³J› q¶Œ·jª#‘BlÜhå‘/AšmÞUaÖnå>w®7¯Õ¸d¡‡Õn!åØðu»K÷îö¹µ¶,˜ðñøòçÓ¯oÿ>þ¥ ¦¾Ìø§o7½i¶é&‚8“GÅ6PgX`AS…†fÀQum£ý¶ÒÁ)·‰À§qù-iqd—sd×wY À\gÁÈþž^ë±Ý[|ýdZÕhÕ ÚtiùT¤Y=YE—FPÒ–A–Ó@)ªø%˜aŠ9&™K±¸%š.ª™&›Z®éb›q®)'oÆY'žvê™§m{B”’—IZæR œ¶áBþ±æÒŒh¡† œ-]äWX#¶¤˜FÊ_h ¦ÒHÓÕ¶!H z*ª©ªº*Š 0 €«°¾+­³Ú*+®µæz«®½òúë®Áú*,°Ã[,²Ä*{ì²É2Ë@ƒÅjR è¶ç§Œ&Ô¤i¨aXÛ¤Nž„©K“:¨H±9ÄÛàƒG"j§BÒR{/¾ùê‹î!ú/À <0Áþ|0 +¼°@öbà0ª¯J+´+­ÅG;1ů6à±®Óº±«{|ëÄ)gŒ+É+“L2È+«Ì@Å%ËÚò̸Ί1È4_¬ë¾A =tЕAj™„‚%½4ÒMgª´ÓG?ÍôÔQC]5ÖRkýiÃMA|ê™.êØ¥¹û´Ø$‚–í¿þf¹[‹ YðÜè–8b¤H4ß}ûý¥~ò)8áƒ^8â‡+ž8ã†ïœ¾Ö†6¯Õ¶]†¦¶‘ºÖgf7Å;‘¥¹mvÞN\‰ ‚HªKÿý:ì±;fô¬×.Üí¸çî[î£+ì{Á4¹NÔׄî÷!ÖZþ òls¶“›iþ#èç¶ñ&Ø·x§ØM×f*añ²‹?þøÉ-~~ã飿¾úí³ÏæwÃ?9®­õ¦o4.ˆšs‰Ù»²U!é)$Bß!—äHàoãÉþ>e@ÖÉOP$3˜*fqÐYl;Âа„$<áS(2‡…L´;àlÚ¥;ÊÙŽ†’àwd=slt:dÛ ³6µØ|-®šŸ“¨Ä °!k»áî› C¼Þƒ° fq`XlÞÖjç/ÚG~-S|v+‘Á,ekcÇ~¦F›IÌrTÙÊBFÇ<Â±Ž®êããøFAîÑd6ÛXÏ4¦H\AZþ["$# ¦3i醞ºÚÖ¨†«ýÇ{“cP%1I®ÿ j ´èF)DMrˆ ÞKˆ#G.– &2&µ‡¹˜„ò5 êTÚt)Ìï¡NÆ´œruDI²™Î¤Ï~*ôCp5üÞµæÄ;úrQ™šTÉõ¨MqM姯éJ(>Ð$,ŒÜáÔ ´ñn{õLåØ:ÄcªóžÖÔ¢ Û†ÿÀ'VM¹à3ªÐÂÐNt»™!€þ™Îšm횦Äf.zi£²(ôú§Jn“SÎSH,óu¼Ìl”žI¥y§O*ÆTy©=aúR˜^ )ËtJŠ J‰å§%;þÊ«ŠBTâ•fHMÑRÖÔ‚&u¨FêS•zUªRª[EjWµZP¬¯ªˆª¬ÀšU«Ž•«k=ëWËV¶Õ­eõjWqY£Ú°„€8%©T&øÃrÆÐ$A]ê~ø9yþ“Ÿ "&@ Å”¸('J)¾(ùÑè¹O}¨Ä¶"ØÙ÷yv mõÚBS«Úï~g¡@¥V2@{Þ4QW[W€î†‘†Ä+¶ìÌ¥¤&—­"QtM¬í9wû¯çLäù2Ÿ¹bËÙêÍ©º¤#ºN=WzȺÇüîu· Þ]b7sƒò3W«Þõ"§t€môW—¾äFêËA|KßT2çm<ºŠþ…0·‘%/Ÿ-àxŒDÎüæ–¶øåei‚ã(¡V¥ŸÊ|G0 Ó”À Šˆæ™·F`¦gNQìω˜ *^:#{cœDpñ½ð}HXˆ›Üýn¯.Mœ( »–žTåRe›ó+ºVçÇ|%€KÚã[˜ -6“¾Ì—C±Üø¾ìtQ©9KU*€¸É1t¶7£Uq§nn0ùó5ƒ"TÆvÖ Ñ4óÞîˆås:*°£¨´Û²¿Ì ƒ‹t—%è+kö/™«´£Ø~E+•²Œ~Â"‹Å£”ªR¤•”`wEÒR™0ò å `ö^aƒn,Å4ÑF$VŽFþˆŒÛ>ú±·^NAº#YäÎ—Š’-¶ÞóÓ;3;’+=õ½Bæ­0¿Ô¶v”±BíE»ÄQ7p¶IríóÙÚ—ÞvŽ}\히{ÕMÞŠ´uTî«H"ŽJ²vÔ ‘P–ŒÝi5µ´ÜmYË—Ðt9 ‘àbâ–'-þ}N”RîG¡:Ξ8r3þ’:7»ãÍx·e+ì7G¹•^Ïnémòü~%ÞÕi9¶ÑRn™§\æk‰øƒå-îkC¼.ñÆq·UäzŸ[×i¾ni*pV½š9²îôEJî"[»ÓæþÏy®gc¯DØZvdÞÓÂØãf×೟W¨g{9÷¾vÑþc%çœ9h1:FìÍ@æö|åUg°tªrzáD?%Zˆq•O]ßç™ÊÄi’“J]9½™-[D(ý’“<ç'ÿ{W¤-d¿¸=ŒØÆ¸Ø¥¬z³øì®_è«Q³6¸PÉçãVxµÿŒ¯8‰<•ª=Ëó"è½øÄè7ÿ³\ k$D£\Çùð±â¯GÞëwSz…/·&†ž÷ãÎzÕ©ª¬·}(ŸèÔWÏõ±§žõâøëã/»•FŸüs¨ä©©]ΑPÄù(=–5Ñeé×qˆ{×r|˜lmD¼dˆþž9ù–GžieŸ«MÏNXš»àd^œıµõ߯þmªê± 6XÙÉ òMì“–‘. !]÷Œˆ~y“Òü‰îÐHÿ…Òٜҷ€Ê®­NÖØÍß•žeZTž djÊ+X…J7‘F6¨Ùú© ÆµàÔHa ¦¡øÐß¿ˆ8éwUÍ¡,Ð\H;ÍTUáé–îJMP‰|‹ ÎbÙÍ£þªDÓaX ¡Seí¦PKèPæm`ÕðY-²ÖSm Ö›%V—``À'n‰6ÎÁÉ"Jb;v–è8#4æc™°®ÁÖkxRÙ,b á˜ŽÝ–$˜HãµØXÅuDAÙÄÕ¾¦ß¶mÓJ® œYDš¡Dæ¤P¨#ÓA"= ŽAâ‰<Ðt e=¥•™¤S>רdÁéÞÕQZŒ„Þò󑙦9ac5!Øñ¤9ŠeDŽ%œU€se–Ȩ ̸ŒÌȑŴeõL¬¼LÆ \æþ ]jÌ[¶%[¾å^Öe_¦`þÑS&«DÓýìY[tÍÕäÊýÍø[ 5ÒØ²EdO–gŽ¡NÞâ:¢Ù‘$bž&jBÈíÜÐÝíÝÜ¥ÁÜZ”GE4™Ëá“õ™Ôæ$N†¦ú…£Y~NËÙ™fj'rýaÔ›PZ»eѹ…bk>¦eâO©\gZÜfòæNþæDEEÚ™q&§yžçQD%vqàÞeeA^åwêÉò&ŠÅˆˆÕ¥‰GýšRþçR¦OJŒ'z¨†bà܉wÅÓ˜!“ì=ÊFÙ”qž€”Gyu•W%a(yMW%fèxa(Zþå–¨‰Êß³c1å0ý¢h­F"BHc²ÎKvd‡Ù(©Ž"cð¤å‰þ(z\‚&Î-‘Óý©Îþ "i0 1iSÜ(”h„v\y)–Æà f$}ñS+m Š˜¢#æTi䙦iG›ÚCTi³}b–Î)‚ž£h¥†.=©žêÕIÌa?Õhjåd§-ª>«‘è])>ª•â¤D•ØÔ'WFŽ©p@XxŽc§n'wö&MBª©ž*ìÐÑ ù‘!ñeÌØÊ¬fµŒ¬¬*\Î%¬ÐÑJ!’ÍjáåÉPŒ¯&R ù‘°+²îÑþZ´Ì £¢ª´NëzÉ)µ2†£^«¶n« r+}d«Y«·Ž+‚’k|€k¡«¹®+»"¦ºfÀ}Èk»Ö«½6jrÒ«aèkSðë½þ+À¦k Ê+½lFEV`ÀWÅÁ2lÃ.¬¾>lÂ*lÄ*lÀ^¬˜ˆkÀ¾«lQ,Æ,Â*ÈZ¬Éž¬ÈVìÉz,ƶ,~p,·Âlù|ìʦìǪ¬Ã–lÉ®ìÃÞlÃZ¬¿º¬Ð‡ÌjkÑÊŽ—°¬Î&ÅÎ.­Éª¬Ó¢,Ð-Õ‚IÐÇÕšèÑÆŽü8íÄ:lÎÚ,ØFìÏJlÖV-Ú¢ÊÙ’la¬-jnmÚÆ­¹*mØúþ,ÅJ¬ÝÞ-ËRlÎ,ͺ-(­Ü®´¦ÈÞz-Ó²íÓŠ¬Ô6-ãî­I¾àÏ.宫áÖìâ‚-ãÞ­ØâìÄ’mÙJ­>–àfÆV.ê>×È"îÈb.ëf®ã®®»*FéŠîßnêæî˜xíäš­Øò-èÞlݦ&Œ}.¿&ìÂòmÈÒ­«é®ó>ïíæm¿&nãÒìÓF-ôf¯öj)íæ­¿Bíãnîöޝüáî©’nçR/ì"lí’¯ûƘùš*úï×â­ø¶o˜Äïûî¯åU®þ¶.¾œ.ÿ0G«ÞN®qàoþ07ðì80GðèJ0ŸçÿÒéW°\îfpÐþðS°cégYŸ0—°J¡0 ó¯ ·0 Çð·š|€° »¯O!å¾pbç ³pÛ0»ò0Ó™Õ±#¡.¯ŠP1ŸUê.1;q q»Zñ|ü aêåwq³Î‡q‹1±—1ÕÑ1£q¿±Ç1ϱ—q´¸g ÇÔqó±÷1 ÿ± ¿¥Å²|ôKŽF‘Àˆ˜"7²#GQD`ñc¼Ð#W²%_2&ÿÎrH2e82#g2(‡²(²"«kea&qRI]ª8¦r+‹©*¿2+qrc¬f,»2.ò,ß².ç2+ýr,‡ÆÛò.‹0³þ/óò1'32÷²33€ÐÒ/§jú_&Ûà‰‘²6/ -ck6o38‡³6cF7«æ7÷F‰³:¯3;‹Yî¨ëñ¼Ë2?³Ú̳=+3>7sÒPéݳ>ç334=ÿ3Aßh׬£?¯¨@'ô@/4@74D3ô*†Ô+7"ÑòÔÅ Ú1ÌÄcÓo* ETH÷Eæá)uH›D•³bäY Ætæ'.a‘Ÿ!NÛÖ™UÉgÈËI_ê`lPä4ð$;N„KÏ9‚$—6M†Øá¡ náVNÙÛ(O!ZR*‰ ÷¥`¢ô¨`„L@¼@‰=5hzd:ž+wê"™ªþ§]Hă|΃dEÿ1XKIÞÝEåPMÈ£L{j §h-JVF(Éi¡F±œŒ”J÷ÉUÚÝ‘¡u-í…Ýõžf‰‰jFYôª¶wòfMuDŽ<Äõ8PdÇ$JßDÌDâSBH  WköÜLßi»‚X¢ç[·õEp‚•kvSIwÚ6¶&.éÆúË‘¢Ü¼}¦¨.*ªÀ4i›£ÃùÄ‚ay|÷¦ðX8œv”ç<ŸUjGªtg{v§P3¡l)p»N9ÜŒX„1©;3ydá<ö†¹ÔæxH_5þ(xð]ãŽ÷_p6oš²o‚§N”ZÈM›ÜþÉ×ÞZï1½}Þ¦EŸaxJowê6Yvªuè\ð‰½øŸQÊy¤Îa |råŒ#ÚÉà¨!šyKwû ó½¤Ý×!um¥„e;æUÞ[©…çx¼Ü[|xïÙöc‹x”Ç&Èg7øñÁ&8Úw}›%…7’Oª ºýœrY»Õdtj›g<æ^yuC–uC¤ŠWøZg^Ž ÇÁu7ÉÅx¾ñÅ\ˆ‡c³ÅŽPGZ´…“_‡Zœu´èž—ÍR×ršo:E=ö¶Ø¶k‡z¥¸ s£x‹ë6ª[Ç©ûv£S‡¤Ïúe;$¨…ßzê_ 9yÉyž‚%Y7:ßþÉE™ŽMy7rI±Gêúödº²­8ë¹¶¼ý¸–ÓÅ•w÷”¸U IªW¹¤[ÚzŸôQú¤{‡ŸÓ`sùg6$±í…î}y¸‹;„”7“sù“7y©Q¹wØ»¨{ â»m›;­7»­—y‰œy»oº‹Ú£iåãÅ$ßíßmÄÛáÕñ™o™J¸g¾iª°¡ÇÓTvÐv·OX‹ûˆÃ z¡áš™Çª“:µ÷ˆ§£z×!ú¾?Þ€u'¦@ûŠH;™÷¡cÎ:eË:èè¶wzd6–/x =µŸ<œ¸…yŸGÔºÍ%}º§Åå:Â[xƒ*˜‹“ (É´]À¹­»raÉ‘ÿb­‹sæŠ (OöÜôgÑ‹öìz2ôà·©G·fýš0RÍ™ž~*5*܃\£–õíÛcÛ¹kË6Æ=’8_¼OÛÎ ÷òléKÝvv}]õá®Lk÷ò ZÒÖY»æºWötõÔ _oí>lå߯–5”>â½a«»'¯;þ´âk-½õ&bêªãäº ®šÏ8-hËÁ vjï öÃJÀãÂ;é<š¤ZèB’L$Ê9 ¢3P=P _Œ‘mt‘FgÄ‘Ç{¼ÑÇ ÌQÈ_tIv,2Ha4R$“Œrƙ̱%‡D2Ë'¯ü1É-¯LàIY<ó@-ÓI'ÅÄRÍ*½$òM6Åt³Ç<›´RÆ)딓Æ»ì3Î?ñüÒJ ý“N;¹,J4ŽAJŸÓi& 3ÕÍC©.´`§Ou >ýð1RCÝT9¨4½ôDX ZQÒÌ8ëð;Ñ$Û5;+[ Ãdzt7üÌu¼`Ǫlþ!á\*°VéôÂÕWu]VÙc…Åv>m»®Sc» µÞ²ý–׳ªí•ÙuÝm÷$h DpAYŒëBQ­ ×4|g*QCP·ÒQgb)߇ãÏàXï.EZ£½‹¡äúÉb£fHãæ¢j,A3¶˜c HrPâ‰mE±ä‘IÞ¸¡¡:>®»å ¾˜eœ‹rùR’gžÙ-y׫­à¢/Õ°D7Ez& B}iU>xÕÝžVš%S~úÓ®Öú`©!vøb§„V9£[9­wí¶›ûîçö ùm˜Çª9®¸Ývlïí®Ï‚³ÑVJí{õv›ìÃë.Ûp¢o¯Ü¼jnÄ'gþ\îÆ3g›ï—v%²-ÅÍé«ÖÚ`©ÎðßÖòZàšò tLabýu…VÝu±7}ñÀÇ«¶ã¾ºå‚ÇÎøßQT\yåƒÇøÛ>êèóá1ªXBƒ<þ%†½ê9—$¬)¬~¿RN¼ mvè‚VÏ‹»{›Åê)ÄßÇÖ ŽòGž*ÅK³R‘H¨€Rñ_Ö×2»${š!Ú¶$˜Ýiêjù2×t×:yPj¸[UïRg–6lw°«àuR¦=‹ÎXýç0ç¼ÍÙ‡9\^Ϫ—<œT.‚.¤HÅŒóSˆ,ýrK[Pò-þÙzÃ⎸p8 «/áþ ÙTžè½ ër™"n˜(FuµJ]KœG‚ˆ¥…g@ñîÄò4îhˆ;¯R¡†j'ª€,u{ ثܲº†Md=‹ÙKÚ8¸$ñ)KDÊS—õHKêQ–´Ò’ø´'Nz ’%(×´I=}RN¦4%&+¹JB9I•}b%b4%!b†ˆ}i €ƒ)È öâ,Æ8d&¦BâZÄW-²Ða2ãÍàÇÒ¼¥}îÙ+н»q¨˜7«A@Ö>ûÔð-¤˜p¢xÃí$ `ÜÔ©*A^ ƒ¬:UÔ°6¡ „žò£ +µÆ¶µð–!ÍÐø2‡>¢•þèD)¹ 4¡›Y‹Zx‰H° 'lY¯ ªQ'r{±ÂÔÕ´&(j÷¼ØàiD¾P­Ž#d)Ô–¶S–*ó¤q)]“f¡Ä´sè„H´8ò8£=.äé¶œ1Š´D¼)æUÄÃ?oÊz>ĉ:U6A”:Ðo–SkRÛÉV͹u­i…ë\¯¹²j¯bá3€…zùKçœ³Š ñ+2uÂ!„0§U­šç9ÑøË¥‘å—aX¦,d¦ 6CYû <Ãö/„¶\u|a3kD÷Ý-zD¹kRˆ(Ÿk¡¥,§1C+CÖͳ kÜT*v¾k…ÝZm­Šç°†J¯yÉeÞþr©Üæ2÷ö F3:)³ À@@G™iDRk™-ìI?صÜýÒ8;%=1UT¥áóuy¬¬I¡¶Ï’7¨óü «â×—UÖ±&•¬I¯*Ú É—jŬ7Üôi’ŸÄ¤¢˜4ÊZòÉKs¢•b´€Q’KSR’”ŽÔ€øH“²ŒÒ…ý”âR6ªI]š°žlY]‹Tl0aq펃ÛcÿØÇ~«€ƒU–W €;èh 9Z«„mÀñ¬ G›ßQQY±$ÉÔcék-ÞLÊí%*NÉ‹ÈW'l­R¦g· ZñšÓÉÊœb›÷õ^)õmD¾HS+*Ñ \ ­üû­Éþ¨…3•Ä>ˆ}ÙÏB]!Ͼ')£ÌâˆJÛh‰„Z-MhL ÅÑÕÍëA0ªìz1ÒâÕ¾bZÚцY¼[æ§µ2çÌj%ÁÀÔ)¾rÒæ^儎uã‹Ýå2y,«ì'à.WÚNNêôæ¢çZÈ<~m¶Ï\nû¥Ö*²ñµÓòA „£¥I 4Åg>À,𣟥Iår"À9Í‹üI³;é:m¹Nϩձv­¸'f@†Ïf ‹ö™ lR¿@vÈ|rPÁG!¿ZM'ëmø}xë•…ùʪìX]tCüÙ&t ÃŽ m—’ߌø¨öû:ÞL«dŒ|¥þB[á<·Ï…î¦}6tІnÑ‹äôC¾žQòÜ]Ù7ä&#ÀðÓÕT–ÛÔ«,òráZº3d°su®PgÒ»>ôX:«ñ|â·ž,åggá«uߎwiµª65ó¢Æ¯Ê¤©¤O¨êwÏ·æPv¸¼bG¬¿·u;™´3OÒ_ ™©öò·7ßyΗçìãZ@¨7·ÿ»êuv·ÖŒßÔ³þ¿U‹•†;;îÏ*îqo$á¡zÀ‚½®hðiq5=IlPê7.b‡{åç´YÇ—`z.>/NïŽ+pƒUäôÆ¢ 4ݺVÄ"»€än{Þ]êv»–…þþéàXú :wNõ™w6—ßn/iÀNiô®„èÉt´.dj öð,µxˆ÷tÏ7Bï–Ò.T ÍhêˆÌï{f,´Ê†:ζP£Œº%æCùþ†übhÎ ï‡úƒ‰tª,¢)†â¢ˆti8å ì`ÃZ NH‰ÂEÆT Q ¥GŒ!åÙäP˜p#LÃöKä÷(bô +êª,×êÉv\®Ì¯4Ž­á|í²Dë,pK,Ž ÛÐ#ÚÀŠ…(¯¤Lø2¥- ¯Ðš¨¶È\vî‹ÐˆÞôµH笺'›˜ ¬˜£+”hy&­›\å¬î8¬.¼ˆ*BÂ88„ŸŽ[°þèýè‚Ò%[¼­ýØ8zÅË[xp6Œ¬Îz‚Uäì¾è˱T-™¢KJétcîqúr¦è’îÓôc0ï j ‚ÎÈ,ïòË{q¾ZNÀöíáP­á¼jãÌï‹Ñ"'±ÑrÏ ÂAxÉ—v‹rãxêL|KȨ" mqÖÐïÛF@*$k¢â|6±>OÉ|´©Î¸I˜X¢Ç©‡âÊßçßþ ê­âJ)±­ H#1 K‹àË@ ͱBEv>ÖÞë¶l'rIç¤-ìt¯"Órt˜.*5ª&æ#m0ü¨¯Ëš"SP^P|€ê4‹frëñbj„4n¼BnžœqD|gªôÉ,cêä鄸†*`ð$„³ð¸(€ü&¿*šü'nÚ}N|>Ê'2‘Á¨­(ݰæ°¬®1ÿà-ú„*Ѱ'oØdˆ¶Êr¾Nfâž*÷â°5+²,`¯„Éœ¦¯nâø`˜ªãžâ¦Î%‹7Ôâ+úe\NÓ·ê çªh?î7QNâ<…¾¢-æï0ÃMïpÇŸÒÓþ<IB&«*±’¾jŽæðî^2³?\ +ŠåŠÖ/:710Ÿ"eó?A‰9™ê;ûðXª©ÙâÏ)HB-P¥+Ér7ƒB/-O´%bBIŒ `´‹» òŽì Ÿ†ŠD s²šq2³¼Xï×t &æÎŽÎ+ƒ* ëk™rôÀ¸0´ð- ë¿–&3kSñ¿ó)ë+ñ0×ôÃ?¯b'¶Ð´†qù$‡ÙŠd=O·L´DË.#5rôŒkú¢3OаºH˜äça¸EE§8÷ìcÕÇ:bNb»>ò¸º,ÀjÒÿäm!?ä±ÀÀ€ŠØ‚þ1GkJkó«“žn‹Ìì!Ÿm½ÔŒJŰ³~í^ä¿ðƒ,o‘‘Ê·V4m£ô`0ÓèW,ªŒfíö\ÕA»)<¯îw.N•5. n>á¸(%'èÂå4Ñ> Ô*šròât8™•YqWcs!`T”Œ#Ñ +ÎV}Š0t!ˬﺣ7m´È×NèvÊHä:çèåÌ ¾Šãr+%ÑoÞõiä KMõŸdëÔ‹ôÆò.Åð.­F9zŠ'4,»é7íLA7dvuL ò Í˨ðõJS•árñ¤pWΊ×GåâM5—s#tV¢²e_ÇôDô×KÇZ¯þ¾lÍI3mß)qzõoÆ—UàÚrˆ¨oU0p/3¶[ðÆ¢Ž)'Èq]Ç'AJð-ñATQ Ø.E)8ÿâv£Ð%96¶)¬NÒ4ËWã1cýœ‚1ÁZÕlÍÖBúˆ¾$¶²& îò`ئÈcIôFÓH|õ· …/F;wµ#PÖ4¨b8J»¦>7(w¦Æãvmötø%,“‡«¸gÕô¢ø×ºèiø€-Ø ñÇ(ŠP…ù(˜Œ…*(¸­TïÕè²BÍ%Ÿðˆ½ç[!/p+PûÔ6rs©ˆË9ÉɪÎÌ#ñ±ôòïªô Kl¥M/Gôðzn„Sì~þ–·!·‰™6Reæl| RëP.×®óÓsØ'æ¬8e]œ‡_Ñï|:ð€p¥'Lƒ&3Ô+|“Œˆ-cÏø«€i>Ú×G èŒý‹Î£&"$û“a ñÎø¹%ï· HŠz+÷ÉÍÉ‘ósÖ®•Ù«J}k/Ù’w‡>w^Ä„¶ ™ÔÊ’?¬0öa-«„gO“ó÷ÅBž%…)ºr×ìÇ^­5sÛ©«¤ïLc’+z\¸Ï6*5g’Z²‰½§™H4E)’4å47(ç¸,ÓgÓË–t…¬w¬T¾*÷Þùc–íÂÈþæÂ4€Ê/]­ ?k^y1äð• ›º~|WË6¤ – JBµX" ξš'9ßТ}²«?ôMí´€‡Z†ø/§Ë&+¹1"ú«ÏùÎH]šÉö4—›1Q›ÀÚ®í>Âq¥ÅÆATg¡‚ëšU›wÚºE8GÕÞ®vúé“ Ïtð©zÁ² ÉÀÂey_ùŠÉ×)ƒ«1 ¸€ÍQ³éBꀣµ¡áFYQo%¥ÎØ@ƒqÅv½æ²›{ýk׈³“æ.åÎ%-@Ùø l ÷i®yíE¥ßmšØ& [Ѝ+‡«8Óšñ#•áÙÏò©{h gÐ0¸¢‡y‹òFþß0Ô÷C—ƒ'D°ªE»'°´Ÿ& T¸Z¬ÿºü°hrÑM·£CáEŒ<*;ÿV#{"E9ãHk~Sn”{곸,m[{°|9J¶—xö=qõã·èÒùz9ú«º CÑB˜qÁÆ[–ÍWº³™ù™â­®:yšbVŒÆ(&(8™¸sCÛ å°´!²«Q••*~±D’÷ž±ÒXu›¨ªlSõ£ˆ÷ñôXg*Ãy …Ü£ «_Lãÿˆ;rÕ°êH€" #ž›u^6£¡Éèeت즮¥iÁÖD¡Jƽ;b4™¼MÓ«µµùØ€« ) † þª<‡|ã§3#¨÷Ê^Ô—°8i5‡¼#›Ë ä|wã4.ÀˆÑ™öG 3ƒLˆmÁVVízÍÖV»Î¶"wLÇ9…÷n@œDæ!±¬Q£¿j­YÞUêøâ[M–mWË¥»ÐáF¼¥ã´›:E̘ظb¤ôuò{{RÊûWp¾¼Ð¶}žYbQAE]‘gÒ–v`Hµ\ª4Vüáï?ûÜÊÈœ`¿øF]ø_§¢ðÒ,ßç)ÝP%zéuHwq*dIoXëcEç¹ÍÇbIOãs‚/ñ#¹™ûW;ú+ ¢Ìwã×—R±±Ûá]3¸§x9¹l·±$íñþ~—aJS%IÝÜøC´Š?Bäxk—Ò‹´õ'Óq©–û.rê³Ú³·Â‘Uå‚4Ôr˜ÌÓ¿˜û¤"ù9h`¦ójÌãðyàG4•çÕi<¶T½>|.¼U‹Å§"î‘”-·£Žä:ˆ½9ò°¶ˆûö‹êVt»NwJèû» æW¦¥Œ×ÓQ$½]Ÿa›ƒeÊ×½ýƒéíX:¥nêN¿écÙ÷´Ø£fí\uX·’zÓsÕ‹ÖŸâÎרN˃jᘠ[™Ò´ÞΞéx¡vgðâHJáñÓ‹4*žjŒZ®Õe ÖvåéÌ“Ýd£–!’]敊§£"þò¡^Ž?žšA˜Ü³.W °|ŠñP7¥ñ Ø~-]ÿmëé8ø€,X¨`¡A ,HX˜Ð¡Âƒ '*¬ °!ňRœp¢EƒZ4yÐãF’#ºLòeB•(+Ä\9ñ%B"mblùsåC•2Q.Ì8raɆ(yn̙Ӡ T«Z½Š5+UE dèÕ«@¾V(ˆð+Ú²i˶TëUcÁ±dײÅyV&E”_Wê hK¿„‹9U«âÅŒs5ª)—%{î徚Ïb+ö³æ”hA§ål—.è§f Æ Ù÷è਄kÓ¾=;·ì• ûþ þœëBºúÚTݺðe‡ éåC£z—G? 57äëIo¼y0ª„šÇU˾™4;ò¿»îÜ»ÜfûÃR÷«púϵÉÍjæ–[&Á•W€_M›qYFß‚]5È„¶ &¡a½Ù‡!p ’d©ef € ç–õ×V‰ Q†â]æcAÎÖMoQWnJ8áŽñ¹ta†BjèÚf¡¥Ñˆó=åu&-•ÓðáÝH?1Åä^Xú”SM4GLeÇQmOÙH&Ke®)ß”>ù˜|èY·[bCj%\w²­å™h¡…•V[§‘5èFü­†hrnÙYŽºÑiþÊUØ’w^ZUžLN[^œ‚ø)ƒt:Ej&*ÔõVˆ™õÉjBÆU§¬\êÈ#®’êzÝA–b l¦!G¨Fm>ÇœK%a—fMc©\`ïÕÔ+µ‚=It ]Ð~ÚN Ö>yéÜKDá–F©+çyù)eݯÁ>_œf:n½®!«m-»×tGu()ˆ¹> é­Oº[ÁÞ¹!¾'¹TZ b çUŠ'ºJ €Ãñe`£wÙÚ¨¶ ’Ip„».ÜãÁ;jëðÃÀF ofœž:Á'1X9…_²Ý}+ žl#º<Ï)’±}t˜žÙ -f¯?Xسá";¡þ¼ÀjºÐMaâ›’„IëäQs[^fÝÙo:Ø`^çòÚòÊ.'|”×2ßw­š1c‰ˆž(Y‰F訂ó‰ZâŽ;g×v€:ÊeÝ”ßmB1ï}§¦N€órL›$_z+¥ì/ƒd“èxiJÐiÀ™ó¸:K£îW¸@"ÎÖ§¦"צ¬‡:¸Ó–ýËœÒúû\È9½œÞ—Ò»fØ<¥ìuçj‘JÞ_¤QMQ+0˜ô‰¿sÙ—¯o¹…œ¹¡ÀmOv»# Õ¥ùcwŸå²ùåeM-l jÉáTf7̱¯nÚ’ÞûˆDÀîfv‘Ènœö®§\ L‘Ñ¢ZG˜n`Èþ Pí.8Bóõl~3áZRFØ-ê,*Q‹ü"ôá‹,â[Ø–¤`F^!e68ÃŒ5 (Ø@6>¡˜OrcëWö V®¾Ž€Î¹Îe&ºE o iâ³¢)òl§„í¡I õ3“2a<Þ¹f EÅî(d™ýÈ—éŒÓÛ‹€®SáÔXú4“Gf,Ey)ã0sX%dw ËÌéÂÓìe=ÿK Lå—RMîo©Ü$G*é}HQ±ä¢2ÄÖ¨®@—3c†¨÷»É°Ïue2Ks*ø³‰•mw0Ê’Ô„Êž¡$‡Ü ¤'µ9B.fC&!þW7Ã5oR<[À¤–Åøli€™KSß¹À?¢Ë—ÚÌJü 2€ƒ(2t8Šæ [ƒKTÎ2–Ö³XÇH—D‘蟒áwž£$Æ(w§ìØ¢N†JÚ€ˆEò!ÉtcKò²5¼t§¯Þ6Y s%á ¹š°$ÆÜâ:Ò {§ÄOú9“Ž1ž«@6ë‰Fæ@&gåÉÚœt´ô‘çQlÄš+…¦¾ê4íšòäêªtT¤:f#ðÊHBÿ´P“:Š mÙ¼ñÒ­ÞêÌh슓õì &õ]dn§K™bÌ•µ$•'M*ìˆ$¤Â[ÇVdµ—ÐÓ>ÀÜþVÃ,“g‹ SL0Ê;ª…ü Ú`æ¯%&Qid$*…è©€°ÎÌ\&mÒVX ®–g»Ô SÖ=÷ÕTèL_DšÃ0xZn¹¸‚Žl·ò\ÎElP’LŠNúAµzpr2ìYʤ½H­Ù=fù8ØÔP¬Q&yë’˜T¼îíèi¯£ÖÝ‘—¸?B J}{–•p3=ÕBýƒ¸ÃžJ‰$[g~‡W±ÅÀd^N­´Jv„ïøXe >2|Û|éäPÎêŒj­u­W+3ÅĶ7þÚ‰oº¯dyÌ2uäg2Ê]‹€rÈ|2Øþ‘$ÊÁN”$†Ž‘SšwÖ@’4y¿e–¶È¨Q"uŽïZ#£·Võá\e‡3™Ü–&,”ù\È.d¼Â’V¾ó!}G6Ã/±”Mëj[vT;¬Çö¡™%c[–ÅÎx¨p{¬-aTªŒ©Šck*·«U’Wl-ݽÝÓHÅYqi·Ã®ãjéªo žaü¶oïz÷íV¹2˜Yc:'7ÔÖœ&âÒóÆ¤ØÚ©£Òøõ4&þ÷Ù‘û˜;ç=»UÃÕZ$p9gV¥jk–(s,Å2ØŠ7†'BLÍT;±W°›Œº¨|;#ñnÛº»Ì_u¹*ÅÙje›ÛúØþ}hCÛxv°T‡±ÂèBv[ Ù“yc¬©%›BÙñˆÀ¢:ëfkm6 ju£ÑH…Ä)G{©‚ïXUòV5A I±™ÆfÉþWæ[ÃsàúíÐÒ ø? ‚]ñ☠÷¢%è$IѾI¢¨¹PáÌ –‚¤hR8„ñPöþ6t¨SˆÇû·[£Éíh<T-í0긷[³<~8ÅZ•j,·²÷W³žMy—Áè—é<µ~‰êþ ŸEb{¹M?Œ†rÛÛ„[™õò¼ˆ.’Ÿn‰8cž¨nŒ¨¥¢Ã’dÅþ¤É‹ÁŠºmhJã'øh/én;þ¡©0 ºÂçp¦`§SgÊîÈO~l!”Z»pjÿ3ÓÉíä;½G~Õçî}7ÜŒ§.óϯèô›_ýèßñ©ÉF¬œ‚³™²ç˰$¶¾MËM;]'›’†ü'dO±xöWhkrC‘÷#pÔyØ/;ÑOO±r6O¦7V*W&®ck!d-kQäÂ&ëDdÆ…l…E-F¡:ìCu:¢ɇ|ZwF)áQü¡zwKptÓþTR#TgÖO+(jß~9¦|x‚w[‘x^AAÎ6GslÃN¥}Pƒ.ÔAyû·f+æM38?V"-aQ5‘€ïb-rTT»xoã-þ@³>¨c:Ñ-†!~³vUÍ„lKqãIÕó€#´Xœu] G„W qÆwrxzÐ×ù&pùÖ'4å`tS‰B1—óƒ W„í󉤿¨ö‚¸„ö#‹$c„wætWf&Š¢$:SLXU=ª³GN÷m=dtÝ^ß¡Z¸w†s{ÔåQ*vg5ön;W. H4+ÖH'7@Ë–¨3Ìf5cø4NŠßX':¶h„Ä:"z'dÈ5{€•}9óUà¨@‡è2á5vça§¨Paeñ„;•.L2\i"F!?N7„‚XG‘3Nú•b8èv0Å­YTþsjkÿò"¹[AMï%(Š‚@Ž˜T…AR™³rt,7Äl¯¸- y4 ™l˜†wø{F¸2L¡ˆŽÑ<¶uÍRM§“/…' H(W“-ñb‚1u”~:)•-Ó@:Öa=‰wÔCHª.òQƒôoØu›Èe0çX IŠÓelEPÿæm¤!#2àŸ•™Hg¦Ñ–®±[ò!"9St–^ï9óh’‡.µõ”@f‚WD‚Œç— ÙeØ7Ze“ #wîÖf¡nFebpìÖ²œÇÑx^.×$ É™žØ™9Iutš‰É7QÁ•8ƒi¶Rneþ7}h¦—Ê£vó%œ?¸_âÖ^=(œCF}Q€Qƒ!‚S¤…EðxQ®Ç—G·^#j¸i¨W‘Æ&RC´‡ƒÅòÅ;.…Lt¤i—-ÍÁs 8›=Ò‚§¨ciB’ 3.±qdCL}8&íOú{p•fh9ÆŸ yÿXgMÐcK﵃Ã,ô] ¥oÐy‘1 €µ<^&S¦P›WAD1––mw%pÉc·eàÉ‘ºXâDZFÎÈõ&L*%ò³{oÕt>›ºÅBS·}`Ä:eU±¹ ôxòVOñ6Œ)ˆŽ×qÚ#g(r%!¢eseˆþT |‡â)3«;£B©+0t¤CÒTBLËS¡ëjaµ¬E1Q&®s­Ée|)P‘’t ZSÉ+Ô«‚Ÿ©¶Ó%ˆžâO–81Å6l1’"C¼¬'^3ºiÖÑ”·Z¥»ûÀø¿›•±*«Ky5äƒ5öbZz†EíØ‡5Üš’IcéÄkqy@Qelâ«ÙAr÷ ¿±ºú¢N'¿‰¦„˜fyšÞÑG‘;±ù™Â\ÂÂ1X¹2ágÆPÜE}þØ…]܃ðEF)~‹²õ(¶×{)Žöd)¥”ƒ Ý¸)®Ù‡¿É¹ÆNȪrs’v‘¥kôÖNŽ¢Q”=÷·æ›¿Ÿö¿9!6’wkXÈ¿;t<ž6cƒØ¾?rÑ»ÅrL!_ü@Ãé8‰+A ÃO5c1t´´B‹Ú+šÁl¸6z>¦URˆè"ÌTPŠA™ lpS^ 3¯e¡S#™BßEÒ ¼¤¯5mÈr˜7‘q‘UaÀ©7ø·ÎaRùÌÅáIÑ@3ÕÛáXRŠÕç3hé%©[M¶W˜]lÊql7¾Õk»I‡Ô•¡ƒÔK†ou*°Ñ­ ú&iK!Œnw±^®˜K˜Tr|̼·¯J³¨¨·œHZ"&Ök)9c}ÎÁtÈý4rÆüL¬èJœrJÄ„^¸1\N]ÊvCÇö³ƒ,zØ›>e€îb¾!ÖÑÔ*&ëh: þxÚm¶Õ’Ú»êùTûÖÈ&* /ÉH"ŠÁµ`¦¡sVnó‡· bncŒ¯”Tg<¬T€ Xƒ£15‹´úM5\É‹5b HSè)Ù[¥n]ÖµM»}·±Àº¼ÛØÕ\RxšÈCÒBµÃ‹ÍìÑ/ïAÄÑFµTÍËÍ:½ ¶û ¼deV—Êp™*¬{s°xæ]wÚgÅÔ¶8^wâ(*}EÓÉ/§iÆ!nÕAl N#›^V£ IËÑ¥¤5ž± ²”¸HZ¾¦kd âMP'ÓýKʽëäiKÑŽV¢¶5ºu5;N‹Zœ4|Ÿ.ºTµaiM®ßþf­Ÿ›ÖTAÁs:ü¥«wšÇ­ÝÅ{ÝÑôÁyˆ"«P×=ç‰â~©nQ3ZºÖ²ÒV%õzÕØ6Õ…_6ë}¾¨Z{¨oúz¨²·Xö§´šß±GüÔŸN¾7ô>^5B N0ŠdÜà_}¾<ڨǚßeÃ}ûРNæ©kTg.,ˆ+Ø|üWu×4úma‰b—¨Á°G0ÿIM,׺”®Ø—=:³þW¢—Ρ0”=ÔoÝ\–‚”tq!—]KqÖ`CÇzªDtwÝÞãrmtº»ŒëmúÛ¿!åpfžÉ_œ3–¬'s[Þ–‡N5Ù˜Ë^ï‚‹þr+Ìëh.1Äq˜×á4Em/»+\nå8áËBy6ÊÙ¤+cÝTœE™¸2ÃöÎ N*ý .5µyóÓ‘h{±—bW ¾œÔ¾—ôMI>K1ëÈðûÝU÷îÓµ%õ÷––ˆÃX·ÔÜcQCE,†©Ý0ïZÝ…hkôTŠÖ¼¼Ú ¨47”Á†½¨öémyž[½¯ä[O{Þc¤ÏÜÃß´rL®™Q^ÖâÕR´…ÛãD> ËŽåÅt6M°@ôCrÒB,Ê8Ò} …¾ð!ê2¼{‚Y œ£š"F§î-$*‘¡ê߉¯›–¿°˜,Xmšùýi›þŸÊÏw¿=“m?À&ÃKêúQˆÂhe(yŽw”ýs>šÇ†;õy_÷€WaVs}/âèT8qÓÎ6_f¯"z‰GV×£Ô„¬áiÞ"û³ï#HßSm@ç²:^ʼÄåí’}Ü5³W¥T”Òã›ôÚ¥*õt×NÕÞa[±ÄxmL¡$ÄP¸ïÚôëÒFås´(Þþâ[Z…}åµP†'}Èá‡QŒx+ÄõEA¡z1F2yÔùH>[º±ç×T›1è©­Mi§[ZÍEf)f)Þ¨åV¶To\º=Ùp¬‰Çº˜­KCKUÈåR«€‚5½êÕJ­ÎX&«~4à¶rU“R´þ›Í´_N1b¶.<ø"jË ÷Ö†$¯?N!u5¢3éÛö¸„uõWW„•ðMµ h¶Nï˜À¾1j”Ìn×Ù´/‘g‡V%ÕVß›-=Cƒq÷v[3×5"cÏ8¢Ó¢f /EÓ°uÅŠ7ž0ÃæíxWµG/²mà‹ªïsµvëq…tÇ™Ïf)]jÍþ‰P;©óÍç_™¢D?0QÁ¾w;`ÏZ RøUB‘,<—`¬¬&8À5ICXèð÷œbY`)9@^²ƒ. y‰hBCðˆ$BâI jÐ"ols€Ñæx­MÔhgBo I…išÀ¢Áá™åJyŠá¹Øu.žBš“ÈöP¤?°„†nCËû$§è©7±來Eó,/q\oÈæ}ɯ~d’'(—èhQ1Þ3_㇑"‚"°2_ÀbçEKiñ5Á‰ÝÉÈ@R­Jˆ׸&Š+þKÕzžÄ%Ù@.‹qkl·ø)$4‘ü¤Ö. Â³¹‹&`þ€X¨xII‰’éä‘s”ÔL@]aOhX•îI†UÜK§–®E‰ù“ý¨³¢9¯%‹À(ƒ´¤ sd€úQ 5î”ÑHÒûýИ° Üo‘ŒìžÛ¾â°ˆ•³TŠLœÙ­’±ï–1WÁ I¯C’sœÆ<ç"V´LŠè³á‹öš‚0€Œ æ#Ö“”gsAçE1‚V¯v64?¹£ƒÙ0qùit!OKeÉù.Z—c>‡‰]‚¢ñ³Ç¨µ.›°™¦q'»öœ0éÓç7Bö󌞩i@WĪ=1£SûDÔ+f‡=5þ IFÔ$!oŸþBë?‘ˆÏ¿(2 âÙJ@6Míg,»ŒÝþ“@yÖGB^1Ù^lB-˜hŒŒ( q8¦xƒªƒ’·°x.š»¶4S–á6Íh£Óˆý x¹³ii=òÑßšf#08°žú‘¶eã)d3Üà’wš•ùâÀHR9ÄC<› Òm£)Wë SQøq²ô“šŠ(°Lq—a–ì‹?í31Ê;§D¡•@Ò‰A ÂË>«¸1÷ò4ñ¢11 ±µ¾Â6)ÔA#c/Ld³†8 Ò ³Þº3Ö­ ë²7¢g³¢8S¨8,6ì“’!¥=c&•ã®ãd\-¦Ë IJÈëMºSµ„àϵa(•˜«ù”ÏŠA,…‹œ#œë´å?ûôJž(šÎÈ·÷R '¬œS4N&ùËIþGH)˜Êܼ<@k?«l%ÒТÖPÄJÚÌÒ 5‹¸ Ä9²±†DM@ NBTžÜª’ú°0Ó ö4°¼3"EÏÜQF‘q#N:Ù)K»cÈpjÎ…¸ÒEÊBêÐ:óK £´íl¼=óɢƹ”Oä ÉN>­ ²sÎÂrÔ-)Ñ"ü´U¹C£ËIIyô19’ó¨ØèÉ”Ü.ôŒ¾cÂþ«D }¼ mŽ¢¥wQFgœU‹ú0™j™=L!>»Uœ ?ü„Ó(\ÕR›Ó§D‹E›±K róŽ©Ø·Îû„éGlùA̲ÖwœÈ¡`¾ ¼ž£@Û4&þcEp —BaÔ÷š=ò¤[šœmݳ­]uý‹¨íÏ»8pS–ùT>hÍž šÍµÐB“Å Ä„S”+y)!t¶üø«ÎÚEú(°Õ¥ÚªE^Oaµ`óÑäXÞŪ¬¶D¢êYQœäÕ¶ó ¯ùsEšÓÝnó•‰)Æ×[2n<[ëáå‰ý/“d-E~µ]÷5/Ê´G6ª™©™›9]£19/Kãú?Õª¤â&„ Ì-I…Õº¬%@àÌel/ûI¡KƬåF¹Åà¼\Ï ‘DžܸÊ-æíþáK5Õ­½»¡œ}»Ï–$=¬Œ¹!ž“øUàà@Tœ=Ue2mÓ¢ìôÏñ[AM;0âÙb5`ÅÁ ÒõY0 ²Õɳ<; îUô‰=¤@  ½ÜQ@ô¬ dÇ3Žã”¼uüÉáCÔ}ưÊ3ØQcý¬¿LÅ}œ%þ¦–lÝs76+èÜ&î‚Ä#â÷ý.ž’¶­Z-’¯<º#jÑ]bëT2mUº¶d²d,àL`’¨  *ˆ :"NIQR zcFÝÑ02ªŸÊÃ7.:˜:بÉ$E,R:P?,IÕ³%ežPMÊŠpA9nТ"ã!n5ód '‚"Õ“&þãËœ#m— ò¢xÁÿ0Ê VåÛ•-LîA)uCΉÑÓÃgg)'íœ&I1È¥Ø,fJ…1´V¦ ô’Ãú üB „•®4®”ò¥ÒP—MF¼/­§;IÃ?:ØŸ@ÒeKãÿ¼°!ÉŽî!_:¿£0sº!Óð ® ³Œï- eÂ@ñ?h’¦=š'<Ç$PmÊÕî ˬDÈüh™3b¸JÌ„YÛY7ÁËŠÊuGåâ5U¤aMê&à}ÂуXj©³Ý:"\¨3´¨š 9¡¥Ä\¹·d)ŽJu&Uª9sž?±U L!EáãÚ§ãóè†õÕþKÒÀ¯˜aœºŽ>aGRú) ìëd\ÐHæ3¥0€“¶îmç­žx.œ¬¼Ìæ €^Ö9KÛärg*•B¤öÍ¿™<ƒ;À¥?Ù4 P±ò QNÁ_´h¡?Ô£ ê7¬˜]ù@nÝá>ß¶Üǃ“J“¨Ö”ù1CñÙIñ,à­ö[cžVZŸ,Ó™Ü"]¤§î\?A®d8í%:ÝÜ:@»JÁ.Pº^’¤»âNe³-à(ھǵT 욬Q¾Jk_<šµ÷£ë$?àž‰¦è=2À¸…¾GkZ#‰²o…Ô˜(3ž}™ý‚$Õ¾Þ,£l’ôL’þ!¯²XçÒ¬Òìê° oc^ÏP%m )뢦0XÄb®~íÐýç»àqùí¢³/ëÛñ+üP8ÛÃ%Œîõ‘›Ÿ ªþªf¯%ÅÚßUB I5Ƭ&/$äʺš»Ä2ÓC–\F¢|¦]ë1âïßâ†ìo‹ˆodB²7cÃ\F\„’”£Ö^$gr¯^rwƸ‚&ðP4­û¢H18Ì®•T¡eYcKò¥Ä}ÔܲþôÎUs/ÿSc+ ÿXÒâRϘÆÎ[GÄ4?]”A'5i6º½Jíï5ÿ®Xß6ƒ.6õK.¤Bl[KeÇæI—ôGËLþ‡ª½‘Ž]\¯´’ýr¾€4T{Œ·sóKK(V;úCŠ,çÛU¬q92J6eV'舠i®ðF¼ÛñM¸»·y;2m•8ˆ"Í2ÂGå‹xòSƒ`ÚP…½ºµŠR íBè÷^ßeçvΚþ«Ãv éjàkÂüs¿Ù%Æ< °ÁŸûª!±xÆõq[šLWÇ)®âJ%ÞYqéQW OÎYìHxœaT×c˜¹ãxd·ú;t›‚ÌÅ{>;lnã ¿XçêTÉŽwZk¯úÿŽ n÷ˆ,<ÌóÝ÷Ùí5¥½MT¡7ƒ¿ÉÊ1ûr¼NbλÀHX*þ¶SQçÆáN´õ|Âa9bŸqÚ>Ãpp†èwKanìô /‹—Z÷»8·“Qûk¿úÊzˆù>¢x’çÝúÀ½_ªÔîjÿìØ¶ô%Žx¦Ž‰ük`þ‹píŠön `B-.¼ÔÚ´¾¡l:RÅý`î[ɬ!RS]¡ïT„V‰í̧:ÊÏZm&ÑuÉ­w$ª\51’û… ¸ÖÆö´Oöá8ýÍ`y¢õ7ßð57ÜŒÙÑŸ}€°PÁÁ‚ <ˆP¡A„ 2èP"ÄŠ-0À q#ÇŽ?‚ ’ D ‰¶¦Ä–fŒi'Í‚1þoÊ|¸sàÍ mÝéSfLN›Âì‰T)M Rkæ|JTiή]·Z˜€ôèWª?œëA›OÝ>-;uëA“ *©7¤¡ P˜ZP­W£'ܽ´!ÃÅý&Žüx2刕'¾´(9óB‚÷‚=²¤K‚t&”PÁ®b ¯Èš2EÎ5K¾Œ2oÝ·ç¶,üîÁ¼¢#ïØ÷àœP“®ý³©i·—E*AÀ[‚buþÜ9=n֏ޡ[7ûÐæbðA£rEí~±Uƒ†YWE võ·:³”[vù7Øp¶—œHËÙ·ý_ƒ&1¤ÚBsÝVÔnÃm¸þ›oÁaÖ!p“5ö™‚'‚ÔcNAhXCbeaBVOÄqeoŽøao<‚è!?†X›‰(" I5ù›i^%åUSN%ßC`á$˜Uc•µÔ{[9µ”XúTU{^ê‡UPI9æbx×Q5¦c®…ˆ¥š\Ý)€Tb5[D &É‘Šh©˜vⵞ¢i  YŒÝõŸˆ=ê裥CVš)A€Š"I6ŠagmA*ÔA§šŠšlm Ùª«” ë«AÊZ[Aœv¨Šå‘—QˆñiRw|V”…7™×«xˆÞiØwaÒ7ì²Fé¦xçY{^ax¾%,v…Gêi×Q‹a]W2þ-¯^jИi–Å®º¶–S`æ'¡TâTÚcsy餴¼ãÀ“™«‚»^X‹ 毇Sö¨å¬_Œq­[j«@ +Œ$I¾å†á‡®_hiÖ°3ÎXš] ZDWBÍ&ñC3ÚxeÌiAÚØ@³kkÀ®ŒôZ‰©ÆòVvQVÏÍ,Ù¼IJ\•¥%:ì[Å‚™BUK¸1‘œv¬X\Èž&ÄŸLñ‡ìLã…gžRèùv£Ù$®}ößjgL¸©üö½õ€¤þIJ‘Ü*Kdᨡz¸ÊJ·fYƒ;W´©œĹ@ÀÒ…PÕ/f†ôB®{œúѶþÊÍ™¯¹Åz5’ >9Ø“òyËxXÖY€Ÿ½CÉöàWªqÁš”¸â{1Ü¡ƒáämø°0µuR‘ͬjá磿|úAf®ûô¡œ.Ž{l9Eâ§¶4þC—6¹Ô¤Íî\è’‘÷jcü™ÆE‰Ûdì—šÖ 0::ÜêÎ#[]@8Ç+ÉKr†˜œ5†Rî;QÖC”¡€;C)T\¼V¹H€ïa^àœ¸õ NyBáû<²¤ æ,Méø¬`Age]ÚL ›g8Ž=1‡RÌ\¤×CÐô…@Ó …ê–²ØA„B¨‚ÙÖ&ÀÌ……6—Ó\ÔnÆÀÒ)nñþØéRW³9jÎ_1sÍ5Dz8"/‡õÙ”âJxW-2LŠ:î_B|h\ ‡²¦¯ÙB­\÷ð³m¹—CÞÀr+§HƒŽÜ‚—d.¯¶Ö«]傱ȸD£ª]ñšV(­lá-+/ué¢à2Oâuw=g¦ b¤”rVýy&4¾è'­ç§–\)WbÍ\ºó/ñÑ—ü—½¶Fªq=…Šñ¥•®å}sù霭8Wnþ/QIŒ±D7äÑÆ²ÁŽGÑßó{}³Ju½,IXO¡_ìø·²ûLT©iŒ ¡èØ'íWo¿MYùwKGÕK|ÍÌ„k³SZft§ãžÎ2}L¾âò„r܊Е“Ô¿z×¹F̰»Êö#ôÚÚG²žäúf œ‹v£R±òÈ¢²*×7Ù½l{Záúìå½¹SLæ®ÖKe õ«ä%ZÇXA pK3 €ýÚLa9`tš»’ÚW| d6ä‘X€IÄÓç ´Ý[c—ÜrÚl7†'Å$ ¿%uÚ_ì ¦Ÿ^~!{=8u—âÕÅüfÒCœØ ÙµîïÍÏ8)Ô¿\_8þ5_©(”99‹Õ%Uí¸ÝD|݈òTP)P7qˆÜºôéÜS¡š]±QTž ðÜm´ÚM£ä¸Ä Õžûm¨ Õü‰êÅ[q”ŒÇpmß¡ G± àÞÞ–¡…^QÖl‘Za•ÅÓ”E_ç$ùôWQß!4]žX)Þ]~_ÑPŽ=ÕM5µ`AU¡ÐÀFñ1F¾Îœ„ž6!’éF ሗPŰ¡d‡“<\ ¢ êàú ‘!vJýUXÅÂYYаÉ]¤ŒÕÅPË “ä}¢apÈ`"…N"þ!Î,T+^ þáÍRpÜ ,òË`â6Ñ’% "ž2ñ’ÿ$T æ 2Æó@aÈTO«½š¼ar×°ÜÚÉÃ1a%Nb‘PœBšâÁDXI„똋£hÝš ÎaÂá=“´5Єµ…µ|Ñ ºâ%•ý¦•‘M ?–J|¡ü¢\©Ný ÞØO]è?šJ>~c72#»‰#ìÚ¥½Ž@¦ÔÛùÏEÌjœ7ùÚz¡Ì÷yãJ^¤=ãQEAÀip¢ãÕÄ-æ‰éGˆË›ÌaXˆ d E™±WED3µ|ùWxSƨ–JÝEB6SBñLYÑ]Í”bLJmPbK‚þåE¼d®Ü ­—Þ­$¢ÀˆEåSSêÆVä\Lf¤å¹†D˜m© ª| ³ü=ÝdÞlTÌÝcKìTB‹uí™FI Uǧ…efÁ¥j=‘Ž0DBÔýõTÇ™dÓmÝš¸Ú@0ÞóÑåd.£Ûdä§(ÒYÂeÍØ ª¢ Ù1ˆGZæ2FœP±ÌX*NüXJT_–áðÝt½¢‹ÙX·±…†ÎY|R‘é¹ÕOïøež0åWb÷E݆Peú=ÌBJUgT“AG§ú鯩îZÉœ íü£u“‹0êÈFýQúE<ΔÁ¢ì…f­-¥¦²ä¥xiª”dØL‡ÆñZ¸¤™mF”òàŸ¦&B¾)JÝôÖ³ÈOªê c& È-jœ4‹Ùj°v«)õ¦Ú!²ÝqõZm†dP^^+NÔc¡ 5Úýà†|,«nj§~j ‹Ã™ÒQç3±Œ½eDüjWrÆ×©i«ÎJ{&I~­Ö%…³©ÙaNÅ÷Ô`šO˜´×ZQŒE¨豩ÆÞš_À¬ÂëÚŒñ=`©Ùä¥11UÓ$ A6J¦¡ßþåyf)°r+À>Ä·Æa/©Ð¼‘úl¾ÑEÊ ×ÔÜæ²6#»ŠHÒ¢H”IÙܯZ¤p[pË”z¦ÿ 3iiÆ2á° hñíöeáVV )Ñ*~àÞhäU_ÒhãÃ&¢Š"î–ídt,×a_µ†È.ºIÜXësõb aߪÒíˆ*rhbOÉŠi\Ð~؉áßH•éZÌêë0Ý׆.—*Á)?ÂRä°9%RóQ¤ ÏÉâY«K¶“\­Ë®kE~«IšŽÍâÊbÅ,'w~äùTØ­«Ø- 1Q‘eKwÝ#G5×ìäky(â¶8Ý ¾­§yï’]"òþjä'ÖD,M“N¸Ñ{‘ ¢Æ$Œ=—daã‰ÓÚ¶¬ç~®¶†îèÖ”ÌÜT–JÝ…“‰Z®Z²èÆnBÌîqÔ®uÎéÌÀÝE&¢„P´‘OŠ °Øþhì¼ð‰,É©€XÔd[^)f¸•kHÉù­[n ˜\6íÕÇLHØR¦7†/ žŠc]¡®ÒE-Î]ðÌòe®ohûÅÃ7¡Êh–¨1FF]AêmÄ,q¶îûÞ^#ïMì%BÕgÊÑ+¯ñ¯\˜r5ò[`I¾œK}Jaèw1 ³¤¿°x`ݳ"ðV–îïHûBlÊöïOQñVþƒF æšÎCÖQi\©ê9öÕB¹áûq0sˆâ¾kAŒ™ÐKŒ!²™ ©î Ðn|ààʱp¥)~"Ä{0ñró·òúmÑ1`,ÂY¡ŠdƒL-ÝíÉŽl¦mñvpü.ŽTÆ%8âHæPd²±9%+snvgmÀ2í>JìÄs Ïä虞”Ž ±œˆ™^ņ£´Ë1éýlT‘ÝÛÜ3ØØ®¤É*W®¯O¤GhYFÃMí6&+–žæWª¦8f1Ù´¡1™!NßtOóôOûtPõP uQ»ÄÉó âìÞÒbr¡þ¾c¶…,WÀˆµýQ{=þÌ9iòLÙjHž¥a©Q‹5Q“õX›uYu8Ï {ð/ø4W(®ÞRóx…ïe„›7eRk“D–[?Ó³_?å_öðá‘a 6aöĸ.6€+@·È.­4wÑQ(j–0õS¹5—³zf^Ë¥Út‰BW3u5 Öç4íô4±¶N»6øµ6j«öNî™…²ñØ‹¹^º`ŠaXWHJ˱,¾¼s3#_‡4€(87t?wtS÷t[·tcwug÷ukwws÷wowx{·xƒ÷x›wy£7y«÷y‹7t77¼·qw9Ž£8`EXi¶>TH k6§!cwdÄþz­b#v+¶8`+8‚/ħ/~•¨­˜:2ÇEÅÉ VæÖ?w/¨)·ƒxˆ‹ø‚E¶€ïêEÑ0?³öâ©ÔìçXI/ãô+’îYã8ZçøŽë8Eܶi8u~Ë¡lEañ¨bÏ<†MTqÔG³0? ôˆKù”SùÝ>ò‰“¬=«¬ #Ò ‹rLòW÷= a³Åzbc3xšø_«/š/v÷…/J´×$ ý‚ÜÞnÞ#Ö1>›ío¿4 Gy•z¡º `6wY,1Ñ&Q5ÕZF~ëÌÖb™ñÆJ&f‚ÖÅ•¦sº‡|2öõªâ[ÌЦè¤%{D„þúEÆðv8X>Ñ ú¬ÓzˆóN)ª¢ ×V•茫äVÙ÷qïeÉ)oòèuèoçÄPÕÏÈ/£¡JÙåÎ8áêÕˆ$#+ÿ±ûÊK­ƒ{¸‹»h<÷{—{À7u§;¸÷tC÷»7·s7À»;÷s¯»»[w¹ã»¹Ç;¾g7¼Ó;»û»¿·»ÀÓ»½«{t¼¹<¿7¼»{ÀCü»O<ÂSãÿ ÙC~ä‹øÈ du.¥mÜŽþÍáXk5%£Œß °»x>ãNÀt ê«>&Î7²«~ 5oT¾>³»îì;¥íW‘äëþîg¤ÀéÅV,¦§}®gúj-ÞtßóçË±Ý¥Õæþ¬7‚a$4ê;Ãc<½cÁ¼öüöÇ;Å|öï{÷—ÿøo?ù¿÷£ÿ÷›?ûŸüC7ïÓýëšôK¯?1:1þA@T° ÐÂN°°PA„ >\8QÂÀ‰ ¼ˆ±‚‰+Z„¸ÐãÁ‚"?n”(åÈ‹+UnléòåEpæÔ¹“gOŸ?ÚóæP£G‘&Uº”iS§O¡F•:•jU«Pp\4+T“lM™bÁŽè‘fʳ¿^¬ˆ0®\³i#tXöbܽê†M) ¤Z¾mg΄yqb–‹^•Ì”ÁdË—1gÖ¼™sgÏ™@,Üõë\‹\¿>~{X€ÓS[ð{¥`‡©asÅx €¼wý¢®kØ,`ˆ&˜4 ›áoŇU3~.ÝñÆÈŸ5ß¼Ž{wïßþÁ‡?5ëÞ­¼ª+a6õèÒã–® =fݸìÏ¿¨¥ì‰±“H0·úr«½ˆ@j±ÅlŒÁi‹n»ñÈà2 1ÌPà 9ìP©Ð€Kï?ÓúÒm áv3Ѹ¯‚ÓŽP;͵eãª!ƒ„«È/æ‹‘½g.Æàþ³±£L‰=ŒØª‰Æ÷ ”Êé¬Î:±Â`B,¹ìÒË/ÁÄÊ1ÒFJ-Fÿ˜óo«5OÜÊÌ5 :N Z3Î8ÙâdÍáÔ$rO†â+“$ß<1M<uMO‘B¢k¹Õª|ÐÊHé+kË0ŠìRL9íÔÓODZÀîlIýÒT;Ÿ 4þ7ÔÒ PÈ4YݨÐZ{Œ±T4OÍ“ÍïŒ .ÇÊè aÍsÒ(¥¬´Ê6UËœ.”ÖÚk±Í–ª¬îúK¡äp\´ÍX]*õÍcOãQ¤ÖÐwÙ‹]SM)6üþÉPå+T¤áòº­Á)'}vJIŒöÓíÖÖá‡!¾VT‰4úèÛ3sÏ×Sç´ÏEEqÐãP|5099î@]‘t“WÑP†uN³è[Œ˜upYÍÙ¢†;ݮڈ‰.ÚhL¹¸ÜšlÛÏ!ƒ~3i­‡’µËT·£R'?J(òñ.Zì’)™JU†§<– #¢ù•pÕÈe Ô"yE.z«OÿZZl$H ]ѱ‰IdâóèÉúZECå*¡MÎ ÒjÀÄ×#u ˜5Þ²—Èa“6÷$2a¹k+™4P(“‰ÇcŽ’“¢\&Ÿ)MyΚI+ãþD*–*yÙrX‡J0óãkºêl´‚ÝåhÇCâøLR\ç;ÓùÎQÆ“žµè­·¶Š N8’S€9#ÇýSp°ÒHGõ„Rüè†]$yàjBJCd®K4f;%:%Š^”§=^+ÿâ’¹FyÜ‹#ÌŒ°˜½k’Ô„5<É”ÅeC±jS†V•g;Ý }V±6Åz [ Uõ£Ÿ .u]cdò–µ–D­­5sÉ*MsúP®F”«‰ñª†þ:VÁÒ³•Þ{Ú€&'T¼$o?8ãž\ñI)4šÕ%ÀKIàžÚ׼╳8íl)‹ÖÁŽ–´;ÑØ–DµÉ9‡uÄ™kþ[ûC×®•‚D¥la;ÓÏ2s³žm'[Zá·CÜRWDT5=K%üO·,ø¾Òï#ì‹1Ù¹ÇÝêÖ·V…'qÁÞ‡ 0ް‘!‰Nú‘°ÐgÅï°½L-AE*£š¼šn7»¼Ýëß\ñ˜Àœ±ç¿Ð“ÙÉè! ¾¬å”¤8r&Žp¸µYmTãÁßöÖ¿üåk<ž˜Äw•“^Ù2Œ¥øJÎXø´‘ëq„ªëOæ êaÍîX¯ÝuˈÃ#ÚùÆÅž gV¯k*t’!áÍÀÔɆZ˜»Þåp•±ìP/Èàé2‘Áœ­½Ù‹ÌýœÕ‰$þ¹œ «·œåýïM½«åk—ÎsÞ*hÜg=c§°geð»žPd‰kA1¾²œ•©Õþfùжò—÷é=ù,l’¢Pš2 еrô†ylå7ۙѡ¾ª³ -iU¹Ï³ƒ«ƒ Û('º§Öñ–½h]7ZÑ+I5w„¼jaÒ‘­ ÖphÆÉŽgKô­·œã:—Ú¢æ²3‡íÒµÚÂnE_ï4ÊÜõÚ–Ô»îõ¨©=msø×|Öö»Mì–,×"Œ“ b›“–äÕn,Æ[vBk8Æ}¯¹%9jµï¬n^o!í†÷ÃÅZØC&·ÞW ±ã8©áMÍbE¬á:ýþÚìÔÔX¾«ÂK¾è 8â-¿è íåó;"D2èƒõý®Ût#\›IjW¦Ê­{Ú GùgYîr¥ËóÀ£»œ ¾YÒò¥Ia¦z/’-v“Í8kéíΔ;ºÜFçmÒ ¼tµƒJTÅLMvT]—Š;ÆüÃbUÕ HËnêai†p¢—}ì¦Fûf¿vÅ;ÅÈ“ùsׄ_©î Vã#Ç5NÈŸËæ™uâ’cöt^ðõK|fN¿xÕ#åľ㓠KF(—Å×U´w“®N6¬>™,Ð üËšA]ú ?B©_ýñ¥gÏøAU÷pL¹téÃ?ÁæfoÑŸ_Óþ¶xdÖû=ú÷I~ã#Ÿü¤Ëh^è+²Œ)^lúªæ¼¾!’ÄeL“£ÆÕ¦$Ž‚óèpð2ʯÁ ¨Êxè `(YH¤‚G®ì+w”ƒÜÚŒ˜J¦TnøÀo¹jü&#Ø p5£¬>®ðîà„I¿î ZÂl2Éw¤XÚ¢.,PÚ:Pu0а}ÏŽ­ã^'-°A,k>¦Fp^‹±zˆŽ*fæZðÂ/EOAP2Dðµ°*NKIdIjt¨r*Çu'­ØÈÏò+˜Ü"$žÐÞ˜Àîh90üä ·ð9ÅÈ ˆâVC+ŒÊ¢Q.ôB¯J`þÌÕšê%X+áщOáì%ÑKÈk4Òã|¼gÁÌå¹lh‹äÅ4ér2i¹‚Jú¾Ni¢-«p«*'ñ‹ çžn9 Ã<… è ¯¦@Ài“VÅíDq°YñýË·•1*N,æ^ï£X 5`I*_†D7®gœÒLGX*yÂ. ÍÚRq éÐA,´–1›¢ñúÉÔ$Xhæ>Ic0/µÌ%OÄÂU jj­JpCÕi©pu +D’õ”†7ìîTê%Xdeó WòóÎì6žð,E  åÐGÈ r$ ¬f”6&ï²x."Q’"uÏNþ`‰gæë Â8Òûˆ$?Ò~D’$}ò2Ší%,MWVj’>†—bÃiÅ"ͺq^$¾Ð '©òäÊq'?¢'r+­‚ÛÊv> "Lcà4ÂÁŒÊ¥ž-¨Ã‘¢#,Ëñ&Ó +ÍÑ´ò)²+•1(ÝÌ)9ÎâÒª1.mDÉ4ÌR\¢ÙžíÿªR Rë’ñð/½ºll‹ÖT"#ëm‹¥…Òw K .S'ßé1×12¹2+fÌÙ…@Ñ/…çç`󢻇&ZÓp𠻬²#s’ç² í¦ŠRÈŠR芨…ŠŽSS³”'¬È9©39«e:›3þ;¡ó:™³žSK¾Ó8¥³;Á³:·s9ͳ<­=µS=Ïs<ÓóŠ4%:-„<å³=ų>ã3<é;½3>ûÓ>Ó?¹s?ç³@ñ“@Ùó?ñ3@ t=áÓ: ¹ ‡.L±œëQexø†n(®â+Y38“4RðPS5U)Ê#/Èd|ˆŠœd‘+xüBËŒ² Îb†i*‡q1…S.'%EWôHƒ¢Ïœ.Áü°7_Fõ-\ª/—"ŶÈéšD“ÆÄnHMÔ#‰ÔmŒIÅ”'é ßNód%‡d^æ‘HÑLpHâýÔOç„“*s­K‡³¿ÂtLUKÌþéEѬ ’Ä%é¥4µ©ê¥—\0‘&ܲi¾1Oã’ì„4Ί±&þ4PÅT:­§êöPe"rQÓH]šRUÞ±Ö é½ZBFð73•D¯R§<5WO)“š„f`Òé¬)ó6âÏTw ²êèªYE.i•Oõ´;UWU”5Î@fLÿj$îîdIª $èôÏr¤æî0q“‚üÃ3É‚]=2H¡uS'bZ©52Éë/x®(°o(‡½Àß¾å2÷;ÔÅ÷¢ìßÖ6°ÇÞµ4¿^ë•+Mp%L‚¨ªf10V]Q‹–GÜøCZ£­ôbŽrssÔ²·T muþ!6b²õ.è5M"6_+C­¦?l‹j ÎX`bxrG­dgè.“3eVeG¯e]–$»P.¢lŒdçeKµls6OÒ‰ÖJ¦Ð $#'ÈKŸ‘ÖÜ”vi’šöði ËÏhÆJcRÚH`ÐÆ닺ÄsjfO-õÜöÊÊÖlÕ±LËîª.`2rò$OãHXŽ \y±{dTÖêIš &ÿ²Vóh5·Ãþp—qoâ$Áª+õ Æ£C}õdåå`’IWg׃äž%ÆLŽamms¶1:×sa±w8¦qýf䛈RQ‹D€D¤æ. œŒTkéý<Ï’¼»ŠõþK÷Vlq×ôxw{;#( ó|èVâó,¨yù)óhÍ_ôQ"e¤QFugþlK^±7s!bw¹›±æ^‚%áÑ–pNüDÓàBœð6? ¥–‹rOD3QqqíÊè·o—ów ƒr¾þ¤c*r÷B]zñTÕ¢þú K êîeÂjòœ uV´~Å΂/ø÷·±üïù¨Î)O¸’ QE–w8äDxØ(mt[w#g¤Òvõ…)Ø&fø‰¯"ƒ31¿ŠªWÍŠm2k>Žð_QËQ3‡rëÉÂ-û4Hõ¶‰eŠ °†eÂbã ã˜dm¿m/×ê6n’°¸\fL"Pw"©þÌz•øŒq7Õ¸ü‚2#kqi6®µzG½(¶p fDdž˙–Ç1Õy騙dÜ‘’œW‡Û¬}ÅIY \E&ð¨cD]x“M³–Û  Úå¨ÉñžLe®¦QqqƒkåµU_2Ãþ챟sW¥E¯“3ú¥ƒf—ÕŒ’’_ÚåæeTá÷Ô†…™KMÜðD)Z¨Íù¢aú¨{bÌW“D¤Û—ŸZ²Q«÷}»&*çäWZ‚™y«•˜ 0©µÍ_âkK¦W •eвL>ª€[,N›ãdõ5Ÿ w'š¨ýÙ¨Á:¯Å MÙ~|3ßšµ‘µX›4û¶¨;±k—.óZ¯µâBìjo«/³´QBtt ò¶xŸíº™Yºû¨EÅ•8²ØB÷X±è«Á|']9©IKÔ¢í:´{´I›¿P³Ý؆BÎêÌJù:¶Ê¢QöRç—«k›%¾·%­LÓþ,ÒëgË£`ejƒòV²åw¨oW±5¹¹{ÒÒ‚LÎg^4›¾"[*11‰e;¨) ²0u¾i¼WQ¼Ç;Ï@×PEw ƒÑo^Mn‰{]èÍœhÙ¾´Í¿óÌ|÷4RìÒnï"÷Ã{ÈǾ–Ì} ‰¾[ßR¹ÍÙÁ|ȼ×5o]»‰\1³£5ˆ©³zÁ»º¾ïšÔLüÄIŒ¯f#Ï…"¿‰ !Hœ.¹g›Æ+º³r\Ç L/9”ÉÖ¢=r¨ð1·6òz½û¸–Ô¼¯šÜÉÅ‹ÇuSÅ0­ˆ))î é¾|z™»<ÁÏyÄ—œ'Åü“¥˜Œ|1qþpŽñiÐlÑ˧ò°á\É—{y¼Ή‹Ìݘu¾¸K/ò°+×(}‚ݼèHü»Šõý’Š‘ùO;îãÒæË }Ð;ÐÔ9uÓ9ý”1gcå S¹{Ž «=s7ï­cÇúkíûÍÃ6›ùÐY´vyâæºd {©UYk-ñ¼¹\SRéZ«“<Õ3]$„}Økš%|Ó@ýpƒêÒŽ”½[n†3É8Z‘<Ä[úÚ³]ÛÇŠÅßÖV@øB±®ŸrA\½Ñe• ½Æù™Ú…úÝá=¬º’à.ÍãÔF“õönCz³Y‘UƧ1ÝÚ«]ΩÐྦྷ6Áhðáþ+’)ÑÆ_Î"Ñ—ok]RSûÙ³»Á?~{eÚÉ\4ÜUµãbOk.¯â·o¾Y”—ýÍ—xã×<¾æ-J©ŸrJÚý’}?:_^f’<ϪsIÁ^SÞŒO“é=w¯Å’&»q\]†dËÚþ*ÜT²Q-´'®õåØ1·™e~87kéÅ~žöZ²q'ÙÀñÓùB`9­²»:†žÝçÜ~3>ÄIHï÷^šî•bÎð K }ô$EscøF¢ïæÉ¹Ý‘¾®õò#šJÛŒ+Öm3jнz®ò{Õª‘ûÒ9ÕsßALÿôU)ä·,?nU‡8TË,utW ½þ÷“^à5ž1zß÷ ºÝ„ ö8’¿FU¶šwìj_š»¹ÜùI_ÄŸ?&¦Ÿúÿ(äÍ+5kûQhø0í´‘ˆ¨öête ,¬ ° ‚T¸Ðà@‡!2ŒhP†‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœIó"ƒ†' @ÀÁ  ÚP'C‚MhÁ§Ò‡£Jtxô!SªX¯jµÚp+×®^)z8QìW³gѪ%+ÐbÍ·pãÊK·®Ý»xóêÅxsêNŸ.è´0aÁˆ}J \–ââ¦§ŽŒ–íä°–Á¦-ËYòeþÍg3ƒ^ë¹íÞÓ¨S«^ͺµë×|Aÿ¥¸‚aÛ GT[¬·VkíµµæJÙ¶Üvëí·à†+î¸ä–kî¹è¦K-¶ì¶ë®“ í¼ÒÒko½øÞ«o¾üîËìºï,ðÀÚ)À€ |p Ìà  qÃñÃSŒ±ÃOÜqÆs\±È_ìñÈ&ƒŒ²Æ'—̲Ê.‡œ2É-× ³Í4߬sÎ<LðÏ@-ôÐDmôÑH'­4M;commons-pool-1.6-src/src/site/resources/images/uml/GenericObjectPool.gif100644 0 0 121300 11701070263 23603 0ustar 0 0 GIF89a¡-÷ÿÿ{{{{{„„{„„„{„„„”)”1œ)œ1œ9½½Æ½Æ½ÆÆ½ÆÆÆ÷ÿÆ÷ÿÎ÷ÿÿÿÿÿÿÆÿÿÎÿÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,¡-þ3H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³W) ]˶­Û·pãÊK÷ ÚºxóêÝË׬ 8°áˆ+>¼81ãÇŽ#7ž ™²äʘ/k¶Ì9sçÍžCƒý¹´hÓ¤O«N͵ëÕ¯[Þ-»v`Ç}2x7·ïßÀWî.pwoâÈ“+x<ƒ‚äÃ34_N½ºõÏ‘G8ýº÷ï}³þϱ;øóCÍ£WHxûõðÁÞU¿xò÷ é×ßÏ_'þÜÿõ' UúÅ _nTà€ 6¨Òvî9(á„S%¨—…ݦarèa‡ ~(bˆ$Žhb‰(ž¨bŠ,®èb‹0¾(cŒ4Îhc8®ˆá~þ¶ãD=R($HÛ-ˆ^†ôãLN´$|H†§d“TzôäzQ"8e•\ftå‘÷mÙå˜}y^–{™Ùšdvɦwh^(f›t®Édœy½É^|2¤§uxâõ'Bƒö)a¡Ëº“‘#5—ÀGj!ÊÜIj1Ê`s–&%)tMezšÐ¦'ª¡ ªéL©ÚÑnþÏIúÜnŠåꀷ E*qµºuW¬Îu,¹fT¬CÇ¢ê«|Mw1XVÉ®WmO»×k\ÏZÙ@¶4] ž¸@ûÛ¶lG,H榪ìxÌjšØô†(­ p˜#ˆù2Vï¿–4Àï[ðÁ'ìU»¹¡‹“D,ñÄW,AÅX ±Æ_<±pÌqÇc<±#Kì1Å)«Ìò+ŸlòÌÌ0kš”°.í«ÉìHÀÓE°o$“ß盛³¹UÏq’k0² &Odþä^ù¶¼Ë}.‚ÐKYw¶²·Ñc;Ô࢘·(Vn‰H“5‡·Ôýìx2ÄZüƇ<ÚP&gœK Mø>ó îl³" X¹ j»#̘1†nŽ ¬a‡¸½ P|°ã8?µ)²rµë£ϷňÉÑ‘vÙ%-©ÇïAŽŠSä"Q÷±-òì”K#LT—5Îd…#$äÚ&pÇI޲r¤[g–HÛ•sÅ›ÞÊj™Áñ±pmE^k9IDNNx3YÁ)ò‚ÖdÙ&9)Én²š¼&7(ÆnNï˜?c¥KÔùW¢±Ý+ä牴NÚq×þ€äìh¹Q>2šüL$ ¿^Š’“´¦ùYÏy‚3–, ÎXÆ8+î0” ÅèBw˜5ivS¡:ch6jË€fS •˜EE ÒRŽ(M¤4£hÅzfT¡$]$:QÇN–ô´-îŒ , x¾ S“{Ti(û(3[æÌ©ZT*ÌiQNq©P|j‰i2TQ¢?‹ÙA•¶ÒŽÑ4¥ÙÞne¼káÉnj rºu+“\äölëZ;0bfWìŽòeÇž¶°Q[Ü¥g¼4'’|¾á{Mw¿oþZ—¨-5éJ˼¤Ò­ÎÍžå©—ÃÜ}°uÞF´­[]ÈAG¾À^ذb6êšoÚõË_=ÆRŽzØÞw§íÜÂÖRàG¡é½ÅÝ0oç&s5O{8]Ú|×F×·ÍõúÙÌ•÷þ"½’¡ÆM‰<ãÑ*A* ¸cÁkâƒXÁ“+îÐOKÞýâöð½ùaC-¬Ð!éÌ¡#{èD7zÑ“Ît¥ lºõœžô`Äê^!9bi‡O‘BŽƒÂMà…óÛ2ÐÚÄŒ;Zõ.9Vµ‰ð£žî¶ønvÀ|Ëî$º;¾£÷¾kÈïüÞñNøÁóýðÿ;â /xÁþñŒW|áß-®`½+ZOIÐ÷jʸ¯Gë|”5GàF‘‚ÄëÎjŠìÇ6SÓÑvÀø]èºÓ±·sÔwÏlòÛwÀxân|gJ­HY¹·–Vy•f97Z™!Z8!"~è!„G‹I‡wç!™|ǘuçxIù™™˜œI‡ Й÷B™Ó¢m £Roùk•FzèFR]”PXõE„E—é•@—õ“ƒ ˜‚rYy˜B3`ç5Â9œÄ)œqYœÈ™œyyÆQ“2JšÊ¦pªœØÅ6»”U±þ©?²Ip4›ÉT‰–ù•.Y˜eâ›Aa“¿¸hÉ‹îÉnΔï)ñIcõØT©9‰ …PZEOy›qÄIzµzöä}µ%R· hP„›r¦›% –èé$êY.s1Gó bé©‘¹“ä©¡”2Ã1)ÁŒ°9ð–U”1Ð^RUótGžuUðA µ]‰t£; “5¡Iô¡ ¡æ©;*K\ÀY7Cx¤å9žc‰¤c¢Iúœ“((AçbudIʶQeµ83ES)ó£-¶C ¦ÿi:<È<7J¥"šUª½ÉˆJ‘÷¢/ ð-ž©™þ9¨¢¹™vg™„Jš‡:x§¨žIšŸé˜ ©ƒj™ q,* sÔs^ÛµP>YåbCZôÔ—p ›éb6š›vЧ»YŠZѤPñ¤Db›Ê¥œºº«¼Ú«Ã92ëbêÂ&þwšãeKÚG¦˜U\He7åO®µQþ“P\×][ª¥Øz­Ê³b«ÁžíIŸð)®öI®÷y®æ ?4t Ϭ@Â¥¹ã‘‚äy§‡ø3J·lªC^ºs<‰¤V:žÇD«A°Ná­1QÛ¨8¢öª°ú°y§›­Üã1øAÑ>°T<ëv¡DwCä‘4vpÿyJ uNklYúþ•k'|ª)UóŒñX³òh³8{³ë¨8îšÒâ,ÁŒ§ùqàT<OöH>uv>oGÏÙX-‹¥kA/ë'ú 0q0ÓcIF ‘^Óµ^+g`‘º–Î1-ÝA¬R4JGóqܹš‘#¯ºÔ´þøEõù2*;±R»²X‰‹ÝÚˆä–z´R:7(£]ÍÈ5„…@–1)ÉEd^odª Ë“áéBƒÁÑÙ!¨Øw±ÒAÜ94;$úº}égIõ61ó7Z{5›EÔøjkfß)±Ù:µñ¶§ ©›7E.Jp‰ÛfH%59„PßY¸REX7´»v‰ªº²²þTAј(ê³ ̸”-J›ÊZ·áWCc´AŵK|Vmëº)f›ÒË·Ö‹JU»õ«+,»C¼ûITĺrŠTÚ%:¨”U³O`)^òK¶׳…a?‚)\È¿Õ;^ÿö^´„·ˆË9ÌCŠ¿‚TMx“£Pó¸(Ël›ÂZú·[q¿I‘¿1Á´$J~RÖPÑ„vÙ¬€³†[/J•É»WšJ„ -ÝËN¾áW}ªOtT,õ©¿äšDÆz¢ÄzÖÚ¯]¬ÂQk§.L(Wë_^û‰Uè¥8;ºÆ\eÀ?z¬L þ:½ŠGN[ž+Y„ì:-=«ˆþ ¡.m†š™xY-–Á”+`þšOVL¹JUãWåd0<Ûg4ʲ¾+¿c|l0¼aªTÉëÆ›¥È9eÁâ ÉK• ÿ…9ÍTEšÉ¦µÉìkk©‰ÈKl>»—ƒªp ƒ„vdZ¥]¬,^jÁ;ŠR³%ÀdåXËÜ»ó»“,<«eŒ-$©¾Þ•OÈŒÌë Ç)ÆÊ—åY”¢C¡¯*2ä1ú±½1QQÉÍŒ\3<ε9W*v²÷¬ª÷…1Õ›6sJÍD\cŸ\M¡<ŽñÄ5§ª›Õ̧­•ؼRf¦eT )¾a¬¡%bÍáˆV£4ÐÓd¡hþ¦SCSAØyTÃæõ€Ð J®57@ÆHñ ƶŽÜ:! í%Øt·oS„E¸:…µ†‹tIÀOSª/´Ut3|ê,”Ûjš›—·—t«¯œ:¦¨&7#k’bímã…AbdÂÕ\м ¸>-¸3JXL‹Â#:’ß´Oâ5·C½m Ðn¦l¥ÇgsH£s¼³èŠÛƒ—öL?§#h•t´$‰5ßYZ:•Ö ¬¤=-!?“…f¤$Â{)|V•òc¾Íè”ä#Ö]4ÕøÃ1É4hˆm‘RM•kÖAr½lfökˆ£h,p]Ùh“ÐØ‘Í<1ÁúLÖ&•¬qªVNîûµ!f›Í¨Ú¶þwpEIqöxÛ›kôAÊ¥l±[²3 Ýs[4œ­É”m>À ¦Â‚”ºp¹¾!«?¶–5ªfAºgc¤g®ûzÑŒ­:ÉÚ©uÖá{zŠYïuÓùú@)ËÐtÀDhq<ʾÅ=• «é,1+;¤4à^¹ÙeýZu:Âô¹»ö³H÷ègh§6fÕ-׿ýöEqÌšô3⃣ tÉߨC­fµiu3ЮÓtá™}Ü¢ý[C™,ÂWÇ«ê§îÁ+³P;‰)SezT„æP#PP¶ª;fô,·æw{ñYÊH¿ëœn$VQl튮蔳é7ŠØ·È‘¸`»ÚNçŸ3@¸Â«AIJæ;Þ ?ªñÔ¾ÞH„3:©®MYá‘nš‚‹·ÍmsïºÐóvq{lΖ¼Çy´4Ëóû:7¹ößömýö×iÕ´°h~¬èÐM¯ø#’ŒM9=ç…Ô‘ˆßo­+ÕZƒ»áóD¤saÐ]n6Âï­öÆ^ÕlÙný?2¤øD=¥pfÔpL¤Ý¾Ãf^þl~Ö®¾ß•$»6éóÚÙßšºóv¢6tH n:Ss&»8êÛ!ŠùÀ¯ùvSÁL.áÛ†ýcÙ°~ýÙ#Y: Æh>˜§EÝ8 .LxÁBA-DȰ Â‡ .LhÐâ nèPãÁŒ9F¼h‘ I”"T¹’¥Ç„ 2̤YÓæMœ9uîäÙÓ'M™?…%ZÔèQ¤D$eÚô¦•,P€@©-³ª¼ºRBWƒ ?bÔH0£@°!KJU‹µ"Ŭ`5ì ÓîË• ƒ:ÝÉ âYªVI2<ëqćˆÅºeìñlD°É&„‹òqE'.é2egÐþ¡a–´°—ïiÔ;M§fÝڵ륯eã„:¶*€‘Z!£Eø•¤ïÑ© VîÁ®…Wâf\ð*Ä‘S=·¤>×àjØ  ^kÑÂaÌ΂Ol,G…S©2œðsnÉæ[~~xãB‚ÇY‚¾;½zèëf)ì4ð@cCðµÚ6» *ÁF#/,Þ:"¯>‹|KŒ3²ÀbN4ÄÄ#íÁÁÆ#Ñ?Ñò¨@ÖüBýFLèC¬RH³ U:‰Ä…êªk°‰Øs¨+ðc)>ïÜó¯¿ÏFs²!”¨)«´’/¯ä«A‰n{è90©ÑÃõ,3€áÐêJIéÌ$S¡2ÕNLƒþkïÉÎà Åè¢DÍÅÆŒÐ9:åœóD0Í£óP7Ed(L1ÕKM%çLS Ã~ìèÅ%÷lÒÓÏ.òSËG%õTT³D).󼫈|T8ÞÚ” Qù¤£×Û«0Ñ:Ù¬õ¢­ÂãTïVÐEÃuï»{¤,€Y§2²!ÜîD Ö 9¼*£5‘›õÁR#¯ìKTÌd•3ž’Фa×öÔ¼]¦($?:‹ý˜äDmÉèV=üÏ*ÂÌÂR:‘¥ßúè¬P¾d@y"MÒed™˜õ´6±qEó"—££.( Ï=ÆKàSc'2é‘jñK0RÏ7†H?ÒªÈ -©Ì‚¦Äwë$ :I¯vöí0â$É…»6FîHÖòص¦Eñ™6›˜î8Ò.vÔ<àÎ)SbS‡°¶Pä•G$©Ì)¡F™‘hȇ儤JLÊÇ“†5)Õ[І*—Ô1ì`GËÖÈF·(®©r²«œÁ@)’`ȨÈäþj§¶†Ð#5IMÝìȦkÕ`áÏ\K"WÇ)¶P´”Æé‚†´¯PëO¾ÚÙ+‘õgÇÛη.⫯ª¼@[|£U…!Œ7¯®Æ$óä&+™Ûê7óT“äÉ* e¥rœu%ªMnL¸Â‚²¯(§µÈüVÑx„V]*é$m¡OÉù= ‚¶€âU§hyvÄÜô`¼M¬éå£÷r….³ÕÕäbuÃ)jʃ|%gü¸(›ÏÝNOËÏädx`£ÑaòTŽ>f¶Ø…ÌQømên4kN˜}Öä…¥yw†^N]×X+T5k™iÞñì(R-¼@$b½!þ×F2‘ªMmpZȸ’ãØöò3».þ°4œa)-6ÄTOi Òq8'–ò<Œ³wæwŸnÅÒDUHA¾•z—Ãô’OF¿O~!•iBI7f÷R=Zìa¯ÖºÑ©Î®–£Sã[æ81VuáQ#n3ë] ÿµÊ6q󢻨N³¾X…Ó;£q´]„˜Œub™º˜¸§ _Uniî/û=Vöiw èžH8‰HŠH¤Ž?™,Íè {hQ#›7û[GÏäÔÁî¤oݾ@ÔF¸eyšÓBIÝEƒ!"®³ó“è®"æÔfj×vÕF!ý±fì ò`Ium”2/Ù4¯þ1…æ®–º ÃÆ2±‹we|õ1]§-wŒ'ˆËSš³Ð‡œN4ÿMH(»Ô"Û®’?&ãÅç&I»OHb®»N¡«ß^ÙGíxc€ô罉hìWSÍ›·Ëx KÄqÐ ’…ü†y%16ñâÍ:á} œÇÄF6r>fIªÜ¸»˜^\;໌#!bÊ):[³ß… Éëeu“7ßWŠz¸SaõM&‹5Ç8ÿ†™¬¶$‡•޳[ªÔûE‘ÿe‘ÝRdç]h‡Ô;ßñ¾wÀO°ïÿûà w ,…öÖÙââø¬³ëu· 43í÷œÇµè. ŽW0ØyÍ­yq}þ n*;¾6rg}ë]ÿzØÇ^ö³§}íå®È{ò‘ÊÄÒ@>àna{^–»½©«å´æhèô«S'÷GÑÞÔá­_xì__ûÙçþö½ßý(Û›¹÷ ùËÏ{­û¾KÜ¡3‘;W 'mQ\¦Õ{¥&E}ÉRëZnáI½Tºs `Àldd\ÀlÀ|À”@<À ´À dÀ ÔÀ „@ÄÀÁäÀ$Áô@ ,AÁ<Á ¤ ó#¯ÔC?,Q?WáŽü–ù2¦:¶áÂP.\‘-º*q)ÂBý ÷À8ΡA(ŒÂ±Ê€ä‰*”þBÔØ=y‰8r›Ž³Ð;šÄŠ›øR¼R’Ôâi09–Э›—{µéÃBÞƒ¼+-¢ ;d<¦ú ›]1­@<0^)²°—rÁ•LÑAÓQ0ùº¦Ðk·O ¿>”Â< +ñ¡x¼K,Š­£³B;94È™h©??“¡=[°Øüx«+±Hœ Z‰¾1 ÀÙÈÄOüEؠ™èÄNä‰bì‰cÆžÐBÉÛEÁ¿–¿»¼è™(y*£t¡b=ÛŸPTFp¬·aœ“Žq¬ s$Ç àÃa\Gw|Ç>üÆUaåxF¿»ÇhÄÇi$<è‡ ¼þâÁ²À¨2ª9ˆ`ÆpLÈÔ0 bÌ ÈKÆw„Èc,FФÈv¼DyD•Õ‹7× Û •ŽäÂ×{£ˆÉIC—PH•¢½°c¤ s„Ç‹ŒÈ™´HŒ,/ûÈïÛIiÌG:„FéIì™Å[I£4"t”IœàÄ‹´I˜|Jš„IˆÄÂŒ<¿˜5ŽôHt(ÖãÊÃÍùÉk K”@È£<Ë¡(Ê›¸Â‰dÇutKv„K›˜J)4ËÓ`€PZ%šQ%HÒK:½¬ìÊzƒh_DKÄ ­š8ÌŴŸ K)¬JRI¨„Ó"³L$%eꥃ¹Î“ÌÄ ÍÓ0•ý;Š<„Ì(´Kþ¾HLÀlÀT€ˆM¤M„M¼@ܼMÚ\Á 4AÝ,AÙ¤Mô@tÍ|ÍפMaMçœÌµ\JO¡¼Åp»±¢sTpÓ»kj*j„¶F=¨)Óœñ¥Ùs(­Ô ƒ›xµ*úH²LDÅÔž!ªÚÔÚ#·)ªGæ»Õ5’´‚´U„Ó©A JÙ;ˆ½R¦pÕRY>]͸YÝ+d•;sû¤mÍÖb-ˆñóU) 0ƒÒVÚ»¢pý4œ4huWƒšT»y×{Ú+z­=-´VþÙHJå$A=<—B6TÆÖ©ÔU6s-˜z)ísŸBÂ;U´É˜X¬ÿB6:™sSUOúWèPËá×ÙØH¯D‘Θ•]ÓL)’€(X]˜n»©­|Ö›-ˆ^]ØÑd±ôh¬º‚Øë³¡a¢Ý˜hÄ ¢ŽÀµà‹¬áÐLÌr¡ ÌC5¶>©€‰û¢•ËxžBž©=Á€£S0‰’W­ºS¿âEž%©«Äü2Ç`¹Â@ŸËÐLø³X2*& ÒÝ’”Ó±9™ë¹»9‚ÛeùC6ƒkiÃé3ëÚ'ꪳS—Ê2˜ ÚÜÃÁTظ=©þ¹·ºU-3ƒ¿Èr·¢”ÒAÚk”=[E6”«ÕqÅù“®»:¬Xy¯ÅZ0í±*1Ù½é:£û2vEB´Cµ©-$K˜„QÚ¢çjšB´e*]†Å¡ÒqŸÖß3Û¿ß},0;Üõ”ù;ܦI_ö “Ù)¨ÙM®0AÙ¿º}…ÜdšC]¹!?[0»+íMœêMUD+€Á FYêmžóÞu:Ý€C“Ñ`þmßNß ½+À8ßA[4™Å†A˜1kßÁ?Ã…Yµ´2«Ûv‹žÿ…%Må^ Z^5L_ ½¨‚šqR¬œJ0Ž’1»¿¬C .þ/…ó`þõH·ÊµX¤Ý˜žái!Æ?Úù]*¾âø… Ü=˜ý¼—Èá<EËô»÷+–…AK Y®úmàÁbÝ—í³]ܪHzâ°Âà[Œ°0#á1f¬@ 3h0»‚¯ØÑàVTœ 5¬³ ^Ã5EG– 8ÃÅ’šC«`+ÃZž°”\1ýX«QY¨S¢õ‚2ŽØYB6 ò‘;‰’ŒˆÇð¨®ÛôjÙ¡¬¢°4Ÿw;6ÔµWÿˆÁµ7¾#_ËÕ’| L{6ÿÁóÈ£ ÒÅìQŒŒº›°å[&!t¤±‘¯mŒá{¹M…aCSÂLÚþc26ªãÌ=Ü&™f–D^Š£¸çñ¨?…£Íèeë·ß?í¶YÉ¢—ÁÇMgá¡@™XµG‘åÇþ>ìéí“Æ«Õáä¨#Vï¸æJê8¸`Ö­=å´z~ˆŒ¸f÷ygðAgö¬^Vqm= +jŽ I¤V¤rmUSö!cÕ?‘°×œ–"™‘–½ÓM}W R¡”­å Vé€i²FX³.k´Î»Õ ÖÞë½Ì˜9Ó3>SYvÅ4,?[3Œ…Ù*½:ç°Î£íÀ \ÁôMÄ.lÅ&ÁÙŒQ$lÈVÁ#ÍÍÚÄ@LìÈ~ìátl+1ÞºêÜ ŠþCÚ];fNš_jx}Ã4v¦¥Êj'¡Wû8äÍèÀv§QÝ9e<}ÞíˆÓÇÞK3ÂF-îÝêán)Ó`ë¶~ãä5ã©'LƒÀ«`IáƒIãᘈ‘‰¶ž3KÞÌ ³úò[®râÛ6"£L¥¦ë£Öå¤~癩×@‚ÖYhÚá­ê34¡_&c¹–a)Žß-ždüE ”±)&˜Ö"ôNïYÂÿw=t‚çw>?xß÷…¿ó†÷s”Õ8põíâ^Ö#8Œsfè¹øVæí™K¡ãnçvŽ æfœ”Ø|äSÊõ† dek¨óÆØ[гrÎâ{î»ÃhêYWÀæŒõ×f‘#;oønïÁÈËõ.ú¢?!o&SöVz–Xë&ìS$K•j ®¼HåÿqÂCÎr&LŠŸy>rås¤_ßs„oû‚ßw\?xB{ºö¹v¹·û¶'Ñb׉ 2Y¥µ ï! :dÕpßpI”ôÑÅzVõÒòBz§ÏÃguG§#&O Ît$þG*{LrS HIަõè$ùa¯û`7Ñ=—P½ÿuÖ÷u×WýÔwû¹ÏûÅô¢gËØ³NÕzMë’6nà?<’µ(ŽtÁ'Cš9éÉxמpÝÞ”y/ÓÀÚÇ2ÀeÜù½À÷âRaãya3}ããÿT½´ÿ~‘Q  öW 0Dÿíwùojì‡ÿð_ûçÿõ 2È€BA f0ÈPÀ‡ &\˜p`ÁˆjlÑÂ…@†’$È”#O®\©Ò%L˜(c¦T9“fK›,g¾ì)S‚H2wæ,ê“§Ñ2mêô)Ô¨ ¥R­jõ*Ö r¨ þ×° $ëµëY…cµš…Ø@-Dµr¿Ò+ö®×¹áòwkÞÀ~·Òå«¶­Z‚‰:]Ê1VȯJfZ9*ãË—ŸnÞ,µ³ÕÌN=75ƒiª¢K?œÀ²$€ &-iû6îÚ¸wçÎ=Áäݽy¿&.\¤I Ä—nü6ÅÓÒ¥bœnýúiË·sßÞüyÐîâÁïnþ=¼HÇ£fX;üøòçÓ¯oÿ>ƒ–#Æ@Rùx€-’k )÷Ò³…$Am I–d mÿYPa€¢wàkþxXR¾¦ ~,¾¤ßkŽÝWÕ{3ÚˆY~¥þCõø£A9¤Ey¤Ñ5%d5Þø$”QJ9ev0Zð[²½æ`…´Y\q(Š&€ºqÙàŠ þGàŠ]rÜM+^¨"nn)˜EÝ&œnÈH¥b€JÉ@mv—ay‰2§hwæ1Šè¢â9zküÉWS º)§z*vbŽÔßI#÷Û€$z¨Ü‰*šäæ€þ5›„Œúæ€'™(a¬$áÚe‡nè ›ªÄ«‡ÁÒ¶!+ȧRŸ:ù©| äyè¡ÐîéŒØZ )¸èa{\ŸÜ–.¢—Ô¤ºÔºû.¼3†º©) j…oΩ"³£Rš+­Çn¹o¾—þ”Òo'½IâJ´*<'¯ˆÜ0rwèS˜{¶;h¼ó*n·Ýj ò¸Ûš|2É!LòÊ)CkAë†Ö1Í5Û|Z~b‚Il€ æ1¿â›*—s2ÌRÁ ,Ñ³Š´«¾GsIâÑ.Ía¿Y\)Æ'oå´7[ePW!vZi›…ö\k›vÛdÏw^oÓÍ6Ùn·ÜgÛ-7D–‰=8á…C5¯¸k^¨4°´Ý,ÅR£(k³OŒtK_éïÁZÌoÅ®ùǬ¯)E-쨦ƒì§´†c•³¡ãÉ>;íµÛ~ûJ‘Öžë½ûÞiÎ W “€&6œ,ê"ïëñ³¡ ,Фþ?ÿë­ýîd¬Âò—ú–É*/+À¹È<çÖ÷5”aÿîž¡çf®ûß®?ýóÛÿþýògûçîëûÿ¿}—›9+qcª‰H´­øŒD BYHÀ„¹ QbBz&˜'!¬[eÊúž¤>ÿ 0N"Ip\t›g±¨8ÜÏn˜@QLG!óÖ¤ÐU²‘„€>üa|‚w’2Uê…'taLØ#)‘‰B”RUÀðX@†ã!·*訇6áú´Ó"®å„†lbâ³ô„B¢´ÈKJÔ¤b‡E.αd(ñ"ó¨G-Ñ€ºißIPH@/É1C\‹“c;J%Ž*þËâ ã‡ÃÞà?{lH‹(•5fò}›Ã ÃcÅÛ<°Š\tI)ÑUG-†’u—|%,¯"DTb-e:z‘ 1xÁ&š,Nà Šp$¶ì‘t<&Ê\ ¼KŠq&ÒRäôÀlyilºJ¦i“„m‹C‡À‘ILH¾¤’±<§ó£Ÿ(’ &"åH~I®] E¸ •x4+‚ä[å$ÅÉÊÆ¨u{`ôdÏ‘ðäž;{ãKZm~Žx"³ å$YL€ÊO™èüè9g‰…f+•à˜ž‚½xÞ3‚þ™&ä©:‚sœ hPÌY0þ®™×˱º¶Áãô3C—Kþæœi¡^zs£75&It Ò©NŒ 49hG6z©KkRšõŽ¢ª=l©/ÝS9ªVrrKªcf'7”UؼŠNâ;¯TÅP79kú§?‹JT6^T•l¥b´¨ªX=Š4¡Xcç«ö=Œ†¯²[œ²²§/‹–ñ€ûjÙZÓzØtT> O(”¹¤ñÌaþâæÕ71Ê=ÌÚ¢œBKÓ›xt±¾õŸUK5*’B®D$bUˆ :ÕI­X˜ÍùD’{%±Šóæw;Zíæ´´y`üƒíenhbšРZUÑ›²bV…¢H^%Ò–‰¬¥hEÕßò¸}‰þr”µô"YëÐxqµ«[ ¹%™or°Û,”X¿,˯M3Œ·V ®Iiá&)×Z¸|‹C.é\ûÞ¤òf¦ƒ„ ní×ÛþÒxpÁe¨pqL¬Ù˜o{ŒCNO¨ë4þPjtªf—†§8ÈÕ4»ÜÕð¸8D¸NÊ”Á:2z‹+×5¨Z-š´Še Æ“¶,ì“3˜Ø³Ylý¤!=ä×VEhBkqŠçÆd]€ºÊäLðŒf'7§O–2|xê»ÓÎÓ‚ˆÍñ—š“k5²“šü¬É¤›EÐn·œmþ´Íf g2²‘2ãž„²ä¢G‚õä¾ MèËZeˆÆŽ¢þ{WB`ï—ßújó§dÛ°pOðŽ@GXY;µ—'¹5¨£í±Œ% Ã[е„ÉûžëÅVW¥xVkZºÜ(‚¶uríºÓ¶¸“FÜeâIÅ BšÂ ÷¦oêiió[ZŽ¼É h雸Z%ddu%ýÄâ˜Üß.NÑ=u¡ðv'±q¬q–(™Ôß¹ø˜œÓ“ac§wì7Ê9uãeç³%ׂ)o}éCYqAÞ¶mZ>hsCœçó.Ù­ÆG:Ø\Ñx‰2ì–nNN4,“Ç{¾Öý¦¼êSµY#íD=14Ÿ6ÌX²Ã„G'›–žµÔÓ~²ŠâƒC\Þþâ—»Ð0x1›ÝËV÷¹ç.{ÿ{ßù.xÀ>ï\‘»Õÿ$ ”moŽ'ÛÝ /ùÀO¾ð‚oKå3OùÍ[>óá•ÜÞßþ)¾ô¦¿éOÿQ‰£îª=ì)Ɉ>öñIýUÏz âÞö¾Ÿýá~?ÕÝ£s!½ÿíñ…¯|ÞÕ~ù§IþN_ }Ù;¿úª_õ£4ýúÿ]Û‡ý÷³oûð‹ßfݧù9cõô—?Ú©iÿŒØ/æ+–ö2£>kÔŸÿ™aþþG½S(‰à\i¼ßhôŸÿQœüýcœßt,àÿEàóà"àÞÿI ¦`Ž2L 2DÒGþj ø1†ú”àZ ¢àÄàb t¼`’`UØà  ÎGïm†ª_JFN :àG…` .¡€€`ò A4aJ!² JÈâ`ö Z‡Fá¾ BaHa^á’ ^¡¢ è`ï0Æ‚aÒ¡ êàÚ!‚ Ö¡Öáv¡ ÞŸâæáöá!ê¡"ú¡öáF ^RuD""Zá#ªá%B¢&B"‚a ¢(>D2"&îaš"*~"&ša$þßÒ˜cÌá&òáÖ"":"#&¢!Ž¢/îß,ê¢0.¢*#.¢"(át˜¡o-Eeà"þ3¢!RÀ)¶¢¦â/f#uDÅ%"Ä'fáÖ"5Z¢+€72# ~ U„b!^ ò j# †_êÅ£ð9Éî°c#ªõéÙ£<ò Þ@ž±¢>!B¶a.‚^Í|ß¶àþä(nŸgXäráR|#TÜa#f"îâàT NdFR$JŸ\dJàñY#/‚$'òâͨ#!~Šf´¤("„TA`AÚ^%£- cB®›uääIî N.¥Ä_= bu¤L†ã5ž!2Ò¤ë eR:äMVÅO.¥é±ßîh¥I²$êTò‘ÆÂËW‚¥[òã[¾KØœ#bàPŠM[Æþ¥^a^î¥{à_M¢_f f”¦iõ¥aêd.fúÀ%Wò—î8&eÒbú¥ú(fen&gÚ^®ifg†&æ^^¦hž&j¾^Åãv  Ný]Re$iZ_^Î&!ÄB8cj~úhîfÄæ‘fmVßqJ¬GdöfU˜&B¦CJu6†B´cubç fçMrçtn'xjçV.^xvgy~§xšgz¢§z¶'{¾§wÆçyÂcWf{œ§|®g~ºç~Â'~þ§~( (zBo(‚h‚6gW¾t¦\r*_„ç:'¨è^Nh\’åk¶£…Rqº‹dþ” b4ž‰ö…ݥ艮(в¨‹¶(Œ¾¨Œ¢h‰JÉz(D‰Æ¨ŽÎ(î¨ö(þ¨i¦|¥ßµhã©è.)‘2©“6)”>©”ºh’F©•N©A,çCÈIþhT»uiýà˜Â…)Éd¦¥•)˜¶é˜²é›š)œ’©œÖi]æè\.©™›ÒiŸÎ) Úiœþ© úé Ž©¡&j ºé‹,¦à’ôHLœ‘Tj¤Z*¦^ªª‰DˆŽÍ‡e*¨jj¨Žª¨–*©ÉÄÌW2ZAjÙª©Æ*¬Îª¬Ö*­bœmݪ­" L8†ÐEÊÅס’ ‰U©˜Rn1Ò³P”þ>e܇ˆŠ—øÚµ„`ªÓ áÎ’©„r( 1K ë~ˆŠÐD‘ÑÒµª¤9+JŒÝyØH\¦HåPÊ`+îÜuñ¬H1GŒð ±öÜ•K±JÈ÷Ìq¬PïÐ^Y³ap ‹ñÚ…GùJðN°JXMذ@ Œð•ÑLŒõÐJÁØ—ÃÌSúúËöÆð¾M3ñÌ!KpõäqöÀ†ðÖqÿŒ­ø ® ð_å±ðÆrK2h‘qàròâ²'Çrå¾ñϰð€@±±)p³þ›2ïö¯^¥2u‘òó˜æ~¯ø"±É¡í–Òp³Õoeñô —ðYò€éä.AÏòhVª¤W³€kMÜ @™!_ÏϘWßq2»ò/ë•«13Wñ/“rã _­-ßrš!t.³q!‹¤°C³°/k•s@ƒò7ë.>3,‘B/ô+o˜rK èDXYñrrx„qOŸ1œˆYŒ]!ͰՕ¼>Õ‘'lÝ®¢R3ûr‡PÈ/7Œz ïP·ñ½ø®ªËQï­Õ<´T÷ï ãëOÛ„tjhôt¤]µ®Î*ˆ@4‡ð­¨1Cu¬¬²®´r §²7‰m„„þ3ņO,C3by5^‡*ÅL6›lA—³{a s]=röìñøÍô +ë®<¦ávð¦"Åžr÷UFÕ.dÁŠøÀ5Óñ¿”hÓ¯q 2]µ¥HeÒeúÔÁ¹ªe‡]kÏ6Ю6ej¯ (·uoWÈ—u6c÷±CñÏ„p2ƒˆpÓ•zý³lsÕm*kG·mã6×asAš ¯Ð‡@Jühå~ø6«N|0è*ïNC‰]ë)AïJÀ”¡ü/I£+Hϼqw×TŸ,k«mÀ«!l{¸{ø¼Ö¾:šI+—"ðвüâ„Ë©­!±7 8…x†þo8†D6&i³5íšÒ­… ’È-«¹ž”Çt#ñ&«·ÆåõBÍÜ© Á–f¿÷áɾ¾·ÝÂZ^¿voÈøW›jƒ[—šÙ„·©¹ÜœøðH0u›—RЫ¹•-t<ªkr>ÅÜ0Ñwgɇ«‘œÁ0Póí‹‹Ú^ø9Ý·†RM8ms\ëú¸˜õÉËì븟¿F0(~„±çts¸¡‹Òæ† ãž,œÉ„I‰ŒÄâ¹çr›ÑQmáþ9{·9y|©¢¼«–ûµ5kËKkï³þ޳k Ÿ§÷“ød¿îx;ø¼6Ý,+È¥‰ÇªŒ<1/ÏziÊðµþ~Œ@ͺ†!{°G (±i“ã8w¨¸£aŒ|#Š©wø¨×:Ô6ÙÊ({JhivoyvÍÄX%Ž‘ZÈ€tÅ•Žy%ëxƒz<Ÿô|7¸œSÛѪ0œãOÜÆÙЈ·:.[‰ß8-‡xAo÷þm·–ø£ý: !L5ùZÊBûpØPÅù¡„q‡´'ûm̰¨×û¼ ›ÉèøCŵ…˜üµ²Š…Eyàzx¬÷…ÜÍMÞÎÍÿM‰®MŠ’Åφ[`YìüVØ…àiXt…Ñ㨉–h\øÍÝüM^ Æ[(¥}œÅ`àMÝx…ÞH}ÎW=ßx}ߌ½Ó‹}ßa^ZØÅ€þ…]œý؇½[ÄÝ_èÜAÔÝÃ=×÷ßñØ“}×ûÞè½ÙFÜâžßËE¨Óû›¶WQ¶Àê6 ¶Ø2°•ˆˆ(üÃúü*Ãú·¦òèóíéÿ\èýפ§þТ~‹A|íèíÉÆyŒ/=zÌžÒ°‚Xœû{†-n-¡»þèÏ„Iwrø¦ÊÓ™Íçóó7+<ȯ„`²ê•o‘w¿ŒO€V{*Ä*ª -Ç©ºßmézå ºçwC«™–Ųт‡yMè†yGíÎÞŠƒ 3(¸pÁÂA… d¸°!ˆ Ð"ÂŒpþaãEZd˜ÑBÈ”Cj$9fÇc2´ €`N;yöÌÉ áLš1‰ÊŒxT(Ò£—uêpiR¦M‡Uzµ(NŸ[¹öd0ujÐ X«–‹Ð¦T³gJ€*1(Ù·VãÂ=›Ð­C›ÆÎŒ[7n_½VÁ~8-TŠaº•*ô±Ü¹k“.Ö:Ð c“ïFå¸rdG‘ -Z :èç‘¥E‡Vº,d§²^îzÛgæÂO+“ímÖoÑßœ‡W• Ü7o¥f €:OƒÁ'ßÌ™-õ y÷v&º×bÅıZÈ+x7a¿€5‡µÐ½î÷†ŽÏöMˆ¸»ÝöÈ•Çî?7¡þæ0#o¶š€#“\-€‹©5ŒFS©–TBÉ;ÿ®ƒÏ¶è<jÃÿøÓD첓«8EÄκØ:ôÐÃé£pÄßʯEIÌ‘-¾öÃk<¨Ë/;üšúë/¨¸»Ñ®àÞª®0#u\1C™tHÀ‚4°Ä·JéA G:‰µ•^25(EIÖP³1Çàjƒ‘N°Oîd <ïìSO<ØÓNB”ÐAó´P?@ÔNFåÓQHÿ4TÒ?½tQG)ÝSÓI5”ÔG7ÕQ:UýJNà%*S|O¦Š4JÏ?'ÃKì:\óÒÏ*îú<(Ỳ±‰ZÒþ(ðRS,ý/Åe¢,3ã1N.ùZ,(ЖWµžM ?ñl´–&›^T•«¯¨š—Þzí½ß|õÝ—ßyz^èX•i,W!´rJ£ÂÜõ¤ŽBTï‚h(neúr!ŒWûì¢Ôô)Ö-’Ø.”¬ª yýÖM.ÉÍ*^·ZmÛ¶ËnéBHÍ•%h°ã†ŒË-ú(ê–½‡{•ó wîIÆq'srêͨÆ뫵¶šk㺮Úë°›øi®dtÈ^ yæ¶1ö¥ƒÝ>è×ÁR’šÀÓnÝû>ieéí†S¬£«9†p[meÌ‚Š~$¸Hvi–þ̺zîlÊ›ü<ÉÐAgRô$GýôÔKWt·˲ìÜd’à>…ê–òžêÙö —Ä]¨º{‹X²h7Ñòu“'ÎéØu¢@^„@€ >rM’J —5Úƒî¸M…& eºË¤û¤´ÇØL¿EÙ­ÑŒ?"÷/ ü·<òí2Žªp€»ˆ÷ú·ÄÑ­~‘è‡2zYìZÿ™‰m€»y™ {÷Â`¿ªÕ¯µ\ð °sÞNpF.ú|Ђƒ©Ûí€Ôž¾œp/ÅC eLT3Ì)mfÍ!Að„Ç×;–Fv…¸ˆ ¨alêÿ×Äï-Dp Iæ(h©çnþ©HËZFÅÑD®‰^BÖà¹Ì<ŠQ™çö¹Í†„X–0$Ö­wÔcù¸G?†®g"Ü!g÷6ÂqØR ï|žpµe>S£znwD:‡pôVgt8ÈèY€¤Þ 'cÄÇm,e%{–)A¦1ŠØq}nÜ[bÂt¾ôÉr‰/K û‚† ]ú¯Šñâ­Ú÷Ä •R‹ûbe¶¼8.m(š#ˆ¡:µ'@e*R•Ê&¨¶¹Ml~jSß”Ô5eMO‰óœÝç¤$…§ j²H–™Å+ Ñn“q `äÆ†ÈŸíb¦PPIhÊ1g éä˜/‰‰)â9þÓÁèK[sYìØ29Ë’Qqõì(¸–ˆ8†e1/Fä_áVšÊ™HôqUàã˜8Šò/Ã$0uvPŸÒ*ÚÚ³$g‹¨8*êRÙÓÔ12uKNMä[»èÕž>ÂeRÉU»ø84fýãÛþ 9£³*±ºZ3ŸÙ%„TÕy”ûvÅ$S®:[£›ÚwÊ7ÂE¤2%&l”M—¨F¯â;1¿Ô—‡šO ÄôØ2ØÏð”Ée"[ãP„PMÖ6u¬ÜSz@Óf°´¨M-Pë5 ž%Ä *Õ‰¡J2äé¹ {Jþù’`÷œé}â¢Äš qEmmÛþáéeï á„)5à-eHêŠéò²ÂgÙåŠ=š®M¤´u•‹Z†}’Дʔ}2IJ$(T3 ÁŸŽ‘Ž‘¬QqÖÊßNwfm]«xáú´«î”¶Ÿ"WFÐèO$äSãa%äF¿=¢5ÅÎñ&3å&/!.ÛW ô¥è’ÃpÁÏÄX»Ý€fgiéêUÖÃ,ÍЊÅH­Õy§‚žÃžÏ°ÕIoJF!"QMÇõݤ3åÚ"¬§÷e«d˜,åÈÇ-ÿjîOª–`+‚Œ±[ŒLùWƆ€ŒUt\Ç8̱–+&±žr?<œ›l™'òÚ"ù ]|F &@"nîþfÈbi}m(C³~CýG̪ëW…©U뚨gFÒ•Vy¥h¢A‘º…ò&ŸI¡Frw@:áïK»ðŽ&«.ŠlìÖÊÔMÄðºê%ÓÓü—$!Mé­6"VÆp¦Íââ$r¼ƒHö³2«/w\Ë 8†9¢”4¾EÒEŒðÐ2îfW­:ËšIÑÜ‹Àà%Y‘sÞÍñŒÕÂu뽶ۚݼ˳f0¹¤–£4’Q•ÓTyR€Âu*Eq“›–ºž…psB¼Q–Z85NqjrêâwøÆ÷„眔°ÝÍ&IøK¿úU°_óJã6“Ž1Å`K7‡•þìY_[×U¬(s¬JF‹=3ßRo‰Šµú@Ú¼ÅÊ7´ÈÛ›àØÆÀ240Ÿ´,¡ÁÜAš²À{1¨„’Äùª|›®c¶uˆ—NÚÄæ®T®jýÅ@‡ÑÝ]¿n?¸Šx­ˆãÞcÊ6ñÕ–`bù6ú‰ÊwÛ‡õ´ÿ£w:ñ]°ÊM‰Ö”‰é²’{]ϲI×söˆIRÊÅíñå©D"”г_u%˜Ýª?Ÿ½ïªµ– ½o”›É˜Ð¦W?šF•ÍeÁ×PY• ,[ p¾Àv²eo»VýUä“×=Q’ýˆëu°°M˜ñ’ëŒËï½;¡tÑk¨þ¦%•ǼåhHïâ#u–Ê­Vdq&Ç£zØ iopË>"ÜÆÄ%6,‹o¾‡ŠpÒ¨mýÊl$"¿Òo‘–ªL¼úK¿e¼8M‘Í!ÞO``=â‚ܪf´ðfÓÞ…¾ Çë£PN|ÎÎ\0:Æ €z¨‡þðo%d5”©4ÔäŒÊg‹¤ëbò#n\­Rl*bÏžpÎanªïÌ ¦Œo•ŒjÀpæCÿ+“<Ì[ãÔjg¦cîüð¨RIÀÏ©¦‘rHŠQ‡ 3±+ø®o ÿ¬hß 3„%Ö¤ïÜàkŽìík¿¸ñ6>é‡@b”Ò¨22ÊA ` )ŒX){Lïÿ–Q¥8Ë&´°J¢÷+ðœnÒÃ! h¯xnLJpÜÇóˆ±Ú„/ïlšJÏËÌËA6Hµê¥:€ÇìÅ\$ÎxK¼–8°o‡p†LèéhÐñÞ¦BèÌo,"* Ñ %o’ë4Ò(­þ»¢‡,Ìe„.Vü±MnÉû±8Š"k¸&Š¦È ùQ­¦ÐÌSI/cæ(*ÍLï£Â’uéÛ(.'1’}@"«x*hx­ÐÔñþhR©nøoÈ4¬óœo>¤m³†)’Ò¹æ#5²JÞ˜ÅÏ@ -dðǀ阈½‘Ü‹ü.†*Úï'‚1}z2†!—މ(ŠÍ*ö,¢h0†åP‰pôq.â1ð'; †Þ(øÜ Ö ñ4f6ÏÍ£$à#ÂÄ{Ѝ(/KA¾¤ó0Æ•VfÀ¢ûv«Ê„¹i\h 2—Q|Ø£»ÍÝêb±2J ”—„É}H ­ˆÏêäÐþäBÏ8Í;_"ßVÑýíü₳(²&xÆ}JìsV1R4¹¦4e‡L,¬RHÀÏ:ÅÎwª¢»°ë‘ø“(&…hЊôâYˆºtË0qŒw <~gxðfh <èîÓTlé,ñkBlw#$פBŒ©ÁZÃåPâotÔ%ÈdGk/ú©”È“#gtAwâªT,GÉh̶§æÂ‡%"Zé{&Dæ´° »¦¥²s#7Ò#ç“>Ϭ4"jàÃǰ"^m¤°åùü Ei"Ð8”Ï@kYøô( Rì$íÞÔ £ ‘ìLm‘*$4¦ZéeЬåd˜ÍRMþ±"̯ *HãP.ë¢Iu¢>y*lRÈ ÍÀH8oQÎZÑŒb©¥:&ÝnåVa°åäAOP>Í4´­õô+Åß²ÒØ-X\òß>4>$ E[ÈN{+åô M±+PùPjÑhcEýtЇ¨äML­Ä2nÔM)+€”I I{wâÆaè±zÉ*ï&½¼j+9æÄL1oØÆ°˜Äj¯’ pÆ/J: vPoÌæn4ªLÍg¸MnžŒµJÒœ¥ûÊ N™QGR-Qǵ;²@ Cò 2”P5…C»¾UNütbñëQ›õön±Ì$p£ˆÔ†U‡‰Vr*ÍþNl¢hFGµõTïïK}K"!l˜ÄJ_KV‹«B؉®Â±Æ..{µi€u@ Q#ÖÆÅDtwŽ–@º£Eù³©âD+MI]LýMÇ‚°n\ÈDŠm5åd¬3‡aÎÕõëØSAâG+§`h¸6¦A?f®´4Ï­=o¸lÍ@v>Ÿ4¢#Ø^3÷®^¸új «rW—ÁTQG2ò\g7ŽJ•„Ô#èoN¡ÉXy!¿‹,{q,=¦%¡hgPsÁôêKni°öÇø 5‰²Ö¹X70$Åüò€6#„®pí¬!„ê¥^ÌǤJ¨%¾ÊË[CþŒd(>Þýâƒç*ç ƒÄv?²Ç¶ÎÒè"±u<ú‚ZRm¥îÖYÅèe©vÛQ+ösÁâ‡æï+;ÒÓHiüìIŒ^iª¶¯9cW'}êw¨yisUû¸ó€ø”HIöŽü‚˜„~äõ ·£‘-8Ù´¨}1Õ5Qþ0ÀpË#[nVHUE#êd9«PnïÉ2µFÁ¸3”Ïê³meöF~E°C¡ïÈÞTI‡”Êwùi•CŒyÈ&~hðS ’9ö’ˆg;Uw¶ŠLi**&IXÑjC€ù¯ñž³‹bŠ,ýÆyËJJ-‹ÖhÔOéd,hÚH§³yÄøWß3<Óv?õ\êÍ?~eÂñºŠ¼XY|u‰ éˆeCùèt\ÇCD-øŠ†ÓÓÛWm;–yc˜ÏÔ!B©MF©ƒš§³ôÂ.r}\&•#¶¤Ìê씀íŸ(«ÈˆI! òN×t)$a»“—þÏ þ_˜ši‡—;³4R“v‘ÖnwñF~‰º¦…,ñO ÚÛÂ6`åÉËd,¢Õkù5c¥o•é.™'ãÓÊ;PÒk­ziŶ‡vé¯ÜwÙXS@'¹ðàUaƒ ÷FÇ·Pœûð¸Ü¨k‹ë*³0í'G§õÇ!¡ùüDúmƒÿ˜©oÅÕœn­™Š.Sƶ*ÍŽ2wFáZ'ØVË?Í«ŠÎ:ÙZú†t;â.k§ ñ9–í¸ˆçK¤˜ò…}·€Ú Û)®—µ)c£3àªRì=¾/jquU†]›Ð5$f@ïYzt¹”2¯„qÅÄ4Zµ¥Êì ÿñ*u‰è4> = ôþÍ„Ôx·ûTvtKnF±k«7CýêPM¶¶Âôh E²e¹_a…kÖ]˜6B5¾“õ.nYxÏ0Çdñ/‚±€HÖ–CF0 „‘.£ «™vº º¸NkhÇIÜo‹ª‚÷CѾj'?9,Þ4ÇíÉЖ.®®YÊë8¾8m%o-Irbv?2»=,`³ ²³¥5VVã•‹§‡ÿjïï˜Í’„›­ãµ›5J-×-—·´•„%˜PM·Â†T·ÃŠo®ÃžyÕ†‹›Ä¦PĹ5të"#·2ð´‚ëFŸQM3Èñ0¤j¾ñÈ®LqK£Í4·ÝtÑHWÖþƒÆDÕ_G„à´D6l¬Î’pÍÚÕB}¥Ù±ë e-Œ¾6CxËN•³Kú¯+{wÚtš+µ°—›ÖÁ™æ$UpXìS‡Â%VÊ úW•Ï&ª®Õ·Mf&iÆE5 • ñ|…éú4ÑÆ¨:40„ÇÅçG°•;”»¨®SB/]Œz@º˜MÖ‡ñ yB:5–,9*#gïÕ^‘™ýqd Å©T\Ÿ#—~Ú¤*[îqs/«’{û±¦ó[ZÙä±5,Òt¸™Gl³mÛ¸ {Þr\Ä#2‡BÞºUŸÎŠ¿õ'[}´BšÒÐÖŽ\ŠM¿(iYiYüþôr·® l‹q.=ÙŸxGyöu6Ù,HSâ„v{"°ü¶Šœ”û7<«¸ôp½5ª’×Yõ¯Á2±M˜®'I­Äkµ˜šÕ‡CÎrmŠ.dß#ߘµ¡ÇÕ”¥•,éc__Ì«ZVZ.?]·£oóТuÅ‚$ÛÉ /|œóP;|xŽè™i(›…´¥üpÎè¥) 6z0¸?hc[ùÚ¢ÑÇRaWu MTw±Ð|ür-QÉLÄLŠq™·µ†IÎwÆ`6/ì4Ä&¬9j)mékÕQð>þZUË&¢ýšÛ•‚q}¸ÃÀ÷d®7×h´òˆìJjÃÙ¯þ³Â‚|½z÷÷C!ñ ÜG<ÏÐÞƒ¨¤ö¬@ìCD°þØ×ýDÂÂ… (! ,h¡…„ '¼¨ð`ôÀð C ñ£Å  :ü¨q£È˜/3ÎD¨ ƒÎ<{úü t'Š ° À£M‘+ ntX2£@¥,7¶´€hB/‰fTŠq©À01†mÚ°#B°`*mꑭɆ\9ÒM+Ó €“n©ž<ÉoUŠ!ýZ%h!îF `§æ]ú8rÍÈG^`ÀSÍ„)/mhù¦WÊ/n+³+dJ+¤ÊÔrèÕ®eæ Š;·O®%Î)þZfÉÙZ¾lªªIÀÀ¬¶µq™‚óÖœ|¦vš·u{×ÍûbÈ'µ[yo€¸{?îe«7¾âº,Û»­ßžhõ­zóãç:Õ{½' h÷ÅW•gtqv|k¨l6Í7XUô)–š^˜ [/¡–ÝMÏY†8e&YYO)èUrÖ95p–‰"½äÒŠ¤!FãfÏÍF›TÝ}GdO¼½˜VXÅMçcH}TãJ^Yä$^ý8b>‚”eIÕHb‰Øm÷ÑEž©S2`Qœu:¦ßƒ‚%fa‡\V¥–žÝù c‡©åXU¸çluá™XÞEg[þ\5vjQmxS)™Ú|xBZau †&©AŽ(f;i&Ù¢I0¥ù6QH)&œFh=Z“‘øäEeå©Lš‰æwGN×'¯¿ÊhcE)ô™W°þHÖE.)Ym†{ú§B9’fª˜dŽˆl²Ê~TÀTä54®H&æÒ£Úi!E&€+švФÖ¥ÁÓ½·l…ºè§õ"œé]Ê™å`7Z žTXž‚©g£‡‰hlŠ$#9ª:ifÙ^l,“OÖYšÈØÑZìk•9GE]M0ÎsŒ¤@骋ۑa¹¼ßˆ92¨£*V– "_Yã§Í oþÑ"R ]˜=s‡4š `D }NøñÀ‡9VWÇtÈØ¡/$ñH× áIŸ²š”l¯U銂Ém±Î£º·—|¼0äò¬óD¬ƒ}r¹¦Z6$« &ö2Ï6ßDìC—‹l·g4ÂÜÙ¾tϹ6Ž0ãÕÖ­™‹¥]B·Q°ð:/|Ù¬"äxé_RŽPV¡:eidõED‹ &„LÄ׳ázßù¹æ>¤rñÃÿd~‘,‹q>ÞýñÃ{Ñ)¨õ»§ò¦t‰Ê´nYo 5‘Ýô¢•„mìQJ. •LJ@‡bàÄj7*‹`È~J”ÖÖ!Ã<=þ)Ìo4’HEJCU™PT t=C‹E8Õº®Ðçm-Z`|fÕ»aÅMq$[ØÎNx£•í'¢S[fØ=Ó¥m[ኡ”"Í-%“:Ëb4‹sE ›ÉÄ6&•-Ñ;,£€š W`jΣ…ÆŒŒKwVšÖ°ð³=%+[SÑLžvD¢T)5ÄÚSFB {¼ƒš½¬¯Rj>Rca"CâçA r_Á¬2?ü(?öAÍýB0Á0&m$e–PBŸì…ÆJÌ@úÒG¤eŒ†•2%+ߣ±RÆg–íªØÊþÜîoK² TòhFÏeÓŒGþæùÔu¼ÿD@aiÀqP¶IcµH"‹lÒøb†±-½hyâÂd&a²+aý'••Œ™†Òv#Cª4ùä•̤†Èï¹0tE %æX¸=çb§œKh°dÊÉ¢­è…æ¸8©Q“haéeð–øIŠ€˜£ºÞ B¬¥â¨æA~ D"jË@I*¾3–,!jô¦7“¥¦±ŽK2Ë#qäµi…ñ¿Ò'>W$¸Ñhey?åT­"¢ÈŸír{9+QBýY™]H×âõX¯ kLÖñ¤?ûõ¼~ê/Ò<%¿:ŠLX h‡~…é£îtÅ™Ih’_tÕ)2¤£*@UGÍþ0Çb¿îas+XE79«Ypró¬ûFµ¯ÔS¨c3#k?‡,`2À¤l| -û,¦6uAŒÉ­ãÂjrª,¶2ѸT“-‘F58®û ‹>xK'–"íDÞ ú¯H"2ºV%+©ŒC$–„+­IŒDR¹WHI®‹¥œ–„µÞ‘å²– {›&GKÇÞöR“Ímq“Rj-í™ôÉáLŒZÃôaÓá¢<_¤×•®¥ªMù|Â_Ìü77m\ë›’âUv1ŒÞrªÔÕÝ3‚ë)[îHT¸˜©r2/RŠ#…}”Â\ùl:DZ$ÑÄ7Pç%¡Ð¢ðHú˜n)“¦kq”þþFÙ¾þ¸qþ9-`þC½~9,ºÛ“„¶é;&Ζ' ¨,x®*AócάO¡yÅî8döbó^²Z_õIáë3Pýœ2ÙöwU'MÖÙg8]º êc‰ÉÍYq,ç\jÙò‚\ ¤C É݈YÇqIbq¸"‰>¥ÎöªÐ`"ª§ÛJÉ~œ¨Ë¨†žsë\V^¥Erõ¹*‘M×´&H"ð€²Iÿb6½]šiÐ=ù]²”P×d–K~t˜¹K'ÏŽ¼Îb‡Å8ÝX®ÕfOJíà©ñ›Á|L»>Ül25K"‚tj.»8a—”÷ü[\¤þÊ™–dz¸™vnáÆª½BâSª}¸¡îǾä4½xó ªæ%0ûvÛª¼D‘=G7dÕÄKŠ(/ötGÓÈúÔ¨­?nݵ‡ëÕÞf²ó&ž Ýó¥/œ×ªÒ¥R¹«n·üŽPõ-QmÜ®-nz_fú;‡:á°I@U `@xb¾,q}d!yE÷ô‡ Ô—ÚôLÄv= {fUÉ@÷E™ ðø>ç§pcÎÏym•e“÷Â7 9ª=‹¤%J4ǽ‘d¤‚òKášÓ%^ô˜Ç¹b7/4¼š¶'S2½m©$H‚l箕 Ö°%*»/™ŽxNo ë¤Ôžlwp¿þ²®K7{8¦I¥qe]ëÆ\—²zŸ¬ NÏ­¸Â€¾ºm&kæŸû~¶¼÷½÷gû}ßÄqÓyøü×>†P|úØ*aª—m~w‹|¡”Ùº·Xqh{Õ\ãwDäR!gpöÄjÕ¯dZ’³d ¦#wÒ×â)lP£¶Iàµ*1£A'w3âµWGÁÑoùT5<¶Mêf}@‚ëoÕ†>ÞAv‘#·ó`1V3f+çc…‚FG&Ž‚'H}v"þ5f`GhKÄa‰qµD"b‰õ8uU'…sSÈ*U”jkö8-ÆàL°¡wÑ1oVüFbHQþ¨Ä…Pò'⮤jŒ’†4Z©ÅWgk§£HDz¨DC50ãi´c"ßâ=v”K04­µzÆ!d”S.ÿ2mü¥{H#L†xn±bœgGTsCN÷]¦wsúb2SiØ4„Ö'óæ{èKà´jsøU¢÷÷YÖãó<Ó6£•;X¸CZs1 8Œu…Þ2MÅ8R¦†‚yS òd7•7†r;÷b?´8~óR´“o`W/âP2¦/Ÿ¦€ŠÃmyF3SÔ‡¿Ñ,ìVG"§xH|™‘{>!YáPLÂGBÎ'-…üG:’%%$&oñS°‹”hþGoe¦„˱/¥¨Zy{A†ÜˆeLïwx¦…; ØW³Yž%2£`Æñis2e‰R²Së!CŒïq\xMWŒòl"dQ–aW²!C¥Ó"R½HOåh«–+¢l`ÄZ;ÒnÛ@1[˜Ñs@M¤B¤ÃR¢G12R͇zya•ÔeS:–l[©'ÇՇ‘_éVmØ7ohB¢Óïñ çV0Fh¶B|&v”ZÞ–\£x‚»BsÅÁÅcÀ5<•]8³3 ¥[¾lׄEA¦rœ¹ZÑ…|Nir=ÄRVVeÍ$/«$eû0” òPþ“Œ¥"p•ycÑMd–.•e>F—R)MT˜Jp'…ri¥6Sˆl·Zv–|{FWÕˆuaé—%–4¹¸‹I´´#3£rÀfœÌ%Ÿú†IÔ¥—;{3£O$Fb±×w´]ib vDÈ!™ Gíã(d×al ñ”®J_4¥EŒ ’Y!ÇQ÷Žþ€„A3;>hµn:²u·¸F*ŠaÉg‡h5Ú‰’ò¡L‘2’}ˆ–^iÈ8™X`äi‘ã™2* LE N#d¸˜0b¢I‚š¨©Os‰—8£f"‘cKqŠ sˆVŸŸ¶ZEÓ•ù ‘sµºs@#I¯¸Hþók!XiÓgiH5…@¸¹)W!rWŽwPÕÓ4°=ˆKØruUõ—··¢g6,ury‘B Æ=.ÅqÍw®&’5ZZrn ™Zžc·¶åžLJIDÑVó.ñ„ª”_2¨%ku•Øš­ªmE+׈±úh]«w%P‡A_´c°ÚHI§[”z61}™ÎáQt‘…µ«³ŒX¸q9òIƒ5á*rZ¢‰d£ê‰š¦U i’=q'9 1~1´Æ!}£`XdR j{ëvd‹ê }øv¹"ÙU&æl.d ¹õ>M7`_“þO7„Õ‚¦–4#µm<¦zÁâGª‰¬ÏŰÔq±xs·$éÈ]*¹Jдfpˆ¬&“t5P‘gd¤'êèª.—5p'ÉL\‘˜M K%Y€¥8‹*’B”ªÅX;“oìv‘æ ´éúq F‘‡¢¶E£p‡7dÛVgåT ”$Ë3h!šÅmˆD Ôf'©‹w"Jfèž,$k²S†Ãx`âL cé_(³®ö"qÊ<®xP¯¨qÌ’7Œµ€™u'džK–×µš·ò¶7S¶»è¬ÌFk:="”ØÑ©=+„™µAëFa°¼3Dú_Çh-‰r»b&þF•—Ä<Ï(6˜kc7IÇ+²§Tâø^R!6ãW 8Z€5F;43U«P2¶©2›ºjlHVÑq;?TâV7è®U¸ÇÛºæŠ.šŸè¾1‘1Ÿ$9r¨:µŽ‰V&hndÒ ¤BšG¯{mO1åñ&o¡"6ûO$d•C™ýG¶˜§11y/õ…l/YLþbJW¨6£De» ¸‘èCÔÔ'pÁd™Ruþ²=’bÃ5û;_Õ”½+­û>PÊHZ×µš/†¾˜%Ì—‰ID™+¿F±>¬+¾ûifq™){_Ûã?Ê–(`s-üú—þ*Œ&I5lbþæ÷ezSSÊր.9› ™L®’C˜)¤Ä1ióšÃÑ{8ìˆqqö·ÑÄ0s¡5T4¼P{›>…½hƒUº ó½ò’]­5—˜éG¾ú3oå?êV¥O§¼—K„sÚÄ?!´Ë ÀÝ¢±rô`‹7ýëÇêE”{ÆV;>b|&ìÓ.,ñ.þ!pøv3•ȳ¼ü’Ç/uwm£{êOã¥Çnc£û´’¾8Q‡ðX£sâ^VhM~bD&h†ÁÁ˜»+Ž ³¬ÂµÃrˆ:¦ô¹3˜™lû·š8#*jl¹±¼¼.J¿æh;„±]z)”©!i5¼Ÿl‰Î–‰¼¥þË,þL$‡ö~jÃG“¦9îË(%1Ÿ‡£g«“^›'Èwn"¤ÒÓì'Æ(y¼°Ù{£DDwÉqO’ÆÒÆ3ÝÇ]‹W8êÇëJ§ÎA:µD™Ñ†·÷b œÇ""JÔÉgxÎö¡ê³¶qÊ»ñ*•¢<¨G¾ª¿k'Ž¥Pe}j¡*‹J\}È™ÕÉ>§±³äFº©Bt6Âz:e2Ë®Ðw4KjPZ2³LïñÔï§T Ó7âû=ƒ}¬¤3]¼€[±Í §$‰³$Üb;ƒ šô2Ò*íüD‡ˆÃñ–Ï3•ž¬…¸ÓhZEƒÿò¶i}.ZAÑŒ:µQþ™nÒ\Ó²]7Q¼ìë]²GܬÖåù¾LÜÖ+CïGVìpÃg‚xÁ-”;"¦)·H+tt¼ÕÕ½VªPõ[j8ÜB_ûZU2}oe2-¥<Ʀ¨ö.›½R MRe|g¬ÙpET†¯ö(ÉBUkMÊl½Ü:A¿øÓ–ƒ%M½ û!*aòÈ@æZðû¾_lá"rÛ á0Nò’6]õ«^l «U‰›EA5¦ AÏ«A¸5Ñ»¾5sÅ⻓WR·p~kºÕ êSQ,–1£k?R¼dŸU:Œ|\Ž-Öè,#÷ÇI`<&Ñá鹕SX›æÒªåfÔ=ÛþšuDÎÏ^Ê.Yž¥z§o(M5ÄÔÍ$3qc[âYeœÝK,ÀÕ+—¦Ö}ÚÉÆ|èä¢UV´| ]™—Ìmž O›AšÛôýÇ•£xåÚøCìåÒz9 äSxbš±ó¿ŠÁæ› ¾®Ô´­f…^œö›b{æW}ëüŒà ÎÜÄÜj*[æjëè Æ²xì‹&Ú\xDbÃ&¢ûY]ÉÑs¤Vÿ.™—þ9À/°ZŸX,báHV;lÞIþAð!¨ìz=Ê®ÝÙhÄ2ë©mèVþ ±ê¨ Wb4±Ä(ë…:*íØgØ‹æW‹ëi®æsï@ÑaÇ‹þo!&§3†œãš¼âT\Ü›– Ò²»ø«¸YÔm‹Î³ AçDrŸ*°yáö"C]¬RÌ­ô¼ÿí(yCÈÙ* JµãNï6‘ðN\¡ìà0›˜Ó  ÁmÉ<{ÜOÊV½áÎë«"iz¡vÀ[=&è$IÂŽ†ó qÙ§HTÃ[‚rqþí ×èK£w6ûvm¸;×TÂ~ÛE[·Â‘1<œ³äŽÝ!jOa/–U¬âÖ%†sä^ŒêOñód­û{sBO«}w!BÖ¹ôOÛºN6QŸáq÷†U;9ëº4 í®º£½1Ò£ÚÚJBa¢Õ˜‚Åx4Üqþ² FæSsZ ïrúÉk“Qž1@|&Á«ªÏaéÃUA¢­¬N³«J«(„:Òî ±+Wát Úóy±øBñãÒݪ•«yXsä[=çßÄâå+ßÇš‚MŸùi°Q¿>Ah§hËc³!á‚… 4 à…  à Äd˜0£F…-°ˆp"F†8ÄhR#à –LˆñâF…,Wª|IRd̆2Y†\ÈP‚I–CÖ,84cF¥™:…*P R 6 ^µÉR«ÒšF‘–$éªSÌfP0–à„’`Û uš2î[’r%`h++V¶WÙBþÕi¡îÜ  ëÔ:¶hbÅs-(8YòdÊ•#3h;ëbŒšK~+¶âÛ¼…å.&¬5°hÆ'FÜXvlÚŒkö ÙònÞ•¤,`a:rvz\ùÒŸ]».%šQpBª3'tTî¡tè‹‘ .¼œ(Å  ?’¿îöaÐô›åþH~:͙Թ}^ó{ò”}UÇ ©•²Â*¾î˜ì4µÊ:+-ÀL;Î3ÔX’p+Ç‚ <†ü{Ë5Û„SmÃë ¬( »-Ä ë­ÅÞ0+J¬çÚë*½H{PÁ¨ÔZqD° ‹Ï/m#7#UDrB%qÔÍE'+ƒq €8¸þ¤&û2H;ó`º;.Û¢;/õ󉼱X“OLèº `Ìf 0LÎÊ<.« Íôoƈ4-ý&œI½”諽äú.ÏÎ Òi¿×6sªI´x4¨‚'Ei´¼@‹kȸj|mQä*¼R0E_UQ“¤«$KŸ¤ƺ2ýνĮ[k­¯bëT¸Ö*ÉÀ“ÃQ»—œ­HX›=µYi¥5Sñ”L0uò M¡”ëö[ uÔ¼ñÖ¿;‹Î¤ùÈÏM¨ÒýòWÆPkÑ1±*t_óòË2´ýJ‹NN¶B²áûðe/]ÊŒA³ Myƹ€×S 4b7’NEþÙÒ¯V<Úg7›–Ú£LÌâM3Ó°`u!©n]m¿‘RaOÓÉRŠé’y,ž¶ÃÉÖ2w79Åd%~k¶¼% ýÄ'e rÒ|wâo20ÝÅür“ë mK'ÓD¦¶6áÉOtá—^¼Ò±p‚-¬”Ÿ„«$yŒbÛKÔr¹IÎCܪK|ôªùÕìsÂ_a¢&D‚]É…{¡®“»Ú‘ì^C M5¢Š "<Üg4,†1.-C’™Ü¤¼A-%soÚ—Øþ…¡ü\¥>]«[w1G­ÂÏÎ%¹¶Q*al¡…›À8W;‹5BéHa½ ½K12FRjE@ð™¹x†‰ÏüØ…æ©פ¤TkâL`_ÇX¾&a\L* %ÌhQ“z½Ir¨öF9¥]zZ•&r8áP‡irÖÈ$hДȵx|]Ÿí#aõ\ê*I.ØeÌœ"gÛ=n·91¿fä¸M/yà&­kcJKШÃÌU @âôX­8{  @-·‹0m["¯sèöÕ=Q%"Ì)Cdð  'b-°ÙT+8ÑøÅÂYòδ•àHz4W*âï¢Ð ”xÂn!o•3/þ`Féž²o&Tø¶·¼NØBíóìD£mLI©·8†’›ÇǾÂaö¾n~ð/}|øˆTå®±Œ+­²K3ÍZ9€f Pœ*9ËÒq¶‰íSs ^øDSgç£âZ‘`êZRÁÔk"71r¾2}D¾ÞÙL^â졲ä–ÚÂnsÏVpÆcZÅ.£ž*ì–áWõ‘«º—¢ùâ{zý®UП,åžVQA*ßf©£Ö̻ÓÖwÖgƒtjEÉÁ)ˆ•>2Õh":35´ÿ[TPŸ=¶¯“V¸º'In+¶Íõ`rO]±lþ³ÖãZ“¼d,K[MæÉÝCì¸þY.܇ƒ–µù®Áõ K¯­åçÒ/ðíôBÍÔè:¡^ÐqÝIª[›¦œeÂÄ4DL¤Sz÷ØfŠ„ö#é÷Mú¥¡›2¿1Û€k•§²g*еYT,¡¹#å¼¼? ¾Ô4IÜnŠ’W%ƒíˆK?Ÿ¼ZjÈ× Vô9òK«“–l±Í¼Í;2 ädI|ÌjÛ¬tŽ®¶ã·ûLb=j¦wx²£‹¡«ñ3 s²ýó°¢S@ÿs«>Óºùê=ß‹ ð:_k1‹˜¬µë¨¤“8‡ÂŽk œ.¹µ¶“ 4“¢?À µQ#!a£b£Å‹%,Q#¶Q µ2‡£þ¸ Z›™à©¦8$-â˜ÀÒŽ!“'ÙªÁ‹œ© Ë»nc=ËÂ8Jë¡«ƒ@Ýû3 ”Œ­²‰ÖÙ q®ÒD‚7qÒ¿8Œ@¤Ã0@'ªp»/Ð;´-’œs0v©¯”¦1²"¨HÂ+©Ã3[r4ÙÈ¥¢xºŸk<Œ á?û‹>éÊ"Iþ1G¢É!_´àY3‚<|9EéÈ÷ræâŸ¿!A¹¬j›10¬´¶‚ dÔªjúˆ*T°6Š$8â1:ù”?ªD칪 Ê$¢ž c7Ø€ÄpÌF©b²KüÏZÈÞ41ó-”2Hæ<– Ã%«[ÉAJ¹CŽP-—›/ñ;Š4³dÍXÄ—´L7#‘Iƒ§³铺±ŒH×´ÏŠGô´ à[Øé1˜êÎ “üŸÂI¸¸$#⤼¹‘ÅR9:­HI¯ÍJ&Õ‚ e>ö(ÇË;6»CTIJãÅPCµ)@ňG ¹< ûÍ& ÌìdáKü¤Ña¤ ÏMÒˆþµ×ó³hl7øs¹/ ÈÖ¬QÍÌ$ýL7ŽÚ,Ì¥k÷YÎæ‹/.ŒÐÛY¯g"­ÐøhsyL+•šµù§%üÒ Û—”¸¹qÃ"ƒ;*ï@¯˜«ŸiÊNâl ±³Zª%¨4Àá¼Oò¬1¬úLŒ,‰òÄx«¦Cõ—‡r” P©m”%ÎìS#=$ Ô 08€øOº² Ì÷̵‹ó MEˆÐH‡b¹ï4‰‰“Hš gœ  ¦"Â6…—ÃY nJ³b”XíR#t1"ֳш¾h;¬1ÂÁù’{¢‘¦íqLžñHŒ)&zKЫëÉò|Mn­Å¬Üªme:ûþ‹ŠqÍ6» ‹T"Ý$J þü:áè4>xI“Tƒ­›6í2‰[ ‹p \È`ã79¤X*´9اˆRÇ»ˆ ]#ïÁ­C±“4“'!ˮʼ 30ÜU=yKµ 9šqFŒ:KTPi<±¡tWIý0¬€W­Ä¹‚ƒ®½0I¾R©ñÁM—­°Ÿ7YìÖ¡µ±Ø´E¯›‹°)ó.増»é'¨uµ1a-°Ô­Á§Øs «‡(¹öCX<£„ùJ›£9ÂÚàª`“—Ò<§ 9ºóÚ¡Áï²ËU-„<)“IU!“UõÓv5±™5‹B2°Cr±c—þ ¡‘‰Æ½rÖ Ë"}YÿÃm’[¼ÊÙ)¶¸èט㘣pÎ{mí–R­;%Aè  ²Ázq¯˜3üx8}E¹¼…“ÜÕ™…%ç€Q~¹ØÂ8ÊÇ9MÊC!Ä«0ñ¡®È¶¥\ËKÏ×îÉÅ¿ ìB¿ô›}¤ÒäÆu!\¢¥Q£%C§é»J¼•ªÍšb¹¶[7RFQ-®øÀe ‘ÝÕ.;Á†‹Žñ%5»Ó_Þ „;¼CŽ+=دÔ$¤ÄQÑyù“ºÙµ#¶ÀÛt^÷èdš¥ä|T> ¯@éG˜MßCÔÜpeÊßÍÙÇóþë©X“ªà«ü»Þ^Í=Üã±!S‚¦n+Ê•\ ›³ ™ÏC$õ`Ô»”&é¼Ç£°"Ù#+“»Â£5µÄޙܴždéă"3Õ‰RÄŸî½µÿõ•¯„$Åø.“)Nnmáöbˆ~ÌîÅ/]›Šs­„£cåW˜;?òÄHìUßfâ­!¸!QÚßÀå–éq½ìy7éq"ú!ÉýÓÙs=Ôl+±q³׳º@¦)jÇp¤:"J®”k=)R‘¹ÈŘi5$ ÁòÁºãË#ɤÊG†Ùo=Z›G=[PÕ%!í ?”¤5Ú‹UùLZGnaö¥@Õþ1R2bi©’©éyT¼¨?Z¢+ &ÊË¡*c¿ÐÎçýéB‰'7ÆmN73ÑTN&6PCå {¥Ad3)ü¸ _Ÿ›†6§ÁigÖЗun¡Eæ·ÒÞeÞÛ„Y,çéEC¶ À%ê0`…Ý;·¹ÂGËÂ.ôÇúb¸b…b(ªF<å‘á|É$T}lbšò<ïÙ>á¾Oþ,-|0¡=|Ÿê”Ë~i”7Ÿüœ"Ìiô_µp,¹øàœ‹²;Bœiþ£Mic DÝ<@Þ4:en_šá!ÆB—äôå<©Š;ª5<<ø¤[Ä’<~inVšHf€­M0D«–Fþøxçj4ÊÄ”bosbúB’Fk TÙ-r–6Ü#ÎΊHt3^N×SáçÚÛ"ttÁy6@ŒÑÓ²ÊIÔíý^r~L ùFRDŸ”7SB ˆ¿þkÁÖ±‚°«å-Ã/¢˜9¥2뼚áaj è lÉuþ6ñM¢!ÚG‰bc)3ÊÇöæŠÁg·¼©€ë¨#9û—Ôð«ÌÜÝ~S’£I"zÎY©N¦™6Þ9ª@™×Æ âÉ_à!“/³÷YSo’H¡{© ™U|Ž™ÜK)ÀŸ¾eµúÒž\§FµKç|•x9( TmCÓ®`Ïô&ÔÖr¡\Ý€ä«R•ž®JUÇÉŠ˜éÆkÁid…q;Œx‘{ ¢¢éš;´çŸ»è(qv€¼vI×Â,õXùQÕÍ<ÕP¨þ›÷ï¨ÿħ¨¡½Ê:{úrV¶Î:ˆ/§@©}ñ¡ó^'ÈœŸ¢ (š6{Lß²g´æüj¤øàƒŒ+Q®ß»6ÙŠ–0ûïƒ},1Ð9è÷ãŸÿ¢ÇàHZ¡Vf¶¯™§BP[ä@ß•ámYpXe ’!»õÉ)˜àdÈ —ðJA8‰ÙïTa(4º[¡„™ÎXZãgDC•a写¹ÖÕ4ŸÇh'…³ãáä&$Ç‘…d!YÀOhE1Ì1MIéƒØtw<Õ(ŠÔâ“Ä’@%ê/Œbão¼·’ÒMïªÜÒf3´5gY„þcó¶5ë- 4Ò’ñ Ç@@Ao&³Ó×èô@?lP,ìö⽆YA;ñ`|ã7 Uæ*P㣶 5(ª42:Ê+¨âgJùÅï'¨ôÒêL ÊUž2–ì;ÊÏÈhË[âR$ýà .¤FÉé…žüLúØ8jKTu)j “ËÄaòØ7En2šZ䆆±Þ)Ð+ êf4?ÇK‰ÅaÌ´<3GÈ=2zÚ[ž±ú×Å'‚ëž\dåXÀÉ´ÝñS‹^ÒÔxvÒ€\"4¡d”Ñxú“ÅÖ x{Të4N°Q^‰lX;ûF'=†Íœõ>¹Q¿!sœ€Œ§þߎ¢»†õœÛò•›¹ ¦pN‚ÜÐH[ÚL»¬{°‘%Qaù¥Y–jJ²dÝ”`éÔXF¥– *UÕÕ€k]Ê-×&LMêN9iÔ)`û gRöU‰QFkcýêwˆ=•–¬ÌôK­ùQMn9ÙŠ¥¤¦Õlgcæµîh©ÁòuB“cãÀ¨€$²1H&+YTö²µìd9KÙÏ2 ³–Õ,i7[ZÑ¢´ª-fWûØ$U-mÏe¸i>@‹O{t±IÎMH…ò§}ˆ¢¥»P<Œ“ƃ°åJ‘_CòŽ“ «ž¥‰T?»&|Ü£+¹OaódÊiþÀ8ûAJªµ½ z×ëÞ÷æ†8¹ƒInãÐëÙi ˜ë–¢Jæ† ?ÏòŠòü×ä–ejYÌÏΪëDët'j*»œ^親?Ër[ÔØTÌ’ö>ª~¹ Nç@\.¡™¾*^ñl*õ’ B@·¹2n) ³Ÿ´ÐK.ü%V`¦ ^ûÓLH$֌ǾéwTr³ ¬±·ÌO??YJŽ”•îð8ËË‹zUbu™Åb3™OBPkûåb>yÅÂyÃl¶Õœ©(ç¸Ý¬Íÿ|³žMEÙyÏM<Œ®½ˆ@Jq™íh÷*¦Ik&( ¡887çùa—ÎÜv9þ]éLƒº[t¦4©;Íà;ËùÔ6 sºÃêGÃ:ÖTퟀ­‹g?ïÌÓºVu¨1Ï€þ:Õæu°-=é'æzÔÄ&ôJ M®I)ñÕ²ž6µÅHë a¾Þµ²¹ë[';Ü·±½mo›Ýåö5ýî'â ,ºÚòž7#½ånã›ÜÅÞ÷²õ}î|;àüV÷§ þï¸qÅÙê—´éíð‡CÊžàqáÁ>p€§ûÖ¿¸¿ ¾ñŠÜãgIËF’’C<å*?‘½•,‹ƒœã0ï÷Ì?.òŽwÜæÏyƒ»¢ðt)18?_9Ñ‹î›kkÛæJçyÍ™¾î˜C}×NøÎ›Žþ`ž ÝË)ùðHÞmô¯ƒ]7üçSË^Ô³›=íh_»ÚÛÎö·»=îg‡¡P²© o=ìzß;m*%¥ð™o|G®5ª ¯¼Ã~ð†O<á/øÆ3~ñ|+!ïJÇsØò³0PPN)“Øï¢'ºq]gA³9Éøü³°-Ð9«^Ÿ}žýêi/ûÚû¹õ©žÔ44õz~ô¯ö.E ÷ãË=ùÈ_¾ò›Ïüç;ßKÁ_‘g#;ü냽Rv=²ùüzÝç÷ÀÿíÇÏzñsŸöª7¿ú÷é~éøþ~ÓÇ>ýa]zS¼çOdzþùÍT ÿ ``©áŸ¨-ÆAÝÿþˆ£Õ_:š½Q\Ô Í¥ÛÍ¥ûM]uà²i`.]ÕHÅü¥J` Ê„B°àG°Vk½ f]V š–dA ~„ fò`lQ– F– ^V î Aahaáá êà2! :!Nácýà ba¾à*á‚aáæ`d±ÖAÈþ   ²áŠŽ|´ÆƒÞ?©ÙùV9‘†ˆqŠ˜p×b â b!Z»…Ѷá"ÒÖm%Lá-X·Ä™›üÕÒpŠªdO§éD&¾NâDâ¥"†¢©â#š¢$Šb©‘\þÄ#ºb£½!rqH»\܇4Yþ`(—ÅLyø!`í! Q¢¾h¾c²cëc2"#¢X@èÙÖ+Bc™9âb$Ë,f L—•OÍð““`™)æy‘¸…ÜŠZÕ=Ý)^ Æq… ¶ˆ;Fc<†Q,~œP¢ÈUÍå^)–RíÁSE oQ×¹‘c:v[AZ B‚à·¬¢<:¤+Nã9†]|ŒA^€ÕšÃ¬G1Î7®rdâ1VBZäÌ)ä–cÚC²dÒ£8!•U*ÓtèN©…FÞŒ\ÁÍ÷tSmH„9‹¤•dQÊ\J%º™]À#Ñ´äS&TDRF È19’ N @RXTqí£UjþR!Ó Oäü‰ÄÔGåZ¤Õ!e¦5¤üAå\æÒKZPUÖNp™Ð…ÔЮ¨Y É•Í\È4ÍΆŒ•Vô‡ŸDË2%­ÔbÊ¢å [ª%I&¥Ç¤U8#¹4%]zæ¢D$LæÉ2QˆEÒbù¶p'ÅTHª&ùe9S-¦t”ˆŒ$e¢¤nšco2ãöäOg~æpªÈK¶N=Z¥¥’iL… Áf M“îà ¹f„¨ÍYøGwüPPdLe‚çnZ&[jæ)"q¢gqžcqäNI5‹tºŒ1ÅW±P:lÖ ßtå½'ÅUWE¢x†§o^&ÀUz"¨ÊþÑ#0YѽLòPËô‰ð`Ë ÍˆÖ$ÓƒzÍñ'bNØ^&~Š£}(:ò¦[žh~Ûª™g‚º(¹'ªtÇß©†½°‡˜`YƤeNè–“)^¾"³m…ë´‘Ž¾å€¢èx*é’mæÝ׋Bé¢,¨}œI É•L­a—û|hu S¸…ýÝXô¤YÒIž¤€ª)~"Êe”Â)h.˜—lc¡üïÁÇ&ix”OáE¶ –ôé°û½\Æ]c’"©Šn˜U§ptOœJ*‹,h$Ñ¢QàéžX¦ EŽ-Ø?öËŽH¦’ÈŸ~þ™hԥꢦh«ºi"Nj¬ö†þq¾DUFTÈ ×sPIž!…Yn…¡…ÀHÏnd¯¡)£†Üš**³‚É£Êj´þ56Æe ’ï„c¢DØhˆB' ϯªÚGé&k:®ª³¶ê¿´žÈyJ«¬¾$ƒPeåØctü×uبd¢•`ÒÔ°ÌL¦ Ïk R¬¹š¤²®+«H“¦W¼B,nH%½ÏË V!R`aÆ­’Y,_}hbº§•æÁž+²&쪫e:*+ÂkÄÆé¼ÎŽ­¾eì‰gUͪ]ILvÒÑ]åg TD­h¹ž,f*ì’ hÂ'Ì:-J,¨*É˜ÏÆUMù”„L=ÖLyþ aqK™æ©™åÑ"¬Ñ¢kÒ2,Áµl‹>íÓÎë½\KX¨Ô ™bz”bâ~&Rñ”“¿R ¸¡¢šíඥʲi̽*è¼lÛºh¥²¥PLpå×ò%NºŽ[í uí$5'àôTµÅ†d*ŽR&Ù¦éé6ëá2[â6 ã¶í4.ÌÄ1£ ËXÙ@žNeÏôí•tìœ*­é&겪®š¶++ž˜ëº­ì|O¢ ’0Ù©˜F¾&‡tÜ.ZØ‘Z%ÇxQ~ôéBn àöZÙnêþ¦Ãšœò¾î¦€I¶¥©‚îï”G?ýfáHêöqXž~çA¦,Êïð–oQ–'þþ¸«ú>å”Ö$k° QRQ²Üîv-W nǘބS0vYãÙr0/ꢭÎq“ð´rEÊL$8¯ˆKÁúQà)X„M´Åq^†¡ÉH{†pÑz0øp[\—póV«}ˆûücˆÔ é䂜¥žªY(ýîjô¤C^Á¯›lø°«gþ,®Ï%ìÒ+Íê*ˆÊ&’k{DŽ“¸Ž˜üÔiן %‘”Ž±Æ±~°ù®Ô ±Q2­“D‰=iò²I4 ¢1ò#? ו"G²"'ò"W2%c²$kò%'o'W2'Cò&ò({²#O²)£2)‡r)§òþ+‹2,Ÿò‡¡¬¸DUŽÐ•À¼‰™ |BîJ¬U™PÉ>á¬;å LÀyÈÆf#ò\1‡ñSÝ ×b!¿©™…Îo”ñ7Cj8{³8û8ó9—ópPïhT¥tæ%GEEJ5WlyP³PRƒHË6Ý'=ë«aøñÁ®,ùñcsönPÕ(‡)ÓC3ŠC7´,?´DG4EO4+g´'W4F_´F4Got+wt°ï|˜ƒþÂWê-KM€²TþjæâG# úlºžæä½1ºÔË>ÕKûÀ¯mîÏ»Ãßr¸ƒýs ,ÿÒ„Ëë,m©±JÿfqË<ó›Û#-á’¶ô»ã6 ^ÒÉq3ggì'`b9­L&Mfåþf@\¸`á‚/Hˆ  BŒ¸pâÁˆ%^œHQcÅ‚䘑dÈ;–i2%Ë’a2È0“fM›7qæÔ¹“gOŸ?:”hQ£G‘&Uº”©N,-(,XááBUÄŠ°jÁWv5èÕäÖ°_µZ {ÐBW‚°uI1ë\»+ñŠÔ{eË»{ûªìwåà— CTДqcÇ!G–<™rå¤O1NYµ!…m¯‚%[à„¬4·Uë•-Ö·fC‹®;:¤êR ”šáÃùþ7¸àâÀO>dóŒdZ–>zuë×±cJ&CÞþ!Ú¶ÍZìæ×\Ñ=;^íy¹£1Z€ÉÙ¥óåÇ• ÇÏ|ÿûÿõó«»è²+ÐÀLPAÉ0»H3–4몠и:-´´x#K! Ší6Î<ôBÓfƒ¯4è³Ë¾Y4@[D.Æü`<¬¾ÅÌQÇyì1»í,úl¤ƒvs©ÈLòÍÁðºSOªÜLŠ/J ¹ÛLI’VTÑ¿ù{QÆ¿ “F-M"ÐÇ3ÑLSÍ5«H©(zP7‰Þ Î÷DâN´(çzK³#Ý‚*ÐÌ21·sÌE»ä2Q1›ÈL6)­ÔÒK«²¾“Ž\&Í ”«Ð9ºò$ÜBR²N¼ø,þÊ 5”ÑGgõ²VGmíGLyíÕ×_‹j!©f[u! ¤¼óMˆ„lu"8‘¤•F)aELÖFÅRZµÍo@`Á W\p5%ô*ªjÛ¨*!åäH¾t%”­Þê”Z«ET_|·Í•Ûý ¸/‚&×àƒÖQØÚ@7ÕTU³HÕa‰»²DÝJ³`SïºÌX­ ב³˜ä~7-8á•YnÙ²r;¬]¹:töÝw¹»ó,ˆF]ÍXQæ÷P¡¯5¹d>¹ÊvuÙé§¡^ja"¤jU Å«Ã=9$5Ð&3\Zh Çy_2•îVm£ƒv÷•£Ž[î¹o‚Ù*‡×;þ <ÞÍÊ4>ëj¨O ï{m‘‰F¼m²OÛd˜š¦[òÉ£žZÕ‡v“ð´ô@Sòª`¤±Ä¦kh´×ÖìÄG:u¶o%˜òÙioÙî„22(*²çDïÑþÙWDÒ/Eô’®b˜D%RgjíRŸnã»\é€iTŒDÂOqAÜbûܸ-‘ŒeTŠÝ@g5¨d¬NЂ[DÒ•7²&„D´£3Ä;²p4ãy;MÅoaDC>S—fq¦ƒŠbwRFI²MxÌbÒ¾HMnò'·kÞÒE³caQ^)šSØS§vñ‹—l[%ùhI[¹mŒœ´å&³‡K4àá]"Cºð™g•Å»Àß”Ç>¶²°ôâ$_”É[Nó–0#–Ã2´ÛŒ%p%ÊÍîD¸G)0–å|e¡)˹šíÄåH •¢ØlÅ!ò1‹þzV%ÜI79Ÿéʲ¡S éÄ—ìÜ™Ð?ÞÎ]2æ„jÆž¯ý-Ÿ‡â2 zѳ1SÏaÈR N U›*h¸ò®Ïi…prLfÞ6:ÐŽ”}ÅhA!RK‘îÔzåB_œPéQŠU4$ĪÒ{D€rÔœ2m M(MžN5Mܧ*r¥{5‰c¾‹”)™ê<œÞÔ¦†ëŒìGUµâ¡écUé †Å"éÐA8›iXñz²6õyR]ë_'‡A:^u YVBDõÄŸˆÝÞÏ´‡‘+Ö¦PżkFóÊJÌv‰€õ,Ýøw.útpŸðQŸÍhsß\éIž2Vnþ¾°B•¯gýYO†ÄÏî6n$m Þ®ˆU:F4,{Ò'o~†‘ÀE±.]Õ iiÝÌѶ2ê,o±k;,NefÎ §FʃÀÑÆ‰gr)åôŽ Â˜n¶ºÓ­­ÀÒìÎ{+©éŠ;±TkËÅÊø¸fÜyî Ÿ£,^ØÞ{Ùö²÷Ž~¥ïƒÉ…E­àíj;#OzÖµ©O<ÚÜÙî>\(}· 6±tì.ùB˜Å–²Üy µ_±`„þý°6繖ͬDB?|K ‰â¹Ä(‹o‹‘ì«Ûùø{f‰XU(:ž¬´%¢ö\YÖ7^žÁt½DVp‘Ýëà$yн/µþ6!­9d|â#pl~,ŸîùCW `!O•ÚHzùÄîí3-Éh6ù”8 #œv“ÕõA$E`£ZE1gÅýÌ©}N±¥ù¬[AoÚG [Ñ Åíjk[U¢9’š ˆ.¨éI¯X¿kLƒ¹ƒÐáô­yDè<9¶‡PQÕ‰ZUC‰úaL 5zyi!ÓººšÆõ³eäC9Ú#¢$áñ4ê]ƒØm ~êR•íçe³èºÐ6·vDíTo÷f„9*"ƒ!‘&‘ú¶fù<îY“û+>÷¿'ãé¾tjiR’˼‹*zWɹ±–öÊEfO\ÖÖ¥À1>]¿µÏv¡ ‰þ’‰i’ЦÓ8#n•ç›UbÎøË#pwWZ%5ZjÍUèLqï|åÕ)ÌŽ”—XuŠ7%ñMñ}ÏrAwzcdnÖšæëÞ3ݳÒõ]g?ëGz—§~Û^=·I¯8ϳØô®¯Ý(Qo^Fšì"“}éYçè‘Ùžw¡|ý©9§îØÍ=ºÛ½ç#ÛºÞß&{KüÄqOùÜOx–'­‰·|›Ì\u¥þ]óZ<Ú±>­‹_žô5q;ã›çwª¿ýóEûÙ ï"µ—žö|gýëÏùÛK½ì¸—|èW„wÚ—þôr·ºîQëÞó¾î OÉì‡yÛ'ðÿD¾ñ7ï{þç7ÿðÑ×{ñ¯}׋½óa­~ìÇÝ}ï³}úØO½^WO}È‹ò­üú~Àï¿ñ×ö™ï÷:JýðëÚïÿvÏœÿÞéèøŒú ý¤Íý䯙üͯõê/ì„o)0óðÐúâÏU¯Ñ/‚$ °=ïc0¬ß\0ïP-î2°ülPù¸ïqFo_pñ~0}ЕίÝ‘0ãz°ü–PáO¥âLÂߪðßô ™pþÈo.Zp _î Õð p ͰÓÛm>a® çð ݇ þQ·oS˜ÆNeðu® qgÐ qp!Äq !ÑGp•‰7Óï5ã1 ïÐí0ûN1ÜîïQEQ]QÙðAñÁi1Óms±¯#ÑYñ½Þ0ŸqѹP'‘5j¯±ÚRÑ¥±{Ñ×½¬·qÓ(€n}‚ªCÍáñå1éqí±ññõ1ùqý±ò÷‘]ÞæÉP«p.Z2ZvM!’!"#²cðc"Ò!'²"529,2#ߊ#—g"2Ñ ‘¬@à$O2%Qr%]²%Ea’%eò%g2&iò&m2'kr'q’'u²'ò'…Ò'‰2(‹r(2)‘r)²)W²&€$¥r*‚¨ò*±2¬ò&;commons-pool-1.6-src/src/site/resources/images/uml/invalidateObject.gif100644 0 0 33645 11701070263 23513 0ustar 0 0 GIF89aÉ~÷1!)9)1BB!LJ%R!R)J!J)J!J!!B!)J!)B!1J!1B)1J)1J)9J19RR!R)R1R!R!R!!R!)R!1R)R)R)!R))R)1R)9R1!R1BZ)Z!Z)ZZ!Z)Z1Z!Z!!Z!)Z!1Z!9Z)Z)!Z))k)g %g%k)c1k1cc!c)c1k1k9c!c!!c!)c!1s!s)k!s +ss1{ Œ){1s9{1{9ˆ1”1„5Ž;Z)1c)c)!c))c)1k!1s)s#1Z)9c!9c)9k!9s!9w!={!B„!BZ1)e.3^-Bo)Bk1BZ9Bgg9uuG{{Rˆ„VŒˆ^ŒŒcŒ”Z”Œc””Z””cœ1¥1œ9œRR””kœ”oœœkœœs¥œs¥¥k¥¥w¥­w­¥{­­{­­„µ­„µ­Œµµ{µµ„µµŒ½µŒ½½Œ½½”ƽ”ƽœÆÆŒÆÆ”ÎÆ”ÆÆœÎÆœÎΜÎÎ¥ÖÎ¥ÖÖ¥ÖÖ­ÞÖ­ÞÖµÿÖÞÿÖ÷ÞÞ­ÞÞµçÞµçÞ½ÿÞÎÿÞÞÿÞçÿÞïÿÞ÷ÿÞÿçç­ççµïçµçç½ïç½ïçÆÿçÎÿçÖÿçÞÞçççççÿççÿçïÿç÷ÿçÿïïµïï½÷ï½ïïÆ÷ïÆÿïÆïïÎ÷ïÎÿïÎïïÖ÷ïÖÿïÖÿïÞÿïçïïï÷ïïÿïï÷ï÷ÿï÷ÿïÿï÷½÷÷½ï÷Æ÷÷Æÿ÷Æï÷Î÷÷Îÿ÷Î÷÷Öÿ÷Ö÷÷Þÿ÷Þÿ÷çç÷ïï÷ïÿ÷ïç÷÷ï÷÷÷÷÷ÿ÷÷ï÷ÿ÷÷ÿÿ÷ÿïÿµïÿ½÷ÿ½ïÿÆ÷ÿÆÿÿÆïÿÎ÷ÿÎÿÿÎ÷ÿÖÿÿÖÿÿÞÿÿç÷ÿïÿÿïïÿ÷÷ÿ÷ÿÿ÷ïÿÿ÷ÿÿÿÿÿ,É~þõõS'->~çþC¨N]¾…ÿüýK÷/âÄŠþÔIÔQ]ÇŒ%òÛ·p¡¹ˆåôá{ø]¿Š0cÊœI³¦Í›8sê”éÏܾŸ=¥;÷SŸ¿£ý$~ÄÈñ"H‰O;†TÇOâ>ŒV¤¨”ëÖ¬þú%õ·oå9u¿ÂêãÇv§Û·ٲ݇T,º†æúé3Êï¿t}ûž ¸¢Fÿ¹´qF¥™BnÙ1åË“3KÞÜøoàƒý®Z.ìOuçÈš›&mÜ=hCùªnöÐÛ¨Ïên¨{wCÞ¹o#m6kÙùÆ5›v®óçСϭºO]¯i%ž N»;j฻þ÷þ~»¼yñ¹Óﯰá¸äç¦M+×ïçÉèøeÊxÔ_¹¾`·mçÈ]p¢·yä§ ƒâõ!ƒ VH!…fHÞ3I#Bçü‚„ *¬` &˜€Š&”/Æc 3Â8c8âH#Œ8à`Á%Œ1†2œAA6áÄ/ˆåçä“ÑITÎUç@c9¤˜Ã\6£`Ò¨#8‚9fŽf~™£Œiâ°co¾XÃHñ"&$Á$Y ]etûTÕ—G õ¢DG€Ã:Â騣bŠÉc dº9©rÖˆ# h–é)›žVª¦¨pÚÈi¦0Rꩪ9œjj£þÒ)œMÔàD:äAOœã¡/G4N3¹4Ó 3Ìðb,3Ëà’ 3Î.“ .Ðæ"m³Ôâ"-µ¹<-.ÔBËÌ-¸ðÒJ+¬4³ 3¬”ÑKCÆ+/NJ™3­ð 3ÝæÂK·ÑNkí´Õnk°ÀÙVël¶ÝJÛ0Áƒ;0ÃÛBël·ú:›lLú4è¼ÏùÓ—aIsF)¬ð²Š³ÿ«¬¿0ÿûï´ÙÖl1´G\°·Ö‚û­Ïƒ{°¶Ó½íÄâêÌíÂ;+<0Æ1G-3Ìýú[ŠÒ ä‹ ß s‹=Ýt³Í2ß|ö6hoƒMÚk£ÝöÚp§-÷ÜÈÔ³M=öã,þ8ÛØSÌ-9@òàƒ§ãOB 9pì2b#ƒÌ6ËݶÚnSn¹å“O>÷æœgζäh/³ ÚÝ,cÂ+±uá;5™˜_çŒA3·Œ.vظŸû6·Ç7å¾^ùðž¿yåÁ¯¼çÃß¼ñÃë.=ïgóîx7ÈH;Æ8$IÃB7õÔ³ö<ØÌsö<ïÈóNúë³ßþû𯯾úïϳ <òÈ£ 3=,S5õXF òáÖðOQ‡9òaumC}ðÀûèç¾øÅ‚|ßü&XÁ ZPƒëƒÇ<æxlãp`NOø¯æÄu~ÁÇ8T`6aÌ£ò˜Gþð—Ãùic~þü 1ؾ ñˆHa—¨DùÁ~ù{ÇÓ'kDQù«Æƒoà¢ãø4¦±‚eC|$Œ ùFh?6ºQ„$Lc ãèÆmÔÑ~%¬Æ;¶a†UôànØÀ… á'ò9¿¡Ê9Æ ­¾£„뻣ã(B8Nò’–¡Ù¸ÉKbÒ“íá»a‚w)²…‡¬ ŽÜbï@_ ç8ËJÒ²’tÄ%3éIOÒ’’ÀÄe/‡IÌbó–È”#<ÞÁwÈÃn«€C bða#‚ðhï§É6vÓ›Üd8»i7VC„ÅXnѵᢠaL¥<Ý"¡füÝþ á#—);Žœœ¨@ÅùÍor³ÿ$¨#yeÂc9˜†¿óºyâ„+qe=æA}Ê‘„×D¦BZБœÛ$¡BzÒ•šÔ %-(6•iÂZа£UÜ3JŽÄLã{÷sè,sKðÝÍ›×ðç<ê»Íã]êó™O;bƒ9,†¨d@õ©±¨Xmr¿ì#+`–(K˜CóÙÍ©mÔÆ¡šÔ·Öƒ­‡\íxW˜òåcc]ëջѕ¯õ8SáøHó±@a TÆ—ÄE6>È…ØJX>5ÖT¥"ì¬RŧÔÑ^Ã~vãëÝІP§Þou}þêSKk?Õnt¯† _]cûVÔªvµKem>kK¾â>5°¡í,í×\ø`šÓ8AU!©MÊŽÃÝdo k7¨¾µ|{eãp¥êwÔcLXFÝšÛ„¦Pö½üÙYÓ*6N¶uä­6V»ý¦vâ#ìiO‹GN–©O=mj¥J 7ÞUzýf?»ñÈÊ·¬ï Yb‚YÍÖW„5!k¿òÙ1¼&,j݈ÛÞm£IëQÜIÙ¢Vkƒ°wƒÛ¥önÁp-]í×àz8©/†ª\ˇ ‹ò Å5qØr‘ƒq4d:¨¯=*ÊëU‡ó°ÆSŬâz¼ª:¡þ—Ñf¼BÕûëÞ¶ÑŒ ¾” ŒlLÀ,…ölΟ­A×gªÀ¤õéÐGž× á¡ kÀøºïÐâ5Þq[ñFuËÐD2²÷ö….WQŠBVÀ £²±­=a¬ÁËXŠðAŽe5þ7B˜Ì›þõRÉœ>^cÓró<’½lÏ•bÎõiÏÕ*2ÕÌáCßÁLX1§˜Àà3˜a­Ãn|#+HZ²üáYn’Ëds,+k¤ªÖXæi-Ëg6ØÒT¹÷›‹8HÏgË8ø<ºÖÕ¡^†‡˜c‰mcçPÌö¦ÆM{ÍFǛ͗ôFþíÍfI¿OÅ#[O¨_x"ª«†³;ðâp%·¸u.Ë3ë}Ƶ#¯1q sÚç铸¼©áäžVÙ’Þô<‚qï*FòËè»8› õ`ëPÒÖ †ÉÑ7o)¾Zç÷ÅÆ3Íî„øêß@ÛF¯ÛT;Â{Ÿ¬‡5‚œâ‹[ãxg«™Z‹nô*xܹK@(„µ¬b 3>ìÍÀ7–ÀU r0ªˆfÛúÚ¼;¼#ýÔ¶^có¼v4¼Ã Uç3–Ëø“üR•˜‹õ'ÿðÓËÏ‘kµó’ýtc[iÒ$Üt%ËÞs “è„à²ñ'õ4ùè «Óñþ>mäkQÞß¿uCìÏX›°r þ%íîO¶Ž…ÒH«oéU›Îñº;†°6 Pn,›’µdkùcCv“=ºMwæxò„agÅgÈ€G•DwË…?fæfáÃ]õ›$WÀ ?gIÏ”mö ŠÅ]Ç6K5µ> FiÆ;:YTÁðuj1¡H½·Y"–I™Dbd\ã ‰  Oiûæt§ l6à ”@f¡P rcõÐ pŠP¡  ösZŠ@WFˆ`$$ ¡ð²ÀzÀg8Ä€h’f†>7WPµG€v\“æMptMå6¼n²·3w*µX»ÄIþz5Pö` öPÝðˆxE Ã7I–ÂAàÃŰ éVQ (VФ¹`wv]OÆF¦W P€7ÃÐ   6BÐl#W¨>àà ߰ˆ®Ø Ú`_8WØ>ÚÐ -hk‘Ô -/ a{õ1qhÅ8ŒGZÀ„Z£pTw œp £P Ä@ š@ P –°‚¨@ õP —p õ “ð ¢P¨€ úèx… …aœ@ ´ðœ´ ˜ –0 Á  ²€ ¡ð p öh>PU šP Ú@Žœ0‘ˆ Û€ • vC ² K% T>û¦ÊÔþXÝÀ €è+YÖFôF“Vc|Å `ö  ?Ù ?ù @© öŽk´Qô ·¸Tà nc“n0Ї„ÖhŒsMŽVlwôVÇÀˆÇ`‰a‰7aÓz…7wUàã–áó `”¿hà@–öpË–mk٠ܰŒøÓŒ/ˆ!òTjM‚e´eL”ÄMr% ™‹´@ ó œ ‡€ „° ¢à©@µP™¶@ © ú¸¤àŸ  –°š¶@®I ¼¨¶°ª ¢  wЩP¶›¨À œà¤š–p õ@ ´  {0´à¢€ ŸÐ£@ Š@ ŠþP ¨ÐŸ`  0 ²uZܤKËÔŒ4Ù!’eñVcêW¹u7Œ8 A‰Œà ö÷À ø“öà“‘ ~'BÝ€ c•¥8¨Y•C*V´aB‰7þé“þ‹XÞ0  ŸrYFÉ û7 û™0©Ÿ¹¡Àˆ‘h ,jú q4oðàŒ³‡8†9O}sözÂ4b¢äF5dös { [h ô8 ‰ ó0œÃ© ŠÀ v`¢p Ú€ –àš—€„€` ¨°Š„€ —`bº {P–`¦xð¨>_ ‡’ásš`Û` þ²a§` ñH õð Ÿ`zÕïNÖ$æPšÄ &]îÙXå$hwóŠÄ>.jö¹lÊè‹ð ÜÜà ` ÞÀˆûù ÷0ÞPôÐ ã'ìVšJJ9øQöS‹¯ˆW«øŠýÇ õ€ «jÊ Üp`Ôz!êˆ@@i Ô:­³zû ü÷¬ ”Œx@Göó>ê…Yƒü‘˜¼'¡øÃKyøI ÖTõ8 #¤ ’p ×ð Ĺ›¢Ð ´0 – Ú` Û` ’P¢À §À – /& “7¨à£` ÚÀŽö0§”0 ou Ÿ° Ö0 •pþ ¨Ð !°Ý` óp±Ë þj ž° Ÿ ‡z7@§`|66I–T>ýä\Óô YæhK…´+çcრ´‰«¸—üé“Öj P­êš ûy¶P÷` µHB¼Jeˆó«‡¡laö:GÁ¥Ce¦‚õÀci w›—àŸÕj 0­-ê¡ÜÚ·Üp¸ãz¸ª¢õ` ³È ¯ ¹Ü  `Æp‹j&J>:ƒîejã0¬¹ôFF»E•§ÀwóÐ…þ †p s* „` ¨y¨¢ “€.{ŽÐ; Û@Ž`¶P† “Ðó w` †`da{à‡ ²þk } {@ §P Û† ð½9 {P } Ó{ „P  ±š`d×pltŒ“ ‚0Y:9@@ëÖ –Ú©šÔ¬rdšÄˆ&Ÿ×zËˆŽ« ÜÀ­B ”€”}‹«wÅV½¤l 2ÁZ¯ù´\¹(Wü'’á•ðLdI‚ô ¬p¸•û­@Iªü——ÌZ­(ªý”ðx#«˪ûÉ®è㌣ö:|Hm±qÁÁh˃¥ËFö§Ås¿U8 Ú…ŒyuXyµ—Qœm{ù@ĈkcæÅgûYÜy@&cºUš  R\´ùšC"¶ J›¿°Ýà´ºrwËWþ›ö@ÛÀµU¨A‰ äꊹÝ Øˆ PÙ@>ñÖ\ šÁ†ä¶ç·,·ùUü·E;Œoù—ª– ·ÿ«è¡ªWÀˆÕJ‹«˜@ú7 ¹h«I=ªL2(“å¹Dº:º¤Kº¦wIççMzu`ædýe7±dGV‹‰fwó†„ežÐ`QécÇfc?FX ^PÌ]“”ͲP´ÚÀÄnd‡æQê†eü+“½l?GVžRåb²5Œö°—µ¬?È—¸, †¶Í徊ɴÁÃêÁufhv ؼ––¶T!¨ÃáìmE½–úw¡y)á|µ™þ—¸ü’mõËCìElH#ƒÄ°Ѩ˜¯8=Bá|~YÑÿúlwEfÿ Uj·T cSü6 &ôiÍÖy(wZ¡ª`AÖT ÖWïÌW²…`ïŒr9mBIû\xÜ´ñÖÇÿ §%A·åÓtu[wC‹/¦W v~FǬ¶íBnËœL¬Ö¬CÈõig{ÆKõ¡Þe7rUXœÖ`ýĵHÆg¤`t¥¨á#·Ž´¹ÂœpŸëÆ<\‡˜Ì9‡¶kSwmɇÔN6Δ6WpnCf„O¥bçGïìÚK…„)–¤ÞÚ×Î$Äø:o¥Sù;Ö÷,Bþ+Xe„ãa[ÛˆælQþ¼b¥Ç!•¶ Óyí$·–ÇFˆ|°Õi#tÎmä] &ÅÊFWǸbŸ&.ÙVõdmÉÒš+jœKsc%Y4™ÕÁ7­Û¡MWM…fnÛóÍTã—Øn”Û©]JnKõ}žÄCÆ]ZÄTÎÚ²-X±ÍK™”Cà 80(L»Çe}?ž:iÝK5vR8ÝÒ•Œ×ÛÍ:šÜ×üâ)I@ ãIªKMÜGJº ˆÙ‰1Ìy¦ß²!ºŸÚøÚãyäB>º@^åŽyˆVŽåSžåÝøIÉ|]þÄ UæSzl©~R;®‡CÏ r Ù]ã„#2‰!¬Þ ã¶$àQήþð,LR¾ç~ž¯l5iBœßÚ}@CÚßJ|¯ ­çPÎæ®å[>é“®åVþçþIj‡¿&NÖ§â•€¾tå¦.·+7è–¼¶r>/{ã–½Û’ÎÄ\éT^éW÷ÌG®ÙÅÌäŽâA~ê?Nì™Né¶þäĤì^ÚqÔÒþtÇûÛ¿*Žç±ÞIRnë:ùgi„ÝDÑêlvÞÉØõICnw·ŽëÄ>ëT~‡$ô®,„¦6¤ôjÓl쥛ìé®ï¸~éGzïø ðÃåÂ=Ïc¾¿|,êß”æ,Γ<^SpÔÒl¶ê¥îrãw^PÅžÓ“)åã!ÖñÝTIA%þnæÌœ‹äû½ÙK~ÌMŽïÉìç±îè_óÆDó›nóïåÐn?ÒnÏfžÏ:NNÉŒî¾P¸kv—¶Mðí/ÝMÛ{Žæ#ôÉ5¿Jº“–eP¶îþË¿¯òžäR‘Äÿ½ÄÞã}®“–-ìN¾ö÷5¿óuÿI"~©ÅzœðIKІ`¡Y*ŽÎ÷üI4Ï9£N ê±Å{lçèhµÁ˜["ûl¸O"ß© ‹ãv ö¶áõäí{Ðsxð%DX»íUÐo×3wÐW9þ§Ì¬#ÇÔê夹²[eiÝ;\Zm]öŸ\5_n½hb~…z ^××ÕKþ[õ]=ƼS~®fîGÉ¥HÅÑ’ôÍ}}¼W’|%×xõVÜqà‡'Xxã‹/–xrA¬I‚WÌåWsPÖs1ï½7üï‹õ[äá Ö–ðÇå&´Ô©òn-…R”$í;wºDV—³rà“ªúùëþ¿pÚKæ§;ž)>ÅÁ]ÏR7Hñ*&L ݳÁ9Mct‚ÕIø×š„g30h®í.PẟœJ¯1íãkÿp†þlxC‚ý«ŽÃšIÜd–#‘ˆEt–•Ø<æ™0gð‰]åÃ^1H»“Û4v &,†Q†b ÏtwÂN h#¹!ÇøÆ,Æ‘Œs|#˜®çžÊŽtÔcc"@2§kuë ü iCu  XpRa D•Œ(g­jÉÿU5'ºDEV´b˜I“4ˆcž|ÞîÆÒ¯Ia­|6ÜŸ!ÑŸ­QIL®d%[yÈî/†ÌQt½‡Iç¹zÔƒŽ GýZEßGБnt°“Êè_KÔ×Õr¯¯—ãæå(z„Ã.öªû#jùšåÙ}Dc-­p‘ÎÑ2²äT‘ªgL2>ʾš‰º]0K«xŽë´jJî‹»ˆ’è"\©]¹ªŠMŽ{Õ)¨(Ú9›„þNw«ïCáp{9 ൬—8úÌ£®žµÝèñ½d€O¸–ГŽtë|ö;çºéKoõSJ=P=؉.}lé^=Å'¤|ØhúÇ‘ƒW¤^¸”/SÉ_ü‰|eüqð™ê˜&˜Ö·îß¿`(V~×Òà~ã>Üy>™ ©³r=ÇÉ(+¢i«±2é1I´ikr£¶tK@ ñi¶±  „²%;2 T6D›§¨©Lã@ó—f«À‘ÿZ"P‚%+sµx†lÂ++8–‹ßqÁö¬{“3<‘)–¸¿ük§âŠ¿VC-­1}Ðr@/ËþÀ=©-´ „ê±Jã!Ó›Œä@Þû1g8Cs Àó¶=Û·€Û7#@¬hã3ë±$€Íë60'/Ì«h󗫉1s‰°3¬±pƒ1 B´ØyD’Ú<‚ó‘ <â~IÂu*0—H¶%ZµÄû«9õK 3‰?G$<“ 7RB!ˆJ ?é‡íÂÂ3ë•*\—ô"¢Yk—X,¢bù)¼5Öj¼7q0O’'>»–NŸyª@bl<¹ ÿRÁ›‚œ¨“…«š€FR92Kžr£@ýÓÃe<.‹+Ç jÆÔ5ÅkžL5gXEÇÅÜ)-;Æ9³?)\þü”ñ“ú %ü™N""ß5ª9“îá$A1‰t"Ú@b4°R\ÈU¢AOB7!Ú@:„±{z-A’èÆÛHÒªË2„¼”¨0šrIáÉÄÆ l tKÀWÃ=E¬¼›“Qé¦ãµ€$cc£š‹3Î3¤‰Ê]›J·™œª¼Åò²oò…'HܨD}X³Ë)¾jë(ïKBOÂÇwtœAä· ÊÃ=Ü7›¶L D ”G~£K<ÁukÃ<ôÁyÜK7iK:µt‰ˆŒBY‹NἤDs!¶1,±˼LÌÌLÍÜLÎìLÏüLÐ MщÚÀ(pƒ$ð…þÊçrÆ—rH“Ô¼‘i8Ñâþ‹p³ih*晩¯÷•*€¦`f¤ñó_»5µÂ\Z‰‡NZoh(œhˆ¾h‰_ÑZóHÝé9°«“gPÛM,è€îäkªa”î°Ff+Sò·ÉJb®iOÆé›~¨œæéÆÊøØM‹T_û«›¾k­¡,æDW+–né•+(Ò"8† 8ª(8¬DJ®Æ( ȯÞê°Þ±±þ¾+›é6‹¦Rj©f ÉüŒê·þ²PËAõ×$«¬ôê®¶é±HH5벎²Á6lîD‘XJ¸¤Ò(À›`€Vp9Êq¡ÿ«ë{骖“ñ…B+µÊ-þÑž¦Ñ.mÒ>mÓNmÔ^í-‹®1_ ’óp§¼B`žrxÛlÌHªî&aÏÞ0eRmãfmä>nåNnæî2 ¡2Æv¡úí°¢ë ÆØ4¿Þ¾ÔR¾Á’ô_ÞîÇ´êò“„³lÎv5AO.èJD ËéVñæn˜Öáÿ%­Y ëÓéýöéþÖoþpÿ6 ëáÆÞcë¦ãâ©B±ä¢ùÆÅc6eùîešþ¿Àöë¸Ñp²ÆpÄÎpÀÞ®µ¸AdžðÉì;˜[êÈ£±¨Ô_QÇfóÆï’ ñãp°>ì·q³ l’Âñ6²L9ù…$X7ߣ‘ꥬþØ'ÃÛÇÂî†RŽ ÝÊ“Žùµ;‹(ÿs"»›”3“MÑ”dùµ0g‹R´/ç”8£3.tœ‚—Ú‘Më<;s ºYNa#s臅%‰RiñÒ0(.hsq_ a´í'×®÷æáë¹áMœkž_Ë+ˆ³|4…9‰hÈ?eqH,Žát ’´¼út“õ{uÛô‘Tubu«)Ÿ |áXã9”Nq°RñQ66qUt›nt—f‹‚Ûs_ Qº+±²kq0ôí¡ß[g|kgÖ™;LÄ—}îÙJ)âým/¸êö+Çv1w+ë‡rþ—îkA÷}Pwp’vߟo'Þxg«®÷1)Kâe8iHƒŠ’}†00qš$ks‘ƒ5)®Wö¬9è¬6Fa£R9 )>¦Ó¥‘væ} ^6 KHçŸnÔ ?Q˜±²s¥iÆlAysPùⳡ–'‰—߇˜Ï9º£ù´¨9“Çy•?%ž— •)T Û¡Å%AI”°\¦i¨éÆc:6¶°I“A¯ÇxztgŒ]sI ðgnf?¾5¡ÁSܧ¶Åd‘íi?\tHý™ûáU»'ÚúÉ{Ε§Ã•{Í]?¼û'|s¹´ð…Wm£6Q”iè»®ksQJZþÇ4{ úmFò•ó¡óؘƒ_è…øô>˜ ˉ† y™y}6zÝXýÚ‹Ê‘’ÀýÚ—}ÞþØá¿’—™ýÚW~r~ß'þÞýã‰ä×}æ÷}ç# ~` HÝʤ_û&F¯`c“Úr)¡:ZЖ—¦ð:‡iHƒ_˜,ÏšÕ<Žˆiꤩ›æ«à@u¥M›FP 4†¾Røï\C‡ B|±àÁ >(ñã´Šê.f$8°¡É‚(C&©±£@”*Y’Ü3bÆœ¦ÚüâøËÕ«_¾~™Z#påÊR§R­jõ*Ö¬Z·rÕjîŸþº ùMUçêÙ®jײmëö-\¸Q¬äõ¢?†;fÀò$Às.P|ÈÙ¡½>tЃ Ç]@FxxƒÂ^hv`6§®‚Ìÿ̹Èà!‡ÃŠ;&Y²4ʧ^μ¹óçÐ+I›F­ZÝâÆ#/”m¹fà·Õy-š·™-6tp8- 4(6ìHÒ&‰ÝÓ(¼÷<úôa‚E;5múøòçÓg{6jÁøÿùSwÎÿ4<\W…IY•T*˜`{ Ø Xæ•G‚.h¡…FH¡Eeµ‡a…B%¢„2è!~•÷ OÉôž?1ÂWò…õË]æI5þc=úøã[sí÷]`MSÁ4®üòKhøgÎYQòW•”Âquþþ$X9šB"OWˆ„"ïØ sŒËÿùÎñìeÑ3¿˜@¨TÆUêI!X‰.ºÆÊù¼¤ùE’`5Bä"žQˆÿA\epBqTÈ3 òŸo ,çp‰2-’L`¶‡ Ë|¦1—©Žd:Ó"Ãt&4»¹’iþ‘™× ç1·MfâÊ?èÔ&4¢ò…¸Œºóä2Mñ,bh–þì‘C|÷;Gþ“–y@ž 5º(OYJ`nÉ#Ä9HÿF²‰pd$Kë_C0 Qÿ`D)ÓŠAúwQ…„D"&L¬óQ_„”¥j$©âhŠÒŠ®4£ÖÙ(Ls™ ¤¥Oyþ&á¦ñÌãQ(xÆùVЩºWåÐ9¢Ú3ª²%NrH,Ø@ºHãpAÒ 9lGŒ@ ”úŒ:T 9½¨ƒ8P^À  Ij<à»b3Ó¸«:9ìà•þA\ý3׺f¯z=l_ÿêÀ¶…Ý+^ Æ:ö=Í9&kWËî5³€í€`¥AXÃ"¶:£Ý€c¥Áƒ'08Qªâ ·ESqµ¸n¡šÆ˜@ãªe Hƒ` Œ^dNÊ_{‚Ãöð#_!Ë]‚©ÝrV×3àí]vÌî~W½éÅx™c.Íóyáå®w›u_Õ}ˆ¼ÿeþyòŠøt@Á F Ø` gC¤ìÈÈ\ãúÇýÐØÖ8ᬨÎ~¸|‚ Ê ¿šEYÔÁÒÉí3Œ‘Çv%à½oé8˹4–(¥‹Tœ¡‹eìÓ.xÖÓônL$ Ÿ˜ÇÆó±÷dyÆéC²_ÌTa¦q)I¡i’R‚£î(ª>3…¤ÁäjiÍ+KB„¹u0àÍhQ®ìÞE/uILx6•Å”, ¿çÏ„¡ ËDh3—g˜O³…V!7Sº<ÑhÓ2Eh®Î Iò‚Y*®E°¹–‹TTefjku.Õ¥6 ««r'>Oó?¾è@žþùs'©’ÒhVˆ¤5¹É×Ì+Kp$PªðW‚Sµ×¢½À«ÕìÕÒÎç°B5k{.Ö™Úu„ô•#un(2v¥§‘¨dzÛ}vó<ÕàèO”Ù•åVDºió»ÛûÆv¶Wý9±üÐÂ&”0"c¢»áoûâIŸ±5>£‘êxÀ£«kç6ç»ß@"ÝÂ<¾–x{PH '¯(mÚá®+È,R߀µ|ªL$®¨ýƒçÐÖöÀí£Dÿ[è'+ºÔ •#‹,oÈqR¸Wn3—ÿ³t˜ÆÓ¸g抗ÞÆØ 9ƒ.YpÉ׫­Rs´÷ùK5WÛaþ¸#žë¯HBËÜÅqªOµ …ëùYXlpªÏS,Ìù ]Ä(xµ;ìí{”ß÷JmÛñ+ÕÁŽý}œ—*wØÞù¾Jf­oëTW•VË,úµ™>TWäðê7|4+iíô†×åZ{W!ŒB|ýîÑíw…´ ‚5³¼?Qo4ÀŸ÷¡bƒ*´(Qž6c*]Ê´éC $ˆJUªÕªX¯jÍÊu«×®TÆýJ¬W*ª]˶ä¨b§Ê•*wn]»wãâ½K—o^½ î[·/Ú¶ˆ+Æ(À¬ã²K¦KyjäË] \¹¸³gÄoç%,Úri¿§÷N5`¹rjÓ¯©øL»¶b¸ XÃÞÍ›0iß…Q÷žâÀƒ«&|xgÛУ›„K:,뾌ÿŽ@÷\ãÇaþë>N÷ºøâ„½[Ǿ6Õ¥6—N¿¾HÜ€é'_Ü´ùß­ÕE^yañ7–{á™æÚ]º]£6Ÿ}VxuÂ@v}‘§¡vQ‘^v JÅxÇ}hœ‰ ¢‡bxà bŒVí‡ÀUÊMháŽ<&„_uýmX ^0N5¢\ žˆ¤‘K2Ibˆ yã‘#&d„–éØã–[b¨” >È¢vBX\ŒPJɤ†Q‘ˆf’2ÎXÞ‹–mhà—Zr©g…?b¹_›EBÉ" MBX¦˜U"¨Ÿ~T iå‘&öÇ_yîi©t^î…#šcVù(o6º™(2©f§®xf‰î}‰@¥þ—ÆJ[Ÿ¥±× V˵•z8²`{¼á`wXÂ*ë±·ùw`nÖÛž¯}ݱv©‡ë®Àž—ƒÓ&g,²à®Ekµséö«kÖF‰•¹Ë¦GÕ¹ÙÊl»óJe^T߆«ïRÞ[k°É¹­°ÍÚ»XÌl|9îë0bø)koy“"¼¬‘*G¦h×ÌU€²»Û‡mΕïÃ(O72Æ,kŠ#Áƒ®úé\Ý©Êñ™¦•úeÉúYIÕÉ)ýQÄî—âÅ7Ê•.’vŠèè‘~y÷2ÎukÞ]·q]@ íuF^Žguˆ%j7£Í*ŽMu©cŽYUŒtžñ‰-Ú [×_çMþÑdol6ŒVÿM6Îe?ó ÇÜòÚ7>x«xë-ùBý2Í8x¬™=·à„-8ɧ­ö“=cÞùéT'-Wä“·nPÄ1“檖[.ûàOÖ xÎê~àŠ‚¹ëÄcäe̤ëÜ"ª2JcóU;¯*§˜·Xt’·'_ñÜï]—ÔÙ l÷ÂÉñ¶ôâ“.(°º/{LàÏÝÇÏP¦"£ö$®À·ÃõºÝ+qõÌ_:6/øÉï€Áø®¢iMK8 ³¶”í ªN]c1˜o,Ö!ðk™Ò‹û‚Ã+]^4û•…%ek8{Õg(ˆÝë‚3! £”‘½ï…þ¢ e¬Õò] _4<àD~r“&Îĉ€bobØ$Ѝ ·øÄ.FñŠ:¢Æ)z‘Š[l¢»Hç$ñ9ÀJ2!7Âñ޵™‰3›¥ì€LKAÐÒÇÌf6 ¤"’È‹ÐD&›ùZÞ2FŽd‘˜¤œD )’Ãx0Ž™ å ‚H:$Š¡L%B,Y‘ùPr:›ádJX©J%Êr®üÈ+ òÉZúÒ ¹%.SÒ’ôò—È”I)yÙÆäé0´Lf2ÙLa­’¼´¦4· L討 Ùå)±ÉÍr.•ѦGæƒNsºó$§ì#8A"Ïc¾³–ÍþÉ¢=B“Bê(š÷„#@K€€:=¨B9òœ„.ôŽQç,²Ï‡"0"e¨LœcÑmJ”%ÏÉhG»çЗ”t¤(]eJUyÒ‰vs¥Œègd*H˜¾Q¤T©MgˆSSîô§ÙcK*´¡†Ä¨DõR]²Ô¤^ª­ IdÙT§>¤¡MAIA›YU…XRœ^5 +»ªÓ†D$’Èú#YÉ9NxštoqY¹Öff„&€Qöz¾úµ¯<ÉIQþJX „Q(eìg]ñª×£V°¬> ;Y2Jö²•ÝkN¦!Ìxv2 ŒÒÆÃÐ>æ¾ÚßGAI´¯˜öŸ-þ‹]d›ÚØ‚v¶K;Ex°îL5ÀuÖ`|+@âw¸  ºz:HÞöö_Å’t{ ¤ýW¸ÓÅÒt ÀÉÆpÇ´¶ ¯iýE/ñbæVê[˜n]"€€Uå†êuí»Àû1ÕUf+á£/fJÄkÍ' 3n`ªûÜÔ¸…þ²¯}cSÜ¥Ë+àKÀjã8€ÕTL4Õµ µ|`‚MP9Blp‡…[/ g·šBŽoCg±:Ö#ŒõÜ—tf./kÄç%Æ<þm\–w—³˜Æ ‘ùÒ]±, E «Ìãõ8sMovÔb~ÏÅeR?ܵ›­lÂwýþl¨w´‚ÕîË¡»¯`*È¢N9­ÈV² ød×eàЙjnr­c3þ K/\³ÕÚ7ZÀ|tg"jK û­è~GtÐýäl43Æ=•‘Sêð—ªÖHÒá‡0}êÜÞËÊ»u|k—Ÿ&óïp×ë›§vª¿mLEƒãrÕ„çkÀ{Ø2ëõܘ¶»÷ÆÓŽN™íëT9Ngþãšd&é`¿IØ}K¶ìÚ¶lHëJÐF43ðŒ–;vÃÝËŽ^ðšvºu—ZÛîÛ ,}íÆáð@жHcrØ· éÞØë\ïò]oz·zÞk÷¨åÖ9‰s®Ö;N³ªý"‹—êv~ëòæþúýîÓÕßÉôå@Þoö™Œ½Ö}Ź]8.ï:qÅn9âàó‰oÈM,¯¸‘aƒn]1Ð75¯=uô›i’öÝ©O¼HcΟÅÞJ£;éÊÞÆuÖc´o u ÷6e6Æo<'}É…ê)%X¯1|lwÇ]—ÁôxCOyP†ÞÊík¨›ðl·®ŽçNc·1»ïÀ†øàÝ(‘¾×…Óµã>"{=OÙ žJѵ·¬:y…+,a„I¦ñ÷€oÊ=+ £Wvµ§6K0w®œ쮩ùP…‘ŽùÎHc2PÀ 2Ý_¾I3˜ÄȲ…·F`;O€Ùu~pù(zʤÅÑ—~ø«vaéQ,‰_±ú‡5Ñ“àÏ¿ü½>û5¸þ§‰×)â]èãþDTz¦^÷÷µ‚bÉgc¹²€àç^¸Õ€ì,¦€¨æ²xÞÔh¸HÆ[SCjæØ#x#¬1ò+ÇukB–}¤ç\æWéu].ˆ]{!wbõ}Gƒ-X`Iv{Èça£‚=HƒwÑ]xeY:QEhäLhOØ„;…OFQH…?q…_¤„YØ…NXQØDì•„Z¸„^xX¨…6qE\4…LôDR„†‘•†CQ›VNy(+uE}(]õ‡ ;commons-pool-1.6-src/src/site/resources/images/uml/ObjectPool.gif100644 0 0 6626 11701070263 22263 0ustar 0 0 GIF89a·W÷”)”1œ)œ1œ9ÿÿÆÿÿÎÿÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,·WþH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ%B`ÊŒIs¦Íš8oêÌÉs§Ïž@ê,f.“*]Ê´éH D*µ*Õ«V³bݪµ+×­¾zû5lX¤NÓª]Ëv-³p§Æ•Wê\»uçÒ…‹—ï]¿çÍ+mÛÈ+î(À.ÙÇb#C&{5ìdÉ`ñ^̹³çÏßö¬×ìèÒ–Q“\õ´^×¥G- º¶íÛN¡¦6Mútßß½ ßÞȇ¼·óçÐAŠn5µTãr]/¿ŽÝºÙãþ˶{<»÷½ÕÅÏÞ<ºû÷ðêöÍû8ø÷e›ÇË¿|õï{Y&xüí¦Ÿcö%§ÕíÅçàƒ¾µžwöáuŸqþ—awᕇ†Üu‡áTöaXÞˆUhÀˆ$⇞y B(㌷A5Úh¬È—-º¨c_¶x]qù!‘ã—‡êHàv1Ò(唉IHŸe ’HŠJFe¢.zI¤—_†©ãw\šfâ…gþeW”TÆ)'Sºh`–?I&y=šäf‚™£˜„Z\ .˜œs6ê(JÓ G׊ØmYé‘á}h\ˆcžIiˆb)×—œjêŸvÈÀ裬¶êÑ|þÁmçÝžg`ª¬Ýúb¦u¥g몮+,EÚyceãźޱúé:¡­«åJÛ°ÔVk‘ƒ%gÞ­µB«ž›2›ìW.k°Ö¦«nVFÛl¹Ý8}áæºÚ±~½¹î¾üTg¹ Z'/¥Ï~[+¹¼ñÚì¥âË^¿ï©¶/®Wfq†’˜Ÿ®£ÉaéuW1ÅÕ¡ñÉqš-®Ù‰8¨ÈÛÒ‹qkØ1l,Ƴ‘<ï¹(÷,l±ƒ|©Ë"³Èb‡5é2™^è¡»ùžåóÔ¬b+©ÌL0‡Iw sÑ/—¸u‰87[0k&S­¶{í®<«šL’}$ÎkvLfȤvôþݼêloÚkŽÛ¿P›ç2w˜Îýõ}‰s˜éÞ›î}o¶Ž.øåŸM rÀLǽ)–N­1Ù8nZ*Ì#ƒ¬/æ¬Ã§²¤ÛÚi ŒKË—Ù°(ïÕ©ZÞúïm]xìÝ2ílß ¶q»]™ïÀGŸ›î+/x×»Ç;;i¦­Å|ªÕó,ýø™Ÿþ~¸gϼÀÏV6)X°× =ùô¯D¸Û±«ŸlûÖÛúßúà‹ßnæW¿šD2 Ž“™469J8A"°´ $(A zð‚ ´àCh£ Eƒ 4  WÈÂk&! DDèÂâ&'h)Hd(D'þ6 âZD#¾$F„HŒj"Ä&*Ň IâA|(Eù(ŠNÌ¢J¢TEƒ ¥‹Á¢µHÆ”4Œ1Œˆ5–ñ!i €Ìq! ª#÷(’5Þ‰þ²_ ùHȦñ)ƒÜ¢ ÉHŒÀä€D$AÜx´4çda{¨H’3¶ä‘^¤d&G©Lþð ¦,%)WEQš•ˆI%+ÕæÊWñ0 œ¥.;©îò—•”%0‡©a6 ÄLf°j©Lµ3#Ïlf!‘é™hÆÑšÒ"3?ƒÍlÚ¦›Þ çÁÉ/rŠóœOÙ&:gdNƬSœít§”âùN6ºŽJ¹þ¬§>÷™Å˜ð󟜡gô¨ Ð= T-æA;™Ð.0A‰¨P$Ú“^f¢Í(Fcr”ˆXÔ' )GÑ Šô¤E©JSJA›È‡Š ) pÑ:„1ÍéJEèO;º 3— êûrÆ- õ2CeÐ }å•TG¨f{›P:ÔqQªî“—:ÓØ¶«–ÅªŠ’ªW±ÚT÷EE‡>uìd@Þ™K5m¥ÿ(7À&,6sÅŸ±v—WÕ¬5®}`‡W²¥ÊŽ­ƒ%Œ_¡%WÄFë°Ô›Êf¬&V²Žu}ﳬf›ËÁ ¬ÜOe3#ÚÉt«™½¬e‰'YÖö²»"þí]7»YøY­ @òËÛÄú5}Í]oÊT¥zT¯áãpÛÇ\ß®U°ûíb!˜î]ųÔm,¸ˆ:/î-w¹ÏunVû2YêœO9Ô™…x¤-µ.ï­ko,G€§ºUSè•+¥xô^Ø4/¿KzZêàÛ^ÏÍ4ž]ÀÞ`ç}N¿&°Ã`6Ü"q{ »”r‰{WLÉkM| 0k>: #k6v3vß"} gcQV?Æ2_áªx(6Õ‰rTý{\+p5¶—­¦qv ;í«5Ú@hÊYzdS©ý>ØmˆƒMy‡ú¹6Y×Æßš-•ãö!ë¯VCÛ1þVVæÓ79"¢J ¶™Åîʬ%Þ‹ÊÇÉ-; ž”é0e3…õ‡qR1rZ#"ÄaÖ:N™E†0ÆÞ Æ”¶ï¥k%FÊZÅÄy»X™’V©Q;ÍÊ;ÖP‹­¬cÅ©:͇«Õ›õ£aSÅxM]su©•öä2›TM{µÓ¢ âý‚Êc%Ñ®;g)5óGÑ?,jˆQmk¤íÍk¢6~mݹVÎT’^ZT·Lbº,mÙŸ#õ¯iÜå\Ÿ[Í”>0ºá­ê?¯‡¸â’³ÓŒl5»ÚÑêîõ»©"î:/{lt“o7p„÷Ú–Õ¶¼%Š_»Ícëó‘e€ËMr]ÃWyþ}¹’óšá ~°ä@Gä¥m<åü r¯þò« ßËyØ¢œð[§;Õʦ3Ì{žá™×ÜÕ:&Ë­}p'n*WYó–íó§_¬q§÷ºO57TgùÚ%ç\§¹…í®ó-ìëM®yNóy×GÀ*šÖJŽòz"Â;ÔÑw-iµÓÛpΖtÅ?Íc´ÏlÎ,w¹ä*.â,3ÞÝJ·LÔSçï¦Ë å~¯ø·×b'ÎãHÇónÆžó_{»ò['2«™^xÓëšhƒÚ¯Ùoì²ÝjÖÄi1·-¾ø€Û~èÍ&ì;l o¨êÕ–½ãºÍ|›`òÌŠ1‚|oëŸ÷Ø~'>í9þoVw[kC%w;̲ÝFí¿Q}{h-­éæŠöîÉ{ô1Lþ¨þ/{Å­1€+­~¿ßÆ“‚k†¸gx3Ã]|¥^q:Y52þõ6œ#5¡±9}•^põ[ˆ‡\†WÅæA~ÚÕ\AˆÎóVYf>Ó5\£u¹X*8<»…g Yãç.«mé÷‚@„Ê“]BX„ç]h„J¸„L¸X?Ø„/È+fVP¸„OX…F؃&aÖ_]ˆ^{¶ƒ©ã…¦…"È…bH†h¸†cø…úÇWj؆㇄l‡v5iè†u¨bÔ.jåX¥Wðâ‚Xˆxs…119ˆ€øXŽ(^¨>øX'h–SÂõ‡„ض3‰‚H‰Ê3Y&4S&U¤8RuŠ¥hS84RªøŠ‹9AÔQ•A8uB³¨‹B!‹¬Ø‹¼hŠ UA«ˆŠ¿¾øAW5ÕªèŒÁR”‹»XÇèɸP µÜØl;commons-pool-1.6-src/src/site/resources/images/uml/returnObject.gif100644 0 0 44374 11701070263 22713 0ustar 0 0 GIF89a¬Î÷1!9!9)9!)9)1911B!B!B)B!B!)B!1B)B)B)1JJ!JJJ!J)JJRO J!RR!RN!RR!J!!R!!J)J)R)J)!J1R)!J)J!)J))R)R)R!)R))J!1J)1R1R!1R)1J)9J19R!9Z!c!c)k%Z)c)c1ZcZ!c!Z)c)Z1c1c!k)s%s)~)k!mk)k1k1k9s1s1„1{1y4„9k)Z!Z)c!Z!!c!!k!!Z!)Z!1Z!9c!)c!1h!1k!9s!1w!=R)9Z)!Z))Z)1c)h))Z)9m);`1-Z5Bg1Bs)Bc9Bpm?~xO„„RŒ)Œ1”1Œ1–6 9Œ9™?„„ZŒ„ZŒŒZŒŒc”Œc””c””kœ”kœœcœœkœœs¥¥s­¥s¥¥{­¥{­­{­­„µ­„µµ„µµŒ½µŒ½½Œ½½”ƽ”ÆÆ”ÆÆœÎÆœÎΜÎÎ¥ÖÎ¥ÿÎÖÿÎïÖÖ¥ÖÖ­ÞÖ­ÿÖÖÿÖÞÿÖ÷ÿÖÿÞÞ­çÞ­ÞÞµçÞµÿÞÎÿÞÖÿÞÞÿÞçÿÞïÿÞ÷ÿÞÿççµçç½ïç½ÿçÆÿçÎÿçÖÿçÞÿçç÷çïÿçïÿç÷ÿçÿïïµïï½÷ï½ïïÆ÷ïÆÿïÆïïÎ÷ïÎÿïÎÿïÖÿïÞÿïçïïïÿïï÷ï÷ÿï÷ÿïÿ÷÷½ï÷Æ÷÷Æÿ÷Æ÷÷Îÿ÷Î÷÷Öÿ÷Ö÷÷Þÿ÷Þ÷÷çÿ÷çï÷ïÿ÷ïç÷÷ï÷÷÷÷÷ÿ÷÷÷÷ÿÿ÷ÿïÿ½÷ÿ½ÿÿ½ïÿÆ÷ÿÆÿÿÆïÿÎ÷ÿÎÿÿÎ÷ÿÖÿÿÖÿÿÞÿÿçïÿïÿÿïïÿ÷÷ÿ÷ÿÿ÷ïÿÿ÷ÿÿÿÿÿ,¬ÎþÕ©û7Pà¿þüñ;háA‡F|H¢Ä„ ÿñó7QGCŠI²¤É“1~\ÈoŸ¿}1VœH¢Í™7%æ´È³fA‡?q¢J”¤ÂY¢ã·P¢N¡O£öÜYêT«U¥f½ª•êÎ@+*Ôyñå¿}B‹Ur!DŽnÕÊ{2ãJh?‚¥Ë·¯É§ ý N¹1äÒ¸ƒ+^ÌølI…L÷¾Ü-ÓË01_n¹93SÏœ™jÜüC–ˆ«FÈš¥D·¯5ËþܹöìдoƒÞyòÙ£mQ¯ö›´mÆÑ¼uÛÎÍ·óäÍ¡?_>]¹õèG·Eè’òY·[þzÍÒxùóÛϳ¾¹ühÑÇÃ}ÈìLôøÓë·¬?ÿBþþ‡Ö€Ž‰6 [ñ•ÚA…Ùàƒæõ'axö·^…êù×^{ ‘W¡e®¡6YBhQ^[]aåN—i¤Kf¹TX‚-ø“@¥¨#WeWA©âquçO?HQéDö}9“}÷¥$B{!©b&¦˜½iSPr†5æœwæXUB\ª‰R’§$˜„âDg¡q¦¢1jg‰Þ)id…\ýôé71VS%š¦Ÿ}™&—Jr©Y¤2Ö§þh¶úg eÊjë­hž‰Ž ©c ŽÀ‹#:Ã+±Ç«²Ë ûkŽÀâÚ—kÿô›Ìf«¬¶ÉvÛ¬·Ü~+n¸8쳑JKQ‰¡.‹í¶ð‚ï¸ó†ko½ø~K,²û&{¯·å û5ÏsK5ÃLSM5ÄTcMà [SL1S¸pÃç¸ç®ûî»Ç·ï¿ë®FjÄ w.Ì¡‚-0É 4ÞÔã7Ï€ 4ÏL¯ýöÜwï½÷Ò× 8Ï\Ž7ö€ó‹ üÃúZqyôO5kÔBŽ8Јsþ÷ü÷ïÿÿôÞ3œ!ŽZ„á¨Ï‚p5-makøÅþHÁ Zð‚äF÷4ˆÁêeozå³Ç/â0}|CÐp†6Þ1nÌ#z.œÇ<à!Êó¸¡ mˆCÒ‡þ9Ä! ³ÁÂdÔ#}½ðF6¢ ˆ£DïC ‚¢©jØ€Õ³G3´D²ð‡4Äá<¾XÃ0zq‡f#u¨F0²‘Œ@”¡<æØÂZùÈ?Âá8‰t§\«ÆÄá º±‡B,£}¨HD®Ñ‘‡ìb$ DJšÑ’‹Lä ɾÓ›œ¡ÛXÆQ²PŽ5¬#úP |ä#³á:Ø1m¤r…Ÿ¬¥.¹È xôò—»l¡/}Ì^ƒ…õ؆7|†e¸Ð³ˆƒÅ …Šü˜FôWzdÿ$&y9LŽS˜ÀÎÁ:€¾Ä ½šFÀaÓ°zÕ®öÄëWó:L®öõ®Õj`ÁØÁ ¶®V k'ÝAVmpCö@A0ü5£=e=^ØÉSÊð³  ­hGûYŸÎC™àè g°B Ó8þÚR™Ê¸¢ce‡7?¹Òúö·À ®p?+w¤Rƒ©%?ÌÑ)[½Fû€k?Ð :€c¸ØÍ®v·Ë]Qz×»bÔ®'}É nÔCq°Ei¬°Šèaƒ…æm¡1oXò¾9Tc*ï{Æýæ×§ÒGÆ@‡^€µ ƒ:Ø:[“t‰²Ã¨Ã3\øšò—¿øµo~3œ_ ÿPÃõý°~û»ÃT¦2‡òˆÇ Ë[gC èàˆ5úHîˆESÓ C =\ßs˜ÇÞ°ˆ â ö˜È>²¼ä0Ò×ÉNN2“‹Æòzj¸EiÔŒBvr‡†¼ç7åÁErÑ»ßeþ/e¸Ùlxó³ÙÀÆ !½_ˆáϨG/€Q†7ø$¢I 1Îàe.²pÌ2ts(WX¾¹Íóø¦7­Æ4ãð›—Ž4hËŒéD+ÚÍß̳ñeoÆKEPë6¢Žj¡†mx?+DR˜§ŒaáñÍw`Z‡gþ¤¢M+DKkÚ“ß<³±;Mj®PÓ‘>t¤/ÍÂmˆ1ͧœj¤ÝìYQÖ:ˆ.|æбå.ϰ“.ÃX‡–Ÿ°Ë„&&­eZ^ûÚõX!7P¾Y6ÃCÐe³7 ;\épÖôÃÏ=ŒûÔéaö¢6ˆxæc'c†ÍFù´¥>¤Ë´µ†o£Ãë e0w­S©óHCìÎÆT³aÚϺ°èR/n-¹Ž€£›Î˜EfTð‘0E"èH¸7jÈÅTÖÃ黀4ÓßüðÍRü»efsÏ%>dž´>ýyhI펢wæÀ8ƒiã8v©)’ÿîÎG?k6§YÑÛ†‡µïñPw3⥻¤ŸîtI‹ñÍìŽzÿíÐ~½ô/}šÛþ øÒÏZˆ?¤ºeèq—ÛËã§{-÷îfá':™Ù°G6b˜CmÈ™ôšN椹ñ‚gT`ó° Ð@Ó0*Ç q5 WG:4r”æiø–|_—r§Õ~b§i §t8´wõÀ ì}ºTuî6Cõ rÆ /÷B±7sµ‡7wá–oh'k=mÞd|æe|óàq”xó7ræf“¶ƒ·Y7˜tb÷MH÷{GøqÔ—tóp}7ØfßCÇÐ~3JæõeÏäv¥wèfÂÄ}ùwzG´ ö0Û&„›%Ý„riö÷$=ÄfŠçg(°Q’Gyù…|‘†tQ˜|n¶ ïðhþ`^st„mX‚XïÀn%(‰ô UReˆL×lïp ïÀ Èöt¢s³§T²b{ßp9Çs£g¼†o’¦ “Ð “`wvzÙ  ›à}2ô šPHç‹¢Wv¡ð’p õð  p}ÙÐ ÉŒ5ôf»P ò ‘€ ì| —Œ¨°YKXzEg„Ð^s—uâöv\†~Ĥ~ uPpDÌPnoXذYÚÆZ$z×Mñv Úð }Æ\y8§€Þ°p¥Ôp—WtôVñXì&ÍPúwmøXä˜CÝ´ F”L`‘¡Hva—|Xj±WþŠïSsñ‚ÞPw½×{_ôYº€iS… ªÐ õ p}±À z÷ Ÿ0ž _7”¡ð¯à ¹¸ =¹ ‘ Cžð ©p ¤0 Þp ±py¯ ºPÉP•ºð ˜  º”¥· ¤Ð º`^© ª “ õ° À Sµ °€ 2T|¼'JnÈ…/ä…p'wŠùYgVq.Än=õè3ö@g%Ø GTÌ€ —(=õØM¥W^Ðö I@, {y„æ‡ò0}µä†ì6’° nˆôPøØ öà†úÇnôð›õÐ ó@nÖ ŠôPö œ hø2$g—þ7U xw1$´—2¨ªèe¬¸{á…r¢ð –   ¤ ±ð–Ž  ±P »à» ¡ »ð ‰ð— ’ »à »P ± ²° ~ÉnŽ Š •@ ÉàÛ° — ’À ÷©‹¯ º Œð”F„ ±Àò° ’° › ø© ˜ Ž )Š ¡ óp ˆ¹ss·vªd~•%wékóZ™©èÓ ÝPÝœèc'™œö–9`‘QHÃðš°™€8× …öh‹Û0ÝÔ òhñˆ†€– ŠÛð›'©‘`’Ò ÂÙ p†þršœÝTøh^@Ê)D¤È 3é‚ s1¨{2k ‡unö Š  •0Ÿ Û ¤à ²° ±P ±° õP žÐEé õ  ýù ›ð‹à©€ Ü`ܰ´º ² «‹Pœ€Žà¥* ɤ ¤¡• eÙ ®ÚÞ° ™ç ºà Û ¢ ¡j•õ ó £Uk?´v1Ôvo†T÷C¶ó8UH‘ÉŠÓ™¤™9`RŠÿ à^oFCø &¦²9yºtC[GiÀf’¸›g(¥Âù¯öPÌбyZßÐ¤Ó ŠÝÀ¨Ûà¤öð €*þUNš²ë¯õp»¨æuJßé-8ä©’×{–ŠfDHZ¯À l¶ ªP¤ ›ð Ý@ © žÀ ~ɪʪýé ž ÉŠ¥ «Û  • ¡à d» ŽPJ‡¡@ Ýä¢Þ ¡àõà I+«Ÿ@ ó`©ð Ý ¥ ´Ê %˜ Г<§I7‰Céx~çÖŽùVqÞ” é Û œ;Oê±Î¹§;¨õ8óÊ›š6Oó °(#¦Veêi’öylŠ†ÝŠ³RzÀy&9*‹¹pÝð %‰¨Ýd¯Ûð¯÷ ²4ûX݉k-ô¨á©.4 P“þšsô—“¢õMŧìIja; z7‹°  –‹ð Š€µº ˆP”}à «õ€›Ð¢Ûp •à¾c¿Å:‹Àn‹ -ª ŽÀ ‹p Ž «ê«£ê˜àóÀ %ªÉP¾»Ð›P¬Fɽ}à{Y¨˜@J~Žé®çèlóp¤vWzŠœºMzD[ß@‘¸‹±%èqÇÄB ;{ žK›¡ÆƒÛlf‘O:¨Rõ¯$Û¤LŠ’°OúÄß ¼ûšLn¨¹ë¯Ã«‘óÐ’/‰CjЧ=›{@«½ž¶ÂãiNÇ}É@g’(CÝC#Ù¥§ Ç{Zú×MÇ mþìöó—üÈ}›5’Ñgzôjk},„-„ â …à…Côpnë*¤ëø¸ék)„nfDò8¨]{™ÀiÞ@WʙɛLÀ Ê„¨'¶IÜÐÃ?L Ùºuô~š¦†noÚ6`²ÉÿšœJܤ%)š™Y’–(UÊ ûxZìÖ§¢yRúœÜ  ÝzÒKƤB“Dr½•šÆ£j¡¶sž·ƒ“VtÊPC‡Œ˜§Ç’F¯uZŠà¶åB_—nxì†iVo“jüÈf¼Pz· ¯p©b”vLǸٮD*†½$„t¦hõ:U¦Ej½Li ëØµüx 2h°&OøfdvlÞ%lHHz½6FTUmb”½›å`'ß3“}Ö\·â39’ƒ ÅFtwb:DDPø„ÃÝF4ôlÒf㥻áN¯ÈwJ~FáuhþxmI}Fd'GƒH\è*GÒ}ÄPJ@ fZS¶fOûX?Ä_–CÆeFÕff,ôâ¿$ÔjÔ‰´€¦ñØWü0hÏ`φ°F6éAvC›eù5ë6´“Ÿ>F!VCcvLŸnFT\¯Çk¦ÆäHêRQs[ÂÃÏ`èö%é fKFV öa4½¦íAv_¶äêF\hn\:dm×.Ô÷îê^_Ô~aFÖîùÕi7D^õep UÀà 󰽕_‹ ´¿EGÂ5~€·îÎ f0pµüFâjÐÓhëÐwÝ\ñçúâŽæ ´Ðgà|ì]§Òþç WF­ñ*¯ò±¼ò.ßs¸6OdV^àÃ@YqÇïst_B-O¾”W@ÿóBßKãTôµäXyUSUÉ4äÎÀ@ä jyÈáTÕPàšÞæXõDô^ßõ`ÏõH¯ d_ö|Uô-7ôAŸöl¿öŽõIŸdO¤ qÀЕ¤î'¯a$÷”uõyÖöj?ø‚_ønOø‡oø?oöe¥Udôÿø’oô“ù”ù–O\*ÆfõN“5 gÐeïu{üò¤õ|{<úõP”üaÐa©t€hú¶/ZÝ7o"Äú}BcU[¶P¾k·_ü¾EƯò¸îþØ«ÎPÌÃg Ï ˆä åõX¢6D74Ué®ë·iKÆ•ldV\¼ùüÓ£A§ ¦¦\­ÙQüàT9 çCˆôÕý†xþÆÚä½ÛO^6yÎC(Oà¼wÜæq{7ï Ä‚ÛÞ9È‘ Â„·ÑÛ&ÛInõž#CŽß¹1eΤYÓæMœ6÷ùÛ÷OÝ¿têÔ «Í·†DO£GJ›.uºQ Õ¤ µ>½Õ`A‰—n̆±"ˆÓ^$X±-Ãã’5[-ÅzõèÉ«7ÏÛ_pu‚ýCWbšQn‚cü·ž·z)!ûM™ØïQÇ)û}¬ù¨JÆþàžýM -Z rÿøådÝÚõë˜<÷ñ[Íoºj'¢3êÌÙãÈÀ%‡ì™³7Ê##ÇœX2óÍ¡O?>¯8oØÿþ}-˜’ièÃ&_>6Oè~þ´FlC´ÑÂå^]ºýÍó‰ÞŸ:äàœÃÌ:ú Üo¸áðû/?Ì˛Ѷƒ°;q4FkÜ`%h~C„æ™_J¦Ä_NLÑDiY‘ÄYüe¥•B_¢‰Æ6ªùÉ< ƒ¬i§ÕÄãbØ`˜`¢¦Cc”RÅ)Q\IÆZX„‘J`¶D‘Ë/S qÅ'ƒaåŽðÖrM›ÐãG(ŸÔ©æ`ÄþA±Ê(ÁÌ3Ì=ûÄO`h¡…J)ÿÔÓP>•ÑÆŸŒ¦–;†j‰;È@È S`è4Ó0âÐ4 2DCSQ˨ %ÄPA2H-#VQÉh>…uÓ`uã Ù–¼zŠI<ÜjCT@aSZ5=µTRE%•ÚR£­5ÔlË0£ŠY·Õ4Vh¹%cÚ8ª%wS9TUTLaP# 8‡µW5âŒé§aR˜Á…LÏEU]s ®]‚ÎÖÜiÆÖÚƒÇUwŒUËøÚQ#~8Zr!–VakAæxZY“°ÕY2T`á2lÉךjÐ!‡œ|f–Yf~ÈA'œ]òyg þɹa™óÉùfŸÎ§f¤u¶kþÉ÷^ªqZÍ'©ýª6£NZgžæyl ÃÎùlŸuVašj~»g¥{mÚŽœùéj‚õgꪅ466ŸÐA'g±å6ûk´ç~›l² o *°^ ä`=8“ÊDk?(ÆOöVAÀ…p_ Ô—íΧ~Ä0|dM󼞨°ƒ,D WØC þPˆôIŠñÂ!êP‰>Üa±6<š¬ç‚ "ù¬DuP(S4ámŬÑ0ƒ\PT¸D!^Qki(¡ø='^„õúLbH:1²†€5ÙÞù˜Æ*ÆÑ‡rÔ  «¨6ð‡T<# ùHAª ‚ç™!øøØ&&2kZ#ÞÏ·?Š”yŸ W¨¦†r&© ß 5I:Iº‘•4©clvâÉ ’Òj«,ßù¦–ŽK“–˜þ&/‹I¼óYÈa$â,‹)Bb3Š@œÚÞl£JܯtÏ|a"Ø}u1|·42¹§Ëª]Í|’T%à ùNcÆFFü ÁXÍx†2—{#]݉N›¬†|S[Í áyÐb“›ÀcèB¥¦' l¨4óYÑ|&4•"Ä÷Ø“¿ýèj¬saÐ@ ÓùCÇÂíÔÚ´€´@Ù´šûÅ”HáiëHúSŸuEi±|R›Þ¦AíéÕŒ„žrRѦ]êÔ¦VU«%ÅêV»ÊU|©Ç (íë\¸<¦z5­`Í*Xo"R³Êdi…:ÖPT7w’Äþ)ë6U!aOuÊ£ðòwذ¢¶ë‡RßÔWÄ>ö'·T]M Ø¥¾Ó”WÝ_g#ëÙö¥g¬öKh?{ÚÌÖ$—m kU‹†îÃžÈ ¨S‹Y!Ð|eB“¬bãXµN~r•ãôãK"ùÉCÅÌXzÜõšO2É?Ê|æ˜ÀÍd6sšoR暌ùc†sMà¬fš¬™Íf^³ž_SæjØa@™²• ­:9ÁAÔ¨]FÍ Z01];¥&:ÿÖÍxn³›e"g4ŸCÎl>sÓ|gOÓYÍç`µ§g‚i>»yÔ›îôœc2kר‡B :öûè÷Z¨{E ì¡ …Ñ,uçPÝiPÇúÓÓ¶I´;ÍiWûÛ·ž ª9]f\«úÚžÞ¶qÕ1jØ)–“²þñEÕuc I2yé‰ýˆg:›Ô¦–v«÷lçn×Úß±nu´gíRsÛÔüöskð¼µ|9|(Ž7ƒýÁjÓÕÔÞ–F¶šÎ15˜˜8ÛiÎ÷¿O-𓯺Ö‡³4pêP»šÚù·ÛüòiùææYv§¨îŠ ØáL3ð tOkö¤Ô`‚ó6×Ùß­^x©Ëo˜È@¬ÿa€ZC}Ü*¿s™¡®çsÜ_'ù?vN5›#_Ô¨/ƒ.á½™ã“nsÓ‘^㡞‡€”Eå×kÞg™#Üí+:ãe‚ósì\ìân|Mðm”œÖi¿öÀc"ö×H£Ž!çÛßïþîÞ‰Êõ„ûªûº…‚î‹'xãöýç-Ÿö§ã|ë[_|ämöÝ?>ì11ï ÿø·oø(>™ßžfã»ÝøÆ×9 ÞCñü¤×aÔáé¯ÛÊ6íÑ•F¼ã­H™—T„Iæ÷ ú´ëžøO— Øq/}3_þëô¯¾ïÿÿš“?7;;Ûc³,@Ýû6ȾŸ0pRì#Œáé2:º¾œx¶‘[¹…Û3©#3´³ ”¶€óÀ<û·$·Ê³µä7J’= ª#­Á²†¢8+ó¯}™ Ëã@}ƒ<曾›û¼ökµt»:Ã9µ‹Ÿ®šê§&{«”C¹7˶–ë3Ä#;4Ô7•K5R{5€ƒÃ¼:™£¥:°ª£7Aõã(ïÛ>¬®fë6΋=!t:)<è 5ƒ:¸¸´¦˜šš“°Ã4h¿|Á¹M<‡}xº|iÄ^‚‰¨5sнN¤?À9Fü¿C †¥#3YŒ2òÃ+ÁÕ¨³h;A9œÃmûÀÎS¸7;9ô6rSÆM¸©‹9ç§áé"@ ±ó°;× D¾)(©Ú=NÛ‡ÚÓ¿Ï3¾T4­£¿¡Ó½}`´È3ûG°›³Ëk?æƒ>Þ{:°³DZÿ9+¾ÃÇQþT“;šè ¹;¡# ùÊ Ê#ÃrKA\Ó?T³¿µ‹µQ‹¹hÛ¹Ä5h„¾²›‰ydÁÚû"ÙÛ¸R@´Ã]¶+$“s3v`B3Mã;OK LƳ6Ÿ0»1Ü—WìÉí«BŸ‡9l³w¤?Ÿ¨Ÿz;jX ºó‡¡‹1²»À~Œ>d¼‹>΋º‘|ÃPc¾w„Åü£‰_tȳ,C¨3±CÂט.}ª& +¯?ìBÛÆ<ü·š‚³šêI™s¶˜ 83¡C³§´I™è9ñ >gã;˜`´¿ô@ß›L¾»Ìs(à»1#7ah bñº£ÂÅþ+¸ô¿g<¹ÆCµçCÊ9ŒBl»ÄL„Ëe´µlM>ÓH<;³ÙTÁ ?»Ô&©™-m,/¬Á”,=¬D<âìȘ‘ê7h;Fê\³¿)3Ód4£Ìóiµ dA™˜}ðiP,€‚b ±9uÈ>2¸K3àM—7äÇÞãÁ{4¼Ü»ÇèGl¾v4»äc¾ÈC€Ý¿ˆtDã+¾à$›¨%0ÃP£¢Ö;¿5È3 õÑQÍÓ Q™Å}Qi73œ-QÑvƒšMјŠQ•QôQÅQ3’@kè‚Bø‚-К‹Qkøþ1åPœ(³é‰yI©‹D¯4Bþ‹B uDÛó=á,SLÓk³M =5ýSS3µBœ°7v²$¡HIæüCkð‚\ †b°†÷üÓj(†?-†A-TC-ÔöTF%F-TGUTD]ÔB=T@T?½T@TMUÔGýTB¥Ô’ÔQUF5ÕPÔKÍ…A„B&õ‚bÈ…jbØ‚\xÏZõ²‹½24@}KÁ!”>8•¿å?bíOTÊyôGû#@65ЧcVfåOœ¨©Ÿ†Àù‰˜ù¡7ÙP•ÔS,ø"ЃH;@ƒØ4h×uUWxeWyWzW{­W|½W}ÍW~þÝWíW€EƒhW4¨&Ø‚@ „%C/¸'°ƒh'¸‚"¸ƒˆ;HI©©¡K%4sK8dµÉÇú›VEìÇeµÐg…¾œƒ¼Ü¬9û‹G'¤B—å´#t>3s?cÕ¿|3К€Àcù‘š¢Å¿¬K?ÄÆGK/jàÖ*-R¨Z©Zª­Z«½Z¬½ÚbA&½‚6(,0ÔIã4×X6|Ðÿ»Èæã³â£Y·lĸ¼sœ3Í¿ݺ®C>ÉSP÷3 ¹BNd©YäAVälzäFŽäCväJ¦dBÆdHäO’(æµíñ‡j0°ÉJU,íc5³6›û¶¬«¼4Þ¼`M<fCY«¶™«:|ÈYãI>J¶A}]-pƒ±UaØ ¤­ãN¿Nã0™2(hö%iŽfjžfk®fl¾fmÎfn¶fi~¡z*–3Ôm2Ñjˆ( “©eQýÑ"QQwÒ*•çQþeçvR¨Åç¨Qs>Q3âg}Zvvg%è#5?Í.èÚBÐ,¨˜©Jõ 'ݱGÛ;ú,¶ß #ϽËa9! “)¡À‚,ØÐ4Hw}iv…W–¦WšÞ&ˆi›Æiumz½éÞivõiœöi4`iživi£~i¤þéy-jx¥é¥†ê£vW¢–Wž~j{Å;Ð"x/B@0- X/ð'@žv‚µÞ°@©Ÿp-׋4ŸhÚJc&Óét£‰ Ð¯…´†;8…BÅ?%UÅFUÆ^lÇnlÈ~lÉŽlÊžlËÕÄ&VëC€,0¢.pþB%Õö؃?56´d[´©©7Žókó0±d>1(!©J#QÍí­çÝÖmÞöíàþíÞ&nánä.îá^îäM/ø‚/‚Â7 Õäö‘ ²«t=Üø½sAØ&±ƒ±çÊ\tcâð..õ¸¸ôX# Ôõ®†ÚÆÃSªbíëëK6©)<ò LoØ0(âAZ ÃÑ,¬  ÀCíÓ\ð6Sðý¥´7qp ÿ­oð ‡ðñ¨p Çð ÷p×ðŸð 'ññç‡t€Á¦­º¶u°”:žôÜ Ð̃[_CcÑã‘JÕ\Iw®v"ïiò‰*þ‚,‡:þ.&'ÉB+r(×è&r)wò(·- ÷ä¾ ÉL‡i0²~ž@k#/Þè8a`)öµÓñ D£cÚ £LW ;ךÙñ5ÂÀ`òµÙ±<¿>÷µB÷ó>¿sWôA_t=OG?ôC¿s@¦E·ôFotH'ôÉ…ôDÿsD¿t<tG¯ëünJ\@–mQëVÌ=7©IOksò8º™ rB$){©Ô>¶hb uö× v×0vœ¸ïôØkJ›o2òQç5Ì¥OúD['zsA!é:ÒkÔ¦Õépwq/wr?÷qOwsWwt_wwowxg÷q"þ'â%Œ¶°õAüf7,»šm§²kg1ZªË‰{0Êýñhþæjö£†æmv§‡wøˆ§ø…‡øl¶x†×ø…7¡b=Öö"G¿¼ìÐ¥íöÙø¿$òÑõÂÅjJy4J"GªyC¢ù›o"œßyïy4¢­ß¨’%\Tù“o#»®õ•¿PúJæ8w [úoHÒáŸz—¬ú@¢z·zBÚú¬'"8â>ŸpR\ú :½ËÐ¥wòqrz2²âÑEGã8g2?ºöc«û¹×û¼Çûfóa Ì\Eb!k#vª8 %êwØ6/‘ÿ"Ø’ÿÆ'Ï…ø¿|ËÏ|ŠÇüÍ×üþÊï|Ðÿ|Ñ—øÐO!H*úiJ¯³:Á¯¥Ùc|´w2"Ÿ8 [ýµç­}B&¢À/"yÛG|ý®¾ý9… ¤5:ßzQ¿÷®âw¨æþh²O`vøšûÛ|fâ(ÔŸ8|í;Ö¯‰bók—þò9þ:²ûîø, Cò4H_ÏÚ‰:‹=ÔÆÞ€c䀣ÿøÅùçþü'ðºçüé+Hp Á} NÜ'ð A ýi´ÑàÁ„ T·cBjþÌùS§£˜AsªÓØÄšºq-)òìéó'РB‡U‡¦XM}Õýcª±$ѨR§R­*uiÁ–G™fäh]þ“bÕšSgvb׌çÎ1Møô©9ˆç>EwRbSÿ¨}ÌZpíÙOÿÅÍ(¸î]‚5½òå9ðĹjå&h—#ÞÅ7å¨qš:–ýÔÝ!Vͳâ„F‘zµêú5lŠ«5ç©86îܺ‡:¥80lïÛMÓT3[Íšµ Ô‰œx¯ð›B|ΜjÁ .üûpàÚ¾Þ§›ü®{^Én»V²oî%«ƒGß[ãúÁ蘞SÊ–i?ú SR„I¤hM9‹:úÈ4ØnJ8›?ÕfÛ…j¸¡kO95†L1—.èX³hàTœqÿ‡Ž‰Ì™%â~Lµ_vÆÁ(þ£ˆ.žEŒû5eãŽ5ÒxÖÌå¥#ŽgÙøc"Ù¤“5ºHSŽêTS¤“>2$ŽŠ¹i­˜fœqÇ­Qà?Òpøfl zÕ#œuÚTMþ³ˆÍ¥¹8áD1Å£Î0Ö s&Nªc 1È=úh5‘ªcéqÕ‡\SZS YÄ0¨%r™ç(¤“6Z)N˜Z£)rÖt)¨—Žº©©ª>z(ª¬^ºâ«›Êºë§RŠj\©¯šé‹Ö\‘K¡‹©5·QLYwj+ˆ™&ܶáÂé¡A}rå:WtÑÊF¬¡Ž0ê@G™^0AeY“C8LzA>Øòhäþk2ð!LS;8,"hØ1°:l øêÛoÿ<ð¾—¥N 7üpSOl–Åúf|1Ç L°È+̰:ï±Äã€ÃÁ$ÃÁÃŒ8E:ØFF쀃8 é•âZÍSÎ8å™!WW{½Vñ¹•pž©ÓF+m8ÑÆ-Z×Ö5Süt™ÐmêÈíÝ’\qEwIÙmGP:u[•Ý]C$¥p|§Vß/9xÝw·‡8ã² ÉŸe&)õO¤ÍÖ`)ü Ôõ×âªÃCü<®gé­SÕ5„Z±YÛR„ó©;X#]…žõÎQw¾[èÕïõsà>úôóCËwe‘ð˜þA½^Åûs|SÉ;’òÌO™ô¾ƒ_ý÷Ø«£=óÝgýò]àY õêLJ¡äº¸|â@ÿêAˆ?ƒ¶=ÉÉ!"Zƒ\„œŽùE2±ÓŽŸ2ÂÔ¤§5 !—èÖ½e‚­qŠ)» B0‚ÿë /˜•*¦wÏ[ÞYšR5%Èx  ˜’ƒaP§)nÙ ƒh@¿$r’ÌŒnB˜LÃm?ù_OTw®°…zbávN(Åi„„S$—ãÆApñDІ©bg®ˆAâç‚þÛ@öƒC5…B¼ŸÌB‚ð ƒwü£aÂ&;¢Æ,„jAöh¸Dr=þÁ „¸¢:ÇaÍ'{Êÿ'FJâ *ªËC©742ÅBiÒîÂÖ%@j¨-ÄàcpÒÃJ@¦”}rcSÂŒ#N·Q݇òÿeˆíŠ0móI2Ê™2fQШ¸šC&0∓b8K ñ)/ì‘NÙ¶@ØùÉ\nÌ:v‚Æ©NŒ¤cæÿ™Îž¼™Ó|çýbF*n­™ôäg%ýAÅñœKô¡^wCqâÆ$vi¡ÈP¯Å2#æTáþ¦¡˜µH4*õü‰A_óÑNîf¤–à?ÓrŽ=„%ÐéÌB'j•n‚änÐ{\Gez50Þ2ê š(øÄ¤ß þ%íNZT¿ŒôÈìèHßéG¢ÕŸ´cˆ Ç—Æ AòáS¹ÚºŽ­@'œMqÓÖùD¢Q­êÛÊ̔⠊9Í)3MŠT¸BÓÿ‰PÅÚPàD ‚`Eÿ8àÀDù<,d¯¢‘Àé.Oo‰¬HÉ&9§bv§°ë©·‚¼v¶´TTLeý·ÓzTER½ iY+¡ZlUŸÞø*[Ö–Uª±Ý­b4ûXàÞ)±ƒ´¤hAI\ÓfƵ±[ír‘;»o%6º"Wo‘ºšpZ—· iwƒ[ØÍ†N–-§m±–Üá–W¬ŸÌ#ÁÞï¶½×½Mvo{îÚ²ù]áþ\­ ¢eþ¶¿Üâëqé¹^Ýx›ïM-l ¼[Üò—­ ¶ YoÉýÒNtÇÄ[ubø˜#.1ZÀã“Cæ#'F ŒSlâ‹Å2Kz·ªWà˜ˆ;¾ðUJ‚͇–5I…Œ›hü³ø˜Òpq_NœäÓGÆI޲{d¬â_Ù;™r•±¬›ÿnÕÀôÝ+=JÕÚÎnÃ09ò‡U,fñôÌYò{çü$Ì3AÜôâðè9ÎN.é¦«å Øµµpš1\®¬€¶$ .?dÂA»8ËÖtŒ· Q§¸Ë¡–³Cíi>“Ø:Nnò– ¶ïJX¶g®n¤þ§‚] ¹lsV²Ek…ÚĦ1§ñæ8ÄÔ†6xji‡¸:̦³kr¦h,¶·Ç Î5QØ[."[ÚÈ\‘È@’ €u“˜'Õþ³¡'rm*g¹ÄéȺ¥=¸Ú5Ì”áÝ&§8Äú–÷–™›¸ÁN*šÁM” §×Íü…ˆÂÿ1o>¿xÅyfuŒ9®…»ãû´¿?Mj9ãÛË×n²B>lyëFÛ¾ ptáKÌ™ˆ[âCá)¹ƒ ª{80o¹wò½ìŒkœÝY7Á.õ‚°ûPzÓ©žd7ñ»éRϸӟ~u¯\ãñ ;Ö®b¦+uÑ\Óy…Ûþ;ýeHçҠϣBñ6™r'¾þtžè›äƒ7;ZæÝòs\»ìGúãÍÎøöLñùÓ Îjþð™G|âÛ::%ýc{c™‘ì` †e¨Ö¦­÷bºµÆõ¹f/ÃeãèÚ,ó˜ŠwD¤Ñu°€àY?‡›Öm¤ÏêHgüÕ=ÿ—©3ß;âMNÁ[~ðÒh<”/PÒ/$@lÙŽ’ä8øÍíå½J2W¼ëšv•F-N˜w6 þH:^tGÄœF0›?Ì[Da€J@F ]ÿÝ_$ ?ŒCóµœ?8 ?tÝBœC´Ò ÆÆ ¿`Ìþ=D¼ÜL`A‡ï(ÅYœC€ÌÅ9à„4DÒ·-sœðôˆ|Ñ_Jý™ÁîØ†WàÅ™Ãɹ‰ º˜ÒE[ñ=]ØÀÕˆ¢ƒ@:L:8ßž¬ûa"ÀS_ÕI^Ó!ÆÀRa–±ATã­› €šÜO¸Åò°M”ßò8Bð`&XD98[à  5EÐiEþuK‰W¸Ø%ÒÍÆåéÜÛ…TŸ%Ù;AD:ÑÍù0Ù¾aZT¢B´…b=„Ꮇȳ=”ÕÍÕŽìÒý‡:Èœ0IÄdôhtL@Ð5bb aITÖ`hÄþè”bžñÍù%’ÂQƒ4¤“+Fá<SŒæpÅ5Ç^TÇ%nÔ–©":\5>2¹‰›”uݬT‰DñLY;ýá@HJqTÃs¼â8ÈDqøáD\tÞõlN: #£5"}HÐ5Ì$‚MCsˆG_Üœ=™ŒíIm¼_©Î9ŽuìÃá(ºÕWH›À™ȵQ‹1Ù±ÉÆIøC5ìADKƒcù-Åi“™yVõœDZD²YuÍê ‹IÉSN匼‹DÉòÈì¡UÖHV¾HWŠ¥–Ì^Vz¥–ìGV Y>¥[òÈ– š\å[ΈH˜þÂhAÊ\¤¬P%Ræ\äß MURUzPˆ=Jà‚¡C.@æíTæ§TƒeЧÜΧtff"‡eÒJeŽ&¤¦hnfeb¦gVæiÃgzæ§„¦gÒ lr¦evæj®¦jÞfm‚f¤ˆf B  |ÁD¦kBf_ºŠ¬œ„™¥Ö{ÅUb6ÓY‘ï(†5l4ÁÀÚ8AŠ ˆx¢Áx–'yž§y¦'z®§z¶'{¾§{Æ'|Χ|Ö'{Šç¤ÁA!!üg!HAìAÁ€6A´ÁÀôÀÃ"šÙVôÓkM§\uMvO¹‘JZÖ¥‡~(ˆ†¨ˆþŽ(‰–¨‰ž¨]šE1| Â!LÁvZC ¢8ŠY ƒêEüõ—Sö^XYè#ÁÖ­ÍA1t‡srÖ­’.©’6)R1é“:iUAé”®Y+Zƒ|Á@gZƒ –Dd#sì‡ (š}ÐGý 2™†:àÀX”Ã@”ÃõHŽÜ+Šž¢_Ùé’ìéú©ž jŸæE êŸj7æi¡2ê¢òé£jo°Å µÁíTC¼TC_6H!©N5ì:(’„ˆ)“íIœ Ý_KèÁ+!m]HnÁªp0ÒÛ S¬Öª¬â*®Òê­Æ*¯‚‹¯Ú*°Î*2MމdKATCX€„þ‘âŸÝ\nQЫBÚš²N›–D ƒF¡ÃúñCàH„û¤ «bMиŠd¾QG «¹®«D¤ë¹¾k»Š¤¼ª+½–«½’+¼º+¾Æk¿òë¾ÞkÀêë¼BFyÄ CÈ[¸–DØÅìíÜœjdQÈM©P ×b™©Ðµéi‡Aä3ÂUÈ‚,È–lÉ‘¡¬É²lÊ~Ëʶìü‘_›ØÏèTV¨>Ž–Xñ¨hmOÏblâWéÞ›­;õÕ¥©6P±rMÆVÞ5-#’ÑÒÒS?ŠI¢EÏ.ey©Ãš$EVQ«D’NìðZ¹MZ=e­ÒöÕ¤éV2¶Ô&)Î%þ­UYTÄemÜÀ8‘lðlcŽ­ÐR§oÜÙàÓÝVèeÁì3ÎI™±mD^Ö…äºä6U ™Ðãn\ý „Q„ÜèŽßž©hY9Q,™­&nWÔŽ¹QEÈÒÅa„кŸÕš*íî..eÄíÆT榅†¯P]uîó†ÎA$ŽIJDæœubEp¨n¤íBÍIØŽ,ñì.÷VOeÐ.Lf0A©•oe¼®çF©Ê~¯÷Zîåºïëºéþ¨ÐSŒnéš.©– õFšq9!)ˆ‘’ø °´ÊµÞêæºìüÕ´>mËìÔVÏU!iÛ7Ea噦–ôþ®…ÒV~õìv…û¾lðknõÓæT ïªÎ2š×¶m±+ C#‰HÐÉM×ΰ€î>Ñ-ƆԸµÙŸl×öÈp1­ŽÞÆpÿ”°"ð ×*D­1ÑIcñ?ΞªcåðéÙ .ÝÎ…ìoõ¾-Sžï?XƒŠüƒ(I’«´Ÿ)&„)ÚÓD`èàq¯n‡/ÎJ&ÎĤßãñ…Ü1ZÐjsð1æŒNß„ WƒŠ€©™ù@¶ˆb• -o¬fÔ|õ[4I^PƒÃÔ%¾Q†$D’±ÄG Æ~\,B)’F~D,DoG,OGk°…M2.»ããðòþ+óaóSó I„"ãß Ç¡È ûa‰:¤Äî…Ù?Õ`&fØd( FYÊäº5ˆÎu†©u¬„g4¬?”ƒ>„AÌà“©K€OK¹3jÀ3xÈ3f ÄJÜsV賫õsïüsN®ë>oCÓ³9 ´ï*…4FK=nSØ€¬,Pe5ø¨}iJFÀÈ¢áÒÖ ]§˜…5,K5\€T‡äÉ`/e o…(† à8™w m„3qKC‘:,þȧ P€Þ„û˜ƒ…´óù@£8ž2D¥h¤ŒiH:õ2WàX·óF2_ØM`'’jvˆöètG?ë4›$4¦²0Gö^L69~Ùè¬`sx°l¨CY­}µ³Ê…‡¨ôtBR¥aSä dA1´M:3Ç)Ò˜Ú©”ðHB¢B|%rwwåYX‰sÏHÞ$·tS¥˜wIp%MH‰`N÷Ž<÷rÛw‡FKC&×%ŽÒN ±`ôF@Ráºõ-Ý:€!¸‚vbÖp N ƒ(@œJÆtŒY4Ì É\€°È@œÔÀ(ÔÀÄÑÏÀ€þø©à€ l°:8‚S€‚3øðjDøÎD…_ø›â€†? pø£x8ˆ‹8Åø‚›ÅœxŠK8W´¸-´Ä쀜ÀÁìE5èA Ê€g„'ØA”mçœt<4·‘­D½*^‘V˜­B¢”bÊm®%_ÐÙ´Â@Á ¥Øh@N è¨å¤„%êAÊPËù RìG²L ©$ Nà9¥ÐåŒðy¨ÜN+ª&s¤¤ ‹¡Ë‹¼Š¢›£_Š£Sêíð¦kz f¡”z©Wú<™YaÒEôÃòÐÙFÏrc7´ŸÄ‘B`O­s|x0ϺGÔúvŒD|DDþÈ ¯Ëºsþú‡(²K°ÉÝÉNi®qtI6ŰÏMBЉ6I7sË µß°Î *ܬ·K·qßðµc·jŒ;oûsg»xÏ^%»ešéÜXlÉmT6†ÆÉZFbTP9Q½Ó`ð»ùþ{ÓgPUMN5düe(É@T‘Êã9mí£@ Ä-P¼' Å' IcR#qé IEÊ«|¼›™šæœîhŠ:”zÈ€ŒDÆ»ÎY}d‡zpÇc˜¡¹›|l”ÐÛ‡v䈽¶mù|ýÃÉ>È?À¬ oΘ ÇwÒÊEà|ÒÇGEV…ãLÒ"‰äó¶ þÔ~8—Ÿ@×™’ÈíC”§ÖÀ t_ŽXfÉ–PI^°ˆì¡2’pI• –äÍߟ»— ~Î>•‰$>w£t@OÖ£ÃZE’:¨Þ(.þäîv›äBtÁp&.ÐÑ~¸f¨+J«$:¬p ±Ôʱz®  ¯¨Š¯¸ÊìËfË­$ Íë¾®¼Š¥øþ©8ʦ8”5Šç¶MG°D9€þ×xܯP׿žtA |ÁêWC•3Ð40€Ô€ÖPÀÇÐLÐP@ ðÁå ÊLϰLÍ`ŒÆ t NÄ…>l©³–ƒBžaêÔQÁGØ?u;(ª“H‚ê*4Hþa‚ǃ8rT' ÁŽ ­ä³ð$I‰ÿp¼b ?3%ª³CLÝ>úôíüwiR¥K™6uújT©S©VµÊÔŸ:4Å,&ÕylX±TÕ­ÉõæÊkÖ€VCÇPÝ9‹ùÍTǯë¿sH-¢ãùÏoRu~»þ—îèÜ£†çâEº×n×ÂJó4ŒØîb¾…<Ó(C¡o«¦Î_?ÁêdXS'íh?£ci×¶}7ÔxѸžýOgÞÜÉ'NC [;àÀµX ¸NB£*½ß>‰þôÉ>:Ô{ôëÒ¯ïO~çWç³KÜ×Ý(øøë¥OŸ~Þ~uúõ©ëÓ>¡þ&Šq-1çÔùá4Ѐ+ŽÁ®®¬¶®º-K« ¼À¢st2§ÂïDü翯@31ºÐò‡ŸôTÊE¯¾kÑD‹¤[±Æ[\ð7{ŒF“zk¢&à!&°Èb ;b°C׃íÂ*­¼Ò©‰¸‚QH,½¤lBwLèÌ‘M»ã+ÍÙP{ñ;û1*Ãܱ«mtóŸa\³©ºòìs̼²z«šµÖ—-r¹e@bN;-°Ï¾¼SÜ$ÜÒ«3õ2CÔj$r<Ê6«kDCÿÔ ©œ˜¢P0V›sESëÂ,ª¼èZ³Ð=£”HbÖÐ.ÈûÙdÃÒ’þ•µ2Cë¾2ç­i:ôÐ]c͕пžÊ«³ÃP”[—‚u³5w®8ýAg/*{‚(½ÎG'*-}–ß~‘J'T.ý…vÂ7o$Ó/O%ëSÁtWe\\·5•³‰ýͨpß<·©ÀÀ¥uO£öªOüNµ½ö˜åd™ØÛ–‡›h­»¾:g/†¨Ñ *t£ÊjY«|Æð)E-ŠgsÎ|— âúGwqe™­¶rÓf±½ú6Žj^ÌÌ1*a‹9^u6>e4ÛaSé¬Õal}†µ¾‹«ìCfª†ºwòëÀ¡ÝSɼ6¯]Ó¡¡ÞͲèͶ^›[¶±úþsè¥ÔnûÆ5!cÈÕ¬vXë­¿ âÑá\h¥ flbKMjH¿{ýÃL-ÌÓ{虞¤i9‰QÌŠè õ˜cO#ëÒ›hµECþ¤"ÿ2 àe~UÄÒzzr:é”OŒˆó‡¡³?îõÐk¢Â ÓØ à {ñ©£÷t²Ì­}zNnÁ3Ê´5¯W©†ާWL¢Ã ùÇÎSBÀúR.`ˆÊ¦X O’½K늘3µªVK ¨ú;=ÑZv,÷c¬êX­Ä£}ê­î˜±­0¢¨%ÎÃÚ=~®CAQë¹Xvþ„§'n$CžØŒbMD5àeěҲY¬î?¸ÜÇ2—)83®_O‹©€;commons-pool-1.6-src/src/site/site.xml100644 0 0 5235 11701070263 15141 0ustar 0 0 Commons Pool /images/pool-logo-white.png /index.html commons-pool-1.6-src/src/site/xdoc/downloads.xml100644 0 0 4504 11701070263 17122 0ustar 0 0 Downloads Commons Documentation Team $Id: downloads.xml 1222677 2011-12-23 13:41:58Z ggregory $

The latest release binary and source releases are always available on the Apache Commons Pool Downloads page.

  • Versions 1.6 adds generics based on the latest 1.5.x release, 1.5.7 at press time. It requires Java 1.5.
  • Versions 1.3 through 1.5 depend at runtime only on a Java 1.3 or better JVM.
  • Version 1.2 depends at runtime on commons-collections.

Older releases are retained by the Apache Software Foundation but are moved into a special archive area.

Access to the source tree to see the latest and greatest code is possible through anonymous SVN access.

commons-pool-1.6-src/src/site/xdoc/download_pool.xml100644 0 0 15476 11701070263 20022 0ustar 0 0 Download Commons Pool 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 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:

The KEYS link links to the code signing keys used to sign the product. The PGP link downloads the OpenPGP compatible signature from our main site. The MD5 link downloads the checksum from the main site.

commons-pool-1.6-bin.tar.gz md5 pgp
commons-pool-1.6-bin.zip md5 pgp
commons-pool-1.6-src.tar.gz md5 pgp
commons-pool-1.6-src.zip md5 pgp

Older releases can be obtained from the archives.

commons-pool-1.6-src/src/site/xdoc/examples.xml100644 0 0 15310 11701070263 16763 0ustar 0 0 Examples Commons Documentation Team Rodney Waldhoff $Id: examples.xml 1221705 2011-12-21 13:03:54Z ggregory $

Suppose you're writing a set of java.io.Reader utilities, and would like to provide a method for dumping the contents of a Reader to a String. Here's the code for the ReaderUtil, implemented without an ObjectPool:

import java.io.Reader; import java.io.IOException; public class ReaderUtil { public ReaderUtil() { } /** * Dumps the contents of the {@link Reader} to a * String, closing the {@link Reader} when done. */ public String readToString(Reader in) throws IOException { StringBuffer buf = new StringBuffer(); try { for(int c = in.read(); c != -1; c = in.read()) { buf.append((char)c); } return buf.toString(); } catch(IOException e) { throw e; } finally { try { in.close(); } catch(Exception e) { // ignored } } } }

For the sake of this example, let's assume we want to to pool the StringBuffers used to buffer the Reader's contents. (A pool of StringBuffers may or may not be useful in practice. We're just using it as a simple example here.)

Let's further assume that a complete pool implementation will be provided via a constructor. (We'll show you how to create such an implementation in just a moment.) Then to use the pool we simply call borrowObject to obtain the buffer, and then call returnObject when we're done with it. Then a ReaderUtil implementation using a pool of StringBuffers might look like this:

import org.apache.commons.pool.ObjectPool; import java.io.Reader; import java.io.IOException; public class ReaderUtil { private ObjectPool<StringBuffer> pool; public ReaderUtil(ObjectPool<StringBuffer> pool) { this.pool = pool; } /** * Dumps the contents of the {@link Reader} to a * String, closing the {@link Reader} when done. */ public String readToString(Reader in) throws IOException { StringBuffer buf = null; try { buf = pool.borrowObject(); for(int c = in.read(); c != -1; c = in.read()) { buf.append((char)c); } return buf.toString(); } catch(IOException e) { throw e; } catch(Exception e) { throw new RuntimeException("Unable to borrow buffer from pool" + e.toString()); } finally { try { in.close(); } catch(Exception e) { // ignored } try { if(null != buf) { pool.returnObject(buf); } } catch(Exception e) { // ignored } } } }

Since we've constrained ourselves to the ObjectPool interface, an arbitrary pool implementation (returning, in our case, StringBuffers) can be used. When a different or "better" pool implemenatation comes along, we can simply drop it into our ReaderUtil without changing a line of code.

Recall that Pool provides a simple toolkit for creating object pools. The PoolableObjectFactory interface is an important part of this toolkit. PoolableObjectFactory defines lifecycle methods for pooled objects. We can use it to separate the kinds of objects that are pooled and how they are created, persisted, or destroyed, from the pooling algorithm itself.

Suppose we have an ObjectPool implementation that accepts a PoolableObjectFactory (for example, any of the implementations in the org.apache.commons.pool.impl package). Then we need only provide the factory implemenation in order to pool a new kind of object.

Here's a PoolableObjectFactory implementation that creates StringBuffers as used above.

import org.apache.commons.pool.BasePoolableObjectFactory; public class StringBufferFactory extends BasePoolableObjectFactory<StringBuffer> { // for makeObject we'll simply return a new buffer public StringBuffer makeObject() { return new StringBuffer(); } // when an object is returned to the pool, // we'll clear it out public void passivateObject(StringBuffer buf) { buf.setLength(0); } // for all other methods, the no-op // implementation in BasePoolableObjectFactory // will suffice }

We can, for example, use this factory with the StackObjectPool to instantiate our ReaderUtil as follows:

new ReaderUtil(new StackObjectPool<StringBuffer>(new StringBufferFactory()))
commons-pool-1.6-src/src/site/xdoc/guide/classdiagrams.xml100644 0 0 2371 11701070263 21042 0ustar 0 0 Class Diagrams Commons Documentation Team
commons-pool-1.6-src/src/site/xdoc/guide/index.xml100644 0 0 6103 11701070263 17331 0ustar 0 0 Developers Guide Commons Documentation Team

ObjectPool defines a simple pooling interface.

  • GenericObjectPool: ObjectPool implementation with configurable LIFO/FIFO behavior. The default behavior is for the pool to act as a LIFO queue. What this means is that when there are idle objects available in the pool, borrowObject returns the most recently returned ("last in") instance. If the lifo the property of the pool false, instances are returned in the oppposite order - first-in, first-out.
  • StackObjectPool: ObjectPool implementation with a LIFO (Last In First Out) behavior.
  • SoftReferenceObjectPool: ObjectPool implementation with a LIFO (Last In First Out) behavior. Additionally this pool wraps each object in a SoftReference allowing the garbage collector to remove them in response to memory demand.


A KeyedObjectPool pools instances of multiple types. Each type may be accessed using an arbitrary key.

commons-pool-1.6-src/src/site/xdoc/guide/sequencediagrams.xml100644 0 0 2517 11701070263 21547 0ustar 0 0 Sequence Diagrams Commons Documentation Team
commons-pool-1.6-src/src/site/xdoc/index.xml100644 0 0 17106 11701070263 16261 0ustar 0 0 Overview Commons Documentation Team Rodney Waldhoff $Id: index.xml 1221705 2011-12-21 13:03:54Z ggregory $

Pool provides an Object-pooling API, with three major aspects:

  1. A generic object pool interface that clients and implementors can use to provide easily interchangable pooling implementations.
  2. A toolkit for creating modular object pools.
  3. Several general purpose pool implementations.

See the downloads page for information on obtaining releases.

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

ObjectPool defines a trivially simple pooling interface:

public interface ObjectPool<T> { T borrowObject(); void returnObject(T borrowed); }

Some client classes won't integrate with Pool any more than this. Clients written to this interface can use arbitrary ObjectPool implementations interchangeably.

BaseObjectPool provides an abstract base implementation of ObjectPool. Clients are encouraged but not required to extend BaseObjectPool for new ObjectPool implementations.

KeyedObjectPool defines a similar interface for pools composed of heterogeneous objects:

public interface KeyedObjectPool<K, V> { V borrowObject(K key); void returnObject(K key, V borrowed); }

The Pool package makes it possible separate the way in which instances are pooled from the way in which instances are created and destroyed. PoolableObjectFactory supports this by providing a generic interface for the lifecycle of a pooled object:

public interface PoolableObjectFactory<T> { T makeObject(); void activateObject(T obj); void passivateObject(T obj); boolean validateObject(T obj); void destroyObject(T obj); }

ObjectPool implementations may be written to accept arbitrary PoolableObjectFactorys. This makes is possible for clients to select pooling-behavior distinct from the kinds of objects that are pooled.

BasePoolableObjectFactory provides an abstract base implementation of PoolableObjectFactory that makes implementations a snap.

KeyedPoolableObjectFactory defines a similar interface for KeyedObjectPools:

public interface KeyedPoolableObjectFactory<K, V> { V makeObject(K key); void activateObject(K key, V obj); void passivateObject(K key, V obj); boolean validateObject(K key, V obj); void destroyObject(K key, V obj); }

BaseKeyedPoolableObjectFactory provides an abstract base implementation of KeyedPoolableObjectFactory that makes implementations a snap.

The org.apache.commons.pool.impl package provides some Pool implementations.

StackObjectPool will pool a finite number of "idle" instances, but will create new instances a needed in order to support high demand.

StackKeyedObjectPool offers the same behavior for keyed pools.

GenericObjectPool provides a wide variety of configuration options, including the ability to cap the number of idle or active instances, to evict instances as they sit idle in the pool, etc.

GenericKeyedObjectPool offers the same behavior for keyed pools.

SoftReferenceObjectPool can grow as needed, but allows the garbage collector to evict idle instances from the pool as needed.

commons-pool-1.6-src/src/site/xdoc/issue-tracking.xml100644 0 0 13367 11701070263 20107 0ustar 0 0 Commons Pool Issue tracking Commons Documentation Team

Commons Pool uses ASF JIRA for tracking issues. See the Commons Pool 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 Commons Pool 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 Commons Pool 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-pool-1.6-src/src/site/xdoc/mail-lists.xml100644 0 0 22532 11701070263 17227 0ustar 0 0 Commons Pool Mailing Lists Commons Documentation Team

Commons Pool 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:

  • [pool] Problem with the ...

Questions related to the usage of Commons Pool should be posted to the User List.
The Developer List is for questions and discussion related to the development of Commons Pool.
Please do not cross-post; developers are also subscribed to the user list.

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 Commons Pool with [pool] - thanks!

Name Subscribe Unsubscribe Post Archive Other Archives
Commons User List

Questions on using Commons Pool.

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

Discussion of development of Commons Pool.

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-pool-1.6-src/src/template/pool-release-notes.vm100644 0 0 6205 11701070263 20401 0ustar 0 0 ## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ## KIND, either express or implied. See the License for the ## specific language governing permissions and limitations ## under the License. ${finalName} RELEASE NOTES ${release.description} #if ($release.getActions().size() == 0) No changes defined in this version. #else Changes in this version include: #if ($release.getActions('add').size() !=0) New features: #foreach($actionItem in $release.getActions('add')) #set($action=$actionItem.getAction()) #if ($actionItem.getIssue()) #set($issue=$actionItem.getIssue()) #else #set($issue="") #end #if ($actionItem.getDueTo()) #set($dueto=$actionItem.getDueTo()) #else #set($dueto="") #end o #if($!issue != "") $issue: #end ${action} #if($!dueto != "")Thanks to $dueto. #end #set($issue="") #set($dueto="") #end #end #if ($release.getActions('fix').size() !=0) Fixed Bugs: #foreach($actionItem in $release.getActions('fix')) #set($action=$actionItem.getAction()) #if ($actionItem.getIssue()) #set($issue=$actionItem.getIssue()) #else #set($issue="") #end #if ($actionItem.getDueTo()) #set($dueto=$actionItem.getDueTo()) #else #set($dueto="") #end o #if($!issue != "") $issue: #end ${action} #if($!dueto != "")Thanks to $dueto. #end #set($issue="") #set($dueto="") #end #end #if ($release.getActions('update').size() !=0) Changes: #foreach($actionItem in $release.getActions('update')) #set($action=$actionItem.getAction()) #if ($actionItem.getIssue()) #set($issue=$actionItem.getIssue()) #else #set($issue="") #end #if ($actionItem.getDueTo()) #set($dueto=$actionItem.getDueTo()) #else #set($dueto="") #end o #if($!issue != "") $issue: #end ${action} #if($!dueto != "")Thanks to $dueto. #end #set($issue="") #set($dueto="") #end #end #if ($release.getActions('remove').size() !=0) Removed: #foreach($actionItem in $release.getActions('remove')) #set($action=$actionItem.getAction()) #if ($actionItem.getIssue()) #set($issue=$actionItem.getIssue()) #else #set($issue="") #end #if ($actionItem.getDueTo()) #set($dueto=$actionItem.getDueTo()) #else #set($dueto="") #end o ${action} #if($!issue != "") Issue: $issue. #end#if($!dueto != "")Thanks to $dueto. #end #set($issue="") #set($dueto="") #end #end ## End of main loop #end For complete information on commons-pool, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the commons-pool website: http://commons.apache.org/pool/ commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java100644 0 0 223403 11701070262 27143 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.io.PrintWriter; import java.io.StringWriter; import java.util.HashMap; import java.util.NoSuchElementException; import java.util.Random; import org.apache.commons.pool.KeyedObjectPool; import org.apache.commons.pool.KeyedPoolableObjectFactory; import org.apache.commons.pool.TestBaseKeyedObjectPool; import org.apache.commons.pool.VisitTracker; import org.apache.commons.pool.VisitTrackerFactory; import org.apache.commons.pool.Waiter; import org.apache.commons.pool.WaiterFactory; /** * @author Rodney Waldhoff * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestGenericKeyedObjectPool extends TestBaseKeyedObjectPool { public TestGenericKeyedObjectPool(String testName) { super(testName); } @Override protected KeyedObjectPool makeEmptyPool(int mincapacity) { GenericKeyedObjectPool pool = new GenericKeyedObjectPool( new KeyedPoolableObjectFactory() { HashMap map = new HashMap(); public String makeObject(Object key) { int counter = 0; Integer Counter = map.get(key); if(null != Counter) { counter = Counter.intValue(); } map.put(key,new Integer(counter + 1)); return String.valueOf(key) + String.valueOf(counter); } public void destroyObject(Object key, String obj) { } public boolean validateObject(Object key, String obj) { return true; } public void activateObject(Object key, String obj) { } public void passivateObject(Object key, String obj) { } } ); pool.setMaxActive(mincapacity); pool.setMaxIdle(mincapacity); return pool; } @Override protected KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory) { return new GenericKeyedObjectPool(factory); } @Override protected String getNthObject(Object key, int n) { return String.valueOf(key) + String.valueOf(n); } @Override protected Object makeKey(int n) { return String.valueOf(n); } private GenericKeyedObjectPool pool = null; private final Integer zero = new Integer(0); private final Integer one = new Integer(1); private final Integer two = new Integer(2); @Override public void setUp() throws Exception { super.setUp(); pool = new GenericKeyedObjectPool(new SimpleFactory()); } @Override public void tearDown() throws Exception { super.tearDown(); pool.clear(); pool.close(); pool = null; } public void testNegativeMaxActive() throws Exception { pool.setMaxActive(-1); pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL); String obj = pool.borrowObject(""); assertEquals("0",obj); pool.returnObject("",obj); } public void testNumActiveNumIdle2() throws Exception { assertEquals(0,pool.getNumActive()); assertEquals(0,pool.getNumIdle()); assertEquals(0,pool.getNumActive("A")); assertEquals(0,pool.getNumIdle("A")); assertEquals(0,pool.getNumActive("B")); assertEquals(0,pool.getNumIdle("B")); String objA0 = pool.borrowObject("A"); String objB0 = pool.borrowObject("B"); assertEquals(2,pool.getNumActive()); assertEquals(0,pool.getNumIdle()); assertEquals(1,pool.getNumActive("A")); assertEquals(0,pool.getNumIdle("A")); assertEquals(1,pool.getNumActive("B")); assertEquals(0,pool.getNumIdle("B")); String objA1 = pool.borrowObject("A"); String objB1 = pool.borrowObject("B"); assertEquals(4,pool.getNumActive()); assertEquals(0,pool.getNumIdle()); assertEquals(2,pool.getNumActive("A")); assertEquals(0,pool.getNumIdle("A")); assertEquals(2,pool.getNumActive("B")); assertEquals(0,pool.getNumIdle("B")); pool.returnObject("A",objA0); pool.returnObject("B",objB0); assertEquals(2,pool.getNumActive()); assertEquals(2,pool.getNumIdle()); assertEquals(1,pool.getNumActive("A")); assertEquals(1,pool.getNumIdle("A")); assertEquals(1,pool.getNumActive("B")); assertEquals(1,pool.getNumIdle("B")); pool.returnObject("A",objA1); pool.returnObject("B",objB1); assertEquals(0,pool.getNumActive()); assertEquals(4,pool.getNumIdle()); assertEquals(0,pool.getNumActive("A")); assertEquals(2,pool.getNumIdle("A")); assertEquals(0,pool.getNumActive("B")); assertEquals(2,pool.getNumIdle("B")); } public void testMaxIdle() throws Exception { pool.setMaxActive(100); pool.setMaxIdle(8); String[] active = new String[100]; for(int i=0;i<100;i++) { active[i] = pool.borrowObject(""); } assertEquals(100,pool.getNumActive("")); assertEquals(0,pool.getNumIdle("")); for(int i=0;i<100;i++) { pool.returnObject("",active[i]); assertEquals(99 - i,pool.getNumActive("")); assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle("")); } for(int i=0;i<100;i++) { active[i] = pool.borrowObject("a"); } assertEquals(100,pool.getNumActive("a")); assertEquals(0,pool.getNumIdle("a")); for(int i=0;i<100;i++) { pool.returnObject("a",active[i]); assertEquals(99 - i,pool.getNumActive("a")); assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle("a")); } // total number of idle instances is twice maxIdle assertEquals(16, pool.getNumIdle()); // Each pool is at the sup assertEquals(8, pool.getNumIdle("")); assertEquals(8, pool.getNumIdle("a")); } public void testMaxActive() throws Exception { pool.setMaxActive(3); pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL); pool.borrowObject(""); pool.borrowObject(""); pool.borrowObject(""); try { pool.borrowObject(""); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } } public void testMaxActiveZero() throws Exception { pool.setMaxActive(0); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); try { pool.borrowObject("a"); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } } public void testWhenExhaustedGrow() throws Exception { pool.setMaxActive(1); pool.setMaxTotal(1); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW); for (int i = 0; i < 10; i++) { pool.borrowObject("a"); } } public void testWhenExhaustedBlockClosePool() throws Exception { pool.setMaxActive(1); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); pool.setMaxWait(0); Object obj1 = pool.borrowObject("a"); // Make sure an object was obtained assertNotNull(obj1); // Create a separate thread to try and borrow another object WaitingTestThread wtt = new WaitingTestThread(pool, "a", 200); wtt.start(); // Give wtt time to start Thread.sleep(200); // close the pool (Bug POOL-189) pool.close(); // Give interrupt time to take effect Thread.sleep(200); // Check thread was interrupted assertTrue(wtt._thrown instanceof IllegalStateException); } public void testMaxTotal() throws Exception { pool.setMaxActive(2); pool.setMaxTotal(3); pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL); String o1 = pool.borrowObject("a"); assertNotNull(o1); String o2 = pool.borrowObject("a"); assertNotNull(o2); String o3 = pool.borrowObject("b"); assertNotNull(o3); try { pool.borrowObject("c"); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } assertEquals(0, pool.getNumIdle()); pool.returnObject("b", o3); assertEquals(1, pool.getNumIdle()); assertEquals(1, pool.getNumIdle("b")); Object o4 = pool.borrowObject("b"); assertNotNull(o4); assertEquals(0, pool.getNumIdle()); assertEquals(0, pool.getNumIdle("b")); pool.setMaxTotal(4); Object o5 = pool.borrowObject("b"); assertNotNull(o5); assertEquals(2, pool.getNumActive("a")); assertEquals(2, pool.getNumActive("b")); assertEquals(pool.getMaxTotal(), pool.getNumActive("b") + pool.getNumActive("b")); assertEquals(pool.getNumActive(), pool.getMaxTotal()); } public void testMaxTotalZero() throws Exception { pool.setMaxTotal(0); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); try { pool.borrowObject("a"); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } } public void testMaxTotalLRU() throws Exception { pool.setMaxActive(2); pool.setMaxTotal(3); // pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW); String o1 = pool.borrowObject("a"); assertNotNull(o1); pool.returnObject("a", o1); Thread.sleep(25); String o2 = pool.borrowObject("b"); assertNotNull(o2); pool.returnObject("b", o2); Thread.sleep(25); String o3 = pool.borrowObject("c"); assertNotNull(o3); pool.returnObject("c", o3); Thread.sleep(25); String o4 = pool.borrowObject("a"); assertNotNull(o4); pool.returnObject("a", o4); Thread.sleep(25); assertSame(o1, o4); // this should cause b to be bumped out of the pool String o5 = pool.borrowObject("d"); assertNotNull(o5); pool.returnObject("d", o5); Thread.sleep(25); // now re-request b, we should get a different object because it should // have been expelled from pool (was oldest because a was requested after b) String o6 = pool.borrowObject("b"); assertNotNull(o6); pool.returnObject("b", o6); assertNotSame(o1, o6); // second a is still in there String o7 = pool.borrowObject("a"); assertNotNull(o7); pool.returnObject("a", o7); assertSame(o4, o7); } public void testSettersAndGetters() throws Exception { GenericKeyedObjectPool pool = new GenericKeyedObjectPool(); { pool.setFactory(new SimpleFactory()); } { pool.setMaxActive(123); assertEquals(123,pool.getMaxActive()); } { pool.setMaxIdle(12); assertEquals(12,pool.getMaxIdle()); } { pool.setMaxWait(1234L); assertEquals(1234L,pool.getMaxWait()); } { pool.setMinEvictableIdleTimeMillis(12345L); assertEquals(12345L,pool.getMinEvictableIdleTimeMillis()); } { pool.setNumTestsPerEvictionRun(11); assertEquals(11,pool.getNumTestsPerEvictionRun()); } { pool.setTestOnBorrow(true); assertTrue(pool.getTestOnBorrow()); pool.setTestOnBorrow(false); assertTrue(!pool.getTestOnBorrow()); } { pool.setTestOnReturn(true); assertTrue(pool.getTestOnReturn()); pool.setTestOnReturn(false); assertTrue(!pool.getTestOnReturn()); } { pool.setTestWhileIdle(true); assertTrue(pool.getTestWhileIdle()); pool.setTestWhileIdle(false); assertTrue(!pool.getTestWhileIdle()); } { pool.setTimeBetweenEvictionRunsMillis(11235L); assertEquals(11235L,pool.getTimeBetweenEvictionRunsMillis()); } { pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK,pool.getWhenExhaustedAction()); pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_FAIL,pool.getWhenExhaustedAction()); pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW,pool.getWhenExhaustedAction()); } } public void testEviction() throws Exception { pool.setMaxIdle(500); pool.setMaxActive(500); pool.setNumTestsPerEvictionRun(100); pool.setMinEvictableIdleTimeMillis(250L); pool.setTimeBetweenEvictionRunsMillis(500L); String[] active = new String[500]; for(int i=0;i<500;i++) { active[i] = pool.borrowObject(""); } for(int i=0;i<500;i++) { pool.returnObject("",active[i]); } try { Thread.sleep(1000L); } catch(InterruptedException e) { } assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 500); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 400); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 300); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 200); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 100); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertEquals("Should be zero idle, found " + pool.getNumIdle(""),0,pool.getNumIdle("")); for(int i=0;i<500;i++) { active[i] = pool.borrowObject(""); } for(int i=0;i<500;i++) { pool.returnObject("",active[i]); } try { Thread.sleep(1000L); } catch(InterruptedException e) { } assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 500); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 400); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 300); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 200); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 100); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertEquals("Should be zero idle, found " + pool.getNumIdle(""),0,pool.getNumIdle("")); } public void testEviction2() throws Exception { pool.setMaxIdle(500); pool.setMaxActive(500); pool.setNumTestsPerEvictionRun(100); pool.setMinEvictableIdleTimeMillis(500L); pool.setTimeBetweenEvictionRunsMillis(500L); String[] active = new String[500]; String[] active2 = new String[500]; for(int i=0;i<500;i++) { active[i] = pool.borrowObject(""); active2[i] = pool.borrowObject("2"); } for(int i=0;i<500;i++) { pool.returnObject("",active[i]); pool.returnObject("2",active2[i]); } try { Thread.sleep(1100L); } catch(InterruptedException e) { } assertTrue("Should be less than 1000 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 1000); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 900 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 900); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 800 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 800); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 700 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 700); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 600 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 600); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle()); } /** * Kicks off test threads, each of which will go through * borrow-return cycles with random delay times <= delay * in between. */ public void runTestThreads(GenericKeyedObjectPool pool, int numThreads, int iterations, int delay) { @SuppressWarnings("unchecked") TestThread[] threads = new TestThread[numThreads]; for(int i=0;i(pool,iterations,delay); Thread t = new Thread(threads[i]); t.start(); } for(int i=0;i factory = new SimpleFactory(); factory.setEvenValid(false); // Every other validation fails factory.setDestroyLatency(100); // Destroy takes 100 ms factory.setMaxActive(maxTotal); // (makes - destroys) bound factory.setValidationEnabled(true); pool = new GenericKeyedObjectPool(factory); pool.setMaxTotal(maxTotal); pool.setMaxIdle(-1); pool.setTestOnReturn(true); pool.setMaxWait(10000L); runTestThreads(pool, 5, 10, 50); } public void testMinIdle() throws Exception { pool.setMaxIdle(500); pool.setMinIdle(5); pool.setMaxActive(10); pool.setNumTestsPerEvictionRun(0); pool.setMinEvictableIdleTimeMillis(50L); pool.setTimeBetweenEvictionRunsMillis(100L); pool.setTestWhileIdle(true); //Generate a random key String key = "A"; pool.preparePool(key, true); try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); String[] active = new String[5]; active[0] = pool.borrowObject(key); try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); for(int i=1 ; i<5 ; i++) { active[i] = pool.borrowObject(key); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); for(int i=0 ; i<5 ; i++) { pool.returnObject(key, active[i]); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10); } public void testMinIdleMaxActive() throws Exception { pool.setMaxIdle(500); pool.setMinIdle(5); pool.setMaxActive(10); pool.setNumTestsPerEvictionRun(0); pool.setMinEvictableIdleTimeMillis(50L); pool.setTimeBetweenEvictionRunsMillis(100L); pool.setTestWhileIdle(true); String key = "A"; pool.preparePool(key, true); assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); String[] active = new String[10]; try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); for(int i=0 ; i<5 ; i++) { active[i] = pool.borrowObject(key); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); for(int i=0 ; i<5 ; i++) { pool.returnObject(key, active[i]); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10); for(int i=0 ; i<10 ; i++) { active[i] = pool.borrowObject(key); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0); for(int i=0 ; i<10 ; i++) { pool.returnObject(key, active[i]); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10); } public void testMinIdleNoPopulateImmediately() throws Exception { pool.setMaxIdle(500); pool.setMinIdle(5); pool.setMaxActive(10); pool.setNumTestsPerEvictionRun(0); pool.setMinEvictableIdleTimeMillis(50L); pool.setTimeBetweenEvictionRunsMillis(1000L); pool.setTestWhileIdle(true); //Generate a random key String key = "A"; pool.preparePool(key, false); assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0); try { Thread.sleep(1500L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); } public void testMinIdleNoPreparePool() throws Exception { pool.setMaxIdle(500); pool.setMinIdle(5); pool.setMaxActive(10); pool.setNumTestsPerEvictionRun(0); pool.setMinEvictableIdleTimeMillis(50L); pool.setTimeBetweenEvictionRunsMillis(100L); pool.setTestWhileIdle(true); //Generate a random key String key = "A"; try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0); Object active = pool.borrowObject(key); assertNotNull(active); try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); } public void testFIFO() throws Exception { pool.setLifo(false); final String key = "key"; pool.addObject(key); // "key0" pool.addObject(key); // "key1" pool.addObject(key); // "key2" assertEquals("Oldest", "key0", pool.borrowObject(key)); assertEquals("Middle", "key1", pool.borrowObject(key)); assertEquals("Youngest", "key2", pool.borrowObject(key)); assertEquals("new-3", "key3", pool.borrowObject(key)); pool.returnObject(key, "r"); assertEquals("returned", "r", pool.borrowObject(key)); assertEquals("new-4", "key4", pool.borrowObject(key)); } public void testLIFO() throws Exception { pool.setLifo(true); final String key = "key"; pool.addObject(key); // "key0" pool.addObject(key); // "key1" pool.addObject(key); // "key2" assertEquals("Youngest", "key2", pool.borrowObject(key)); assertEquals("Middle", "key1", pool.borrowObject(key)); assertEquals("Oldest", "key0", pool.borrowObject(key)); assertEquals("new-3", "key3", pool.borrowObject(key)); pool.returnObject(key, "r"); assertEquals("returned", "r", pool.borrowObject(key)); assertEquals("new-4", "key4", pool.borrowObject(key)); } /** * Test to make sure evictor visits least recently used objects first, * regardless of FIFO/LIFO * * JIRA: POOL-86 */ public void testEvictionOrder() throws Exception { checkEvictionOrder(false); checkEvictionOrder(true); } private void checkEvictionOrder(boolean lifo) throws Exception { SimpleFactory factory = new SimpleFactory(); GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); pool.setNumTestsPerEvictionRun(2); pool.setMinEvictableIdleTimeMillis(100); pool.setLifo(lifo); for (int i = 0; i < 3; i ++) { Integer key = new Integer(i); for (int j = 0; j < 5; j++) { pool.addObject(key); } } // Make all evictable Thread.sleep(200); /* * Initial state (Key, Object) pairs in order of age: * * (0,0), (0,1), (0,2), (0,3), (0,4) * (1,5), (1,6), (1,7), (1,8), (1,9) * (2,10), (2,11), (2,12), (2,13), (2,14) */ pool.evict(); // Kill (0,0),(0,1) assertEquals(3, pool.getNumIdle(zero)); String objZeroA = pool.borrowObject(zero); assertTrue(lifo ? objZeroA.equals("04") : objZeroA.equals("02")); assertEquals(2, pool.getNumIdle(zero)); String objZeroB = pool.borrowObject(zero); assertTrue(objZeroB.equals("03")); assertEquals(1, pool.getNumIdle(zero)); pool.evict(); // Kill remaining 0 survivor and (1,5) assertEquals(0, pool.getNumIdle(zero)); assertEquals(4, pool.getNumIdle(one)); String objOneA = pool.borrowObject(one); assertTrue(lifo ? objOneA.equals("19") : objOneA.equals("16")); assertEquals(3, pool.getNumIdle(one)); String objOneB = pool.borrowObject(one); assertTrue(lifo ? objOneB.equals("18") : objOneB.equals("17")); assertEquals(2, pool.getNumIdle(one)); pool.evict(); // Kill remaining 1 survivors assertEquals(0, pool.getNumIdle(one)); pool.evict(); // Kill (2,10), (2,11) assertEquals(3, pool.getNumIdle(two)); String objTwoA = pool.borrowObject(two); assertTrue(lifo ? objTwoA.equals("214") : objTwoA.equals("212")); assertEquals(2, pool.getNumIdle(two)); pool.evict(); // All dead now assertEquals(0, pool.getNumIdle(two)); pool.evict(); // Should do nothing - make sure no exception // Currently 2 zero, 2 one and 1 two active. Return them pool.returnObject(zero, objZeroA); pool.returnObject(zero, objZeroB); pool.returnObject(one, objOneA); pool.returnObject(one, objOneB); pool.returnObject(two, objTwoA); // Remove all idle objects pool.clear(); // Reload pool.setMinEvictableIdleTimeMillis(500); factory.counter = 0; // Reset counter for (int i = 0; i < 3; i ++) { Integer key = new Integer(i); for (int j = 0; j < 5; j++) { pool.addObject(key); } Thread.sleep(200); } // 0's are evictable, others not pool.evict(); // Kill (0,0),(0,1) assertEquals(3, pool.getNumIdle(zero)); pool.evict(); // Kill (0,2),(0,3) assertEquals(1, pool.getNumIdle(zero)); pool.evict(); // Kill (0,4), leave (1,5) assertEquals(0, pool.getNumIdle(zero)); assertEquals(5, pool.getNumIdle(one)); assertEquals(5, pool.getNumIdle(two)); pool.evict(); // (1,6), (1,7) assertEquals(5, pool.getNumIdle(one)); assertEquals(5, pool.getNumIdle(two)); pool.evict(); // (1,8), (1,9) assertEquals(5, pool.getNumIdle(one)); assertEquals(5, pool.getNumIdle(two)); pool.evict(); // (2,10), (2,11) assertEquals(5, pool.getNumIdle(one)); assertEquals(5, pool.getNumIdle(two)); pool.evict(); // (2,12), (2,13) assertEquals(5, pool.getNumIdle(one)); assertEquals(5, pool.getNumIdle(two)); pool.evict(); // (2,14), (1,5) assertEquals(5, pool.getNumIdle(one)); assertEquals(5, pool.getNumIdle(two)); Thread.sleep(200); // Ones now timed out pool.evict(); // kill (1,6), (1,7) - (1,5) missed assertEquals(3, pool.getNumIdle(one)); assertEquals(5, pool.getNumIdle(two)); Object obj = pool.borrowObject(one); if (lifo) { assertEquals("19", obj); } else { assertEquals("15", obj); } } /** * Verifies that the evictor visits objects in expected order * and frequency. */ public void testEvictorVisiting() throws Exception { checkEvictorVisiting(true); checkEvictorVisiting(false); } private void checkEvictorVisiting(boolean lifo) throws Exception { VisitTrackerFactory factory = new VisitTrackerFactory(); GenericKeyedObjectPool> pool = new GenericKeyedObjectPool>(factory); pool.setNumTestsPerEvictionRun(2); pool.setMinEvictableIdleTimeMillis(-1); pool.setTestWhileIdle(true); pool.setLifo(lifo); pool.setTestOnReturn(false); pool.setTestOnBorrow(false); for (int i = 0; i < 3; i ++) { factory.resetId(); Integer key = new Integer(i); for (int j = 0; j < 8; j++) { pool.addObject(key); } } pool.evict(); // Visit oldest 2 - 00 and 01 VisitTracker obj = pool.borrowObject(zero); pool.returnObject(zero, obj); obj = pool.borrowObject(zero); pool.returnObject(zero, obj); // borrow, return, borrow, return // FIFO will move 0 and 1 to end - 2,3,4,5,6,7,0,1 // LIFO, 7 out, then in, then out, then in - 7,6,5,4,3,2,1,0 pool.evict(); // Should visit 02 and 03 in either case for (int i = 0; i < 8; i++) { VisitTracker tracker = pool.borrowObject(zero); if (tracker.getId() >= 4) { assertEquals("Unexpected instance visited " + tracker.getId(), 0, tracker.getValidateCount()); } else { assertEquals("Instance " + tracker.getId() + " visited wrong number of times.", 1, tracker.getValidateCount()); } } // 0's are all out pool.setNumTestsPerEvictionRun(3); pool.evict(); // 10, 11, 12 pool.evict(); // 13, 14, 15 obj = pool.borrowObject(one); pool.returnObject(one, obj); obj = pool.borrowObject(one); pool.returnObject(one, obj); obj = pool.borrowObject(one); pool.returnObject(one, obj); // borrow, return, borrow, return // FIFO 3,4,5,^,6,7,0,1,2 // LIFO 7,6,^,5,4,3,2,1,0 // In either case, pointer should be at 6 pool.evict(); // LIFO - 16, 17, 20 // FIFO - 16, 17, 10 pool.evict(); // LIFO - 21, 22, 23 // FIFO - 11, 12, 20 pool.evict(); // LIFO - 24, 25, 26 // FIFO - 21, 22, 23 pool.evict(); // LIFO - 27, skip, 10 // FIFO - 24, 25, 26 for (int i = 0; i < 8; i++) { VisitTracker tracker = pool.borrowObject(one); if ((lifo && tracker.getId() > 0) || (!lifo && tracker.getId() > 2)) { assertEquals("Instance " + tracker.getId() + " visited wrong number of times.", 1, tracker.getValidateCount()); } else { assertEquals("Instance " + tracker.getId() + " visited wrong number of times.", 2, tracker.getValidateCount()); } } // Randomly generate some pools with random numTests // and make sure evictor cycles through elements appropriately int[] smallPrimes = {2, 3, 5, 7}; Random random = new Random(); random.setSeed(System.currentTimeMillis()); pool.setMaxIdle(-1); for (int i = 0; i < smallPrimes.length; i++) { pool.setNumTestsPerEvictionRun(smallPrimes[i]); for (int j = 0; j < 5; j++) {// Try the tests a few times pool.clear(); assertEquals("NumIdle should be zero after clearing the pool",0,pool.getNumIdle()); int zeroLength = 10 + random.nextInt(20); for (int k = 0; k < zeroLength; k++) { pool.addObject(zero); } int oneLength = 10 + random.nextInt(20); for (int k = 0; k < oneLength; k++) { pool.addObject(one); } int twoLength = 10 + random.nextInt(20); for (int k = 0; k < twoLength; k++) { pool.addObject(two); } // Choose a random number of evictor runs int runs = 10 + random.nextInt(50); for (int k = 0; k < runs; k++) { pool.evict(); } // Total instances in pool int totalInstances = zeroLength + oneLength + twoLength; // Number of times evictor should have cycled through pools int cycleCount = (runs * pool.getNumTestsPerEvictionRun()) / totalInstances; // Look at elements and make sure they are visited cycleCount // or cycleCount + 1 times VisitTracker tracker = null; int visitCount = 0; for (int k = 0; k < zeroLength; k++) { tracker = pool.borrowObject(zero); visitCount = tracker.getValidateCount(); if (visitCount < cycleCount || visitCount > cycleCount + 1){ fail(formatSettings("ZERO", "runs", runs, "lifo", lifo, "i", i, "j", j, "k", k, "visitCount", visitCount, "cycleCount", cycleCount, "totalInstances", totalInstances, zeroLength, oneLength, twoLength)); } } for (int k = 0; k < oneLength; k++) { tracker = pool.borrowObject(one); visitCount = tracker.getValidateCount(); if (visitCount < cycleCount || visitCount > cycleCount + 1){ fail(formatSettings("ONE", "runs", runs, "lifo", lifo, "i", i, "j", j, "k", k, "visitCount", visitCount, "cycleCount", cycleCount, "totalInstances", totalInstances, zeroLength, oneLength, twoLength)); } } int visits[] = new int[twoLength]; for (int k = 0; k < twoLength; k++) { tracker = pool.borrowObject(two); visitCount = tracker.getValidateCount(); visits[k] = visitCount; if (visitCount < cycleCount || visitCount > cycleCount + 1){ StringBuffer sb = new StringBuffer("Visits:"); for (int l = 0; l <= k; l++){ sb.append(visits[l]).append(' '); } fail(formatSettings("TWO "+sb.toString(), "runs", runs, "lifo", lifo, "i", i, "j", j, "k", k, "visitCount", visitCount, "cycleCount", cycleCount, "totalInstances", totalInstances, zeroLength, oneLength, twoLength)); } } } } } public void testConstructors() { // Make constructor arguments all different from defaults int maxActive = 1; int maxIdle = 2; long maxWait = 3; int minIdle = 4; int maxTotal = 5; long minEvictableIdleTimeMillis = 6; int numTestsPerEvictionRun = 7; boolean testOnBorrow = true; boolean testOnReturn = true; boolean testWhileIdle = true; long timeBetweenEvictionRunsMillis = 8; byte whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; boolean lifo = false; GenericKeyedObjectPool pool = new GenericKeyedObjectPool(); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE, pool.getMaxActive()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_WAIT, pool.getMaxWait()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, pool.getMinEvictableIdleTimeMillis()); assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, pool.getNumTestsPerEvictionRun()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW, pool.getTestOnBorrow()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN, pool.getTestOnReturn()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, pool.getTestWhileIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION, pool.getWhenExhaustedAction()); assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); GenericKeyedObjectPool.Config config = new GenericKeyedObjectPool.Config(); config.lifo = lifo; config.maxActive = maxActive; config.maxIdle = maxIdle; config.minIdle = minIdle; config.maxTotal = maxTotal; config.maxWait = maxWait; config.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; config.numTestsPerEvictionRun = numTestsPerEvictionRun; config.testOnBorrow = testOnBorrow; config.testOnReturn = testOnReturn; config.testWhileIdle = testWhileIdle; config.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; config.whenExhaustedAction = whenExhaustedAction; pool = new GenericKeyedObjectPool(null, config); assertEquals(maxActive, pool.getMaxActive()); assertEquals(maxIdle, pool.getMaxIdle()); assertEquals(maxWait, pool.getMaxWait()); assertEquals(minIdle, pool.getMinIdle()); assertEquals(maxTotal, pool.getMaxTotal()); assertEquals(minEvictableIdleTimeMillis, pool.getMinEvictableIdleTimeMillis()); assertEquals(numTestsPerEvictionRun, pool.getNumTestsPerEvictionRun()); assertEquals(testOnBorrow,pool.getTestOnBorrow()); assertEquals(testOnReturn,pool.getTestOnReturn()); assertEquals(testWhileIdle,pool.getTestWhileIdle()); assertEquals(timeBetweenEvictionRunsMillis, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); assertEquals(lifo, pool.getLifo()); pool = new GenericKeyedObjectPool(null, maxActive); assertEquals(maxActive, pool.getMaxActive()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_WAIT, pool.getMaxWait()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, pool.getMinEvictableIdleTimeMillis()); assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, pool.getNumTestsPerEvictionRun()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW, pool.getTestOnBorrow()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN, pool.getTestOnReturn()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, pool.getTestWhileIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION, pool.getWhenExhaustedAction()); assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, maxWait); assertEquals(maxActive, pool.getMaxActive()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle()); assertEquals(maxWait, pool.getMaxWait()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, pool.getMinEvictableIdleTimeMillis()); assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, pool.getNumTestsPerEvictionRun()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW, pool.getTestOnBorrow()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN, pool.getTestOnReturn()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, pool.getTestWhileIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, maxWait, testOnBorrow, testOnReturn); assertEquals(maxActive, pool.getMaxActive()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_IDLE, pool.getMaxIdle()); assertEquals(maxWait, pool.getMaxWait()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, pool.getMinEvictableIdleTimeMillis()); assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, pool.getNumTestsPerEvictionRun()); assertEquals(testOnBorrow,pool.getTestOnBorrow()); assertEquals(testOnReturn,pool.getTestOnReturn()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, pool.getTestWhileIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, maxWait, maxIdle); assertEquals(maxActive, pool.getMaxActive()); assertEquals(maxIdle, pool.getMaxIdle()); assertEquals(maxWait, pool.getMaxWait()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, pool.getMinEvictableIdleTimeMillis()); assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, pool.getNumTestsPerEvictionRun()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW, pool.getTestOnBorrow()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN, pool.getTestOnReturn()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, pool.getTestWhileIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, maxWait, maxIdle, testOnBorrow, testOnReturn); assertEquals(maxActive, pool.getMaxActive()); assertEquals(maxIdle, pool.getMaxIdle()); assertEquals(maxWait, pool.getMaxWait()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, pool.getMinEvictableIdleTimeMillis()); assertEquals(GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, pool.getNumTestsPerEvictionRun()); assertEquals(testOnBorrow, pool.getTestOnBorrow()); assertEquals(testOnReturn, pool.getTestOnReturn()); assertEquals(GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE, pool.getTestWhileIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, maxWait, maxIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle); assertEquals(maxActive, pool.getMaxActive()); assertEquals(maxIdle, pool.getMaxIdle()); assertEquals(maxWait, pool.getMaxWait()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); assertEquals(GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, pool.getMaxTotal()); assertEquals(minEvictableIdleTimeMillis, pool.getMinEvictableIdleTimeMillis()); assertEquals(numTestsPerEvictionRun, pool.getNumTestsPerEvictionRun()); assertEquals(testOnBorrow, pool.getTestOnBorrow()); assertEquals(testOnReturn, pool.getTestOnReturn()); assertEquals(testWhileIdle, pool.getTestWhileIdle()); assertEquals(timeBetweenEvictionRunsMillis, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle); assertEquals(maxActive, pool.getMaxActive()); assertEquals(maxIdle, pool.getMaxIdle()); assertEquals(maxWait, pool.getMaxWait()); assertEquals(GenericKeyedObjectPool.DEFAULT_MIN_IDLE, pool.getMinIdle()); assertEquals(maxTotal, pool.getMaxTotal()); assertEquals(minEvictableIdleTimeMillis, pool.getMinEvictableIdleTimeMillis()); assertEquals(numTestsPerEvictionRun, pool.getNumTestsPerEvictionRun()); assertEquals(testOnBorrow, pool.getTestOnBorrow()); assertEquals(testOnReturn, pool.getTestOnReturn()); assertEquals(testWhileIdle, pool.getTestWhileIdle()); assertEquals(timeBetweenEvictionRunsMillis, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle); assertEquals(maxActive, pool.getMaxActive()); assertEquals(maxIdle, pool.getMaxIdle()); assertEquals(maxWait, pool.getMaxWait()); assertEquals(minIdle, pool.getMinIdle()); assertEquals(maxTotal, pool.getMaxTotal()); assertEquals(minEvictableIdleTimeMillis, pool.getMinEvictableIdleTimeMillis()); assertEquals(numTestsPerEvictionRun, pool.getNumTestsPerEvictionRun()); assertEquals(testOnBorrow, pool.getTestOnBorrow()); assertEquals(testOnReturn, pool.getTestOnReturn()); assertEquals(testWhileIdle, pool.getTestWhileIdle()); assertEquals(timeBetweenEvictionRunsMillis, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); assertEquals(GenericKeyedObjectPool.DEFAULT_LIFO, pool.getLifo()); pool = new GenericKeyedObjectPool(null, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, lifo); assertEquals(maxActive, pool.getMaxActive()); assertEquals(maxIdle, pool.getMaxIdle()); assertEquals(maxWait, pool.getMaxWait()); assertEquals(minIdle, pool.getMinIdle()); assertEquals(maxTotal, pool.getMaxTotal()); assertEquals(minEvictableIdleTimeMillis, pool.getMinEvictableIdleTimeMillis()); assertEquals(numTestsPerEvictionRun, pool.getNumTestsPerEvictionRun()); assertEquals(testOnBorrow, pool.getTestOnBorrow()); assertEquals(testOnReturn, pool.getTestOnReturn()); assertEquals(testWhileIdle, pool.getTestWhileIdle()); assertEquals(timeBetweenEvictionRunsMillis, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(whenExhaustedAction,pool.getWhenExhaustedAction()); assertEquals(lifo, pool.getLifo()); } public void testExceptionOnPassivateDuringReturn() throws Exception { SimpleFactory factory = new SimpleFactory(); GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); String obj = pool.borrowObject("one"); factory.setThrowExceptionOnPassivate(true); pool.returnObject("one", obj); assertEquals(0,pool.getNumIdle()); pool.close(); } public void testExceptionOnDestroyDuringBorrow() throws Exception { SimpleFactory factory = new SimpleFactory(); factory.setThrowExceptionOnDestroy(true); factory.setValidationEnabled(true); GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); pool.setTestOnBorrow(true); pool.borrowObject("one"); factory.setValid(false); // Make validation fail on next borrow attempt try { pool.borrowObject("one"); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException ex) { // expected } assertEquals(1, pool.getNumActive("one")); assertEquals(0, pool.getNumIdle("one")); assertEquals(1, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); } public void testExceptionOnDestroyDuringReturn() throws Exception { SimpleFactory factory = new SimpleFactory(); factory.setThrowExceptionOnDestroy(true); factory.setValidationEnabled(true); GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); pool.setTestOnReturn(true); String obj1 = pool.borrowObject("one"); pool.borrowObject("one"); factory.setValid(false); // Make validation fail pool.returnObject("one", obj1); assertEquals(1, pool.getNumActive("one")); assertEquals(0, pool.getNumIdle("one")); assertEquals(1, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); } public void testExceptionOnActivateDuringBorrow() throws Exception { SimpleFactory factory = new SimpleFactory(); GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); String obj1 = pool.borrowObject("one"); String obj2 = pool.borrowObject("one"); pool.returnObject("one", obj1); pool.returnObject("one", obj2); factory.setThrowExceptionOnActivate(true); factory.setEvenValid(false); // Activation will now throw every other time // First attempt throws, but loop continues and second succeeds String obj = pool.borrowObject("one"); assertEquals(1, pool.getNumActive("one")); assertEquals(0, pool.getNumIdle("one")); assertEquals(1, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); pool.returnObject("one", obj); factory.setValid(false); // Validation will now fail on activation when borrowObject returns // an idle instance, and then when attempting to create a new instance try { pool.borrowObject("one"); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException ex) { // expected } assertEquals(0, pool.getNumActive("one")); assertEquals(0, pool.getNumIdle("one")); assertEquals(0, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); } public void testBlockedKeyDoesNotBlockPool() throws Exception { SimpleFactory factory = new SimpleFactory(); GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); pool.setMaxWait(5000); pool.setMaxActive(1); pool.setMaxTotal(-1); pool.borrowObject("one"); long start = System.currentTimeMillis(); // Needs to be in a separate thread as this will block Runnable simple = new SimpleTestThread(pool, "one"); (new Thread(simple)).start(); // This should be almost instant. If it isn't it means this thread got // stuck behind the thread created above which is bad. // Give other thread a chance to start Thread.sleep(1000); pool.borrowObject("two"); long end = System.currentTimeMillis(); // If it fails it will be more than 4000ms (5000 less the 1000 sleep) // If it passes it should be almost instant // Use 3000ms as the threshold - should avoid timing issues on most // (all? platforms) assertTrue ("Elapsed time: "+(end-start)+" should be less than 4000",(end-start) < 4000); } private static final boolean DISPLAY_THREAD_DETAILS= Boolean.valueOf(System.getProperty("TestGenericKeyedObjectPool.display.thread.details", "false")).booleanValue(); // To pass this to a Maven test, use: // mvn test -DargLine="-DTestGenericKeyedObjectPool.display.thread.details=true" // @see http://jira.codehaus.org/browse/SUREFIRE-121 /* * Test multi-threaded pool access. * Multiple keys, multiple threads, but maxActive only allows half the threads to succeed. * * This test was prompted by Continuum build failures in the Commons DBCP test case: * TestSharedPoolDataSource.testMultipleThreads2() * Let's see if the this fails on Continuum too! */ public void testMaxWaitMultiThreaded() throws Exception { final long maxWait = 500; // wait for connection final long holdTime = 2 * maxWait; // how long to hold connection final int keyCount = 4; // number of different keys final int threadsPerKey = 5; // number of threads to grab the key initially SimpleFactory factory = new SimpleFactory(); GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); pool.setMaxWait(maxWait); pool.setMaxActive(threadsPerKey); // Create enough threads so half the threads will have to wait @SuppressWarnings("unchecked") WaitingTestThread wtt[] = new WaitingTestThread[keyCount * threadsPerKey * 2]; for(int i=0; i < wtt.length; i++){ wtt[i] = new WaitingTestThread(pool,Integer.toString(i % keyCount),holdTime); } long origin = System.currentTimeMillis()-1000; for(int i=0; i < wtt.length; i++){ wtt[i].start(); } int failed = 0; for(int i=0; i < wtt.length; i++){ wtt[i].join(); if (wtt[i]._thrown != null){ failed++; } } if (DISPLAY_THREAD_DETAILS || wtt.length/2 != failed){ System.out.println( "MaxWait: "+maxWait +" HoldTime: "+holdTime +" KeyCount: "+keyCount +" MaxActive: "+threadsPerKey +" Threads: "+wtt.length +" Failed: "+failed ); for(int i=0; i < wtt.length; i++){ WaitingTestThread wt = wtt[i]; System.out.println( "Preborrow: "+(wt.preborrow-origin) + " Postborrow: "+(wt.postborrow != 0 ? wt.postborrow-origin : -1) + " BorrowTime: "+(wt.postborrow != 0 ? wt.postborrow-wt.preborrow : -1) + " PostReturn: "+(wt.postreturn != 0 ? wt.postreturn-origin : -1) + " Ended: "+(wt.ended-origin) + " Key: "+(wt._key) + " ObjId: "+wt.objectId ); } } assertEquals("Expected half the threads to fail",wtt.length/2,failed); } /** * Test case for POOL-180. */ public void testMaxActivePerKeyExceeded() { WaiterFactory factory = new WaiterFactory(0, 20, 0, 0, 0, 0, 8, 5, 0); GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); pool.setMaxActive(5); pool.setMaxTotal(8); pool.setTestOnBorrow(true); pool.setMaxIdle(5); pool.setMaxWait(-1); runTestThreads(pool, 20, 300, 250); } /** * POOL-192 * Verify that clear(key) does not leak capacity due to _numInternalProcessing * not being decremented. */ public void testClear() throws Exception { SimpleFactory factory = new SimpleFactory(); GenericKeyedObjectPool pool = new GenericKeyedObjectPool(factory); pool.setMaxTotal(2); pool.setMaxActive(2); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); pool.addObject("one"); pool.addObject("one"); assertEquals(2, pool.getNumIdle()); pool.clear("one"); assertEquals(0, pool.getNumIdle()); assertEquals(0, pool.getNumIdle("one")); String obj1 = pool.borrowObject("one"); String obj2 = pool.borrowObject("one"); pool.returnObject("one", obj1); pool.returnObject("one", obj2); pool.clear(); assertEquals(0, pool.getNumIdle()); assertEquals(0, pool.getNumIdle("one")); pool.borrowObject("one"); pool.borrowObject("one"); pool.close(); } /* * Very simple test thread that just tries to borrow an object from * the provided pool with the specified key and returns it */ static class SimpleTestThread implements Runnable { private final KeyedObjectPool _pool; private final K _key; public SimpleTestThread(KeyedObjectPool pool, K key) { _pool = pool; _key = key; } public void run() { try { V obj = _pool.borrowObject(_key); _pool.returnObject(_key, obj); } catch (Exception e) { // Ignore } } } /* * Very simple test thread that just tries to borrow an object from * the provided pool with the specified key and returns it after a wait */ static class WaitingTestThread extends Thread { private final KeyedObjectPool _pool; private final K _key; private final long _pause; private Throwable _thrown; private long preborrow; // just before borrow private long postborrow; // borrow returned private long postreturn; // after object was returned private long ended; private String objectId; public WaitingTestThread(KeyedObjectPool pool, K key, long pause) { _pool = pool; _key = key; _pause = pause; _thrown = null; } @Override public void run() { try { preborrow = System.currentTimeMillis(); V obj = _pool.borrowObject(_key); objectId=obj.toString(); postborrow = System.currentTimeMillis(); Thread.sleep(_pause); _pool.returnObject(_key, obj); postreturn = System.currentTimeMillis(); } catch (Exception e) { _thrown = e; } finally{ ended = System.currentTimeMillis(); } } } static class TestThread implements Runnable { private final java.util.Random _random = new java.util.Random(); // Thread config items private final KeyedObjectPool _pool; private final int _iter; private final int _delay; private volatile boolean _complete = false; private volatile boolean _failed = false; private volatile Exception _exception; public TestThread(KeyedObjectPool pool) { this(pool, 100, 50); } public TestThread(KeyedObjectPool pool, int iter) { this(pool, iter, 50); } public TestThread(KeyedObjectPool pool, int iter, int delay) { _pool = pool; _iter = iter; _delay = delay; } public boolean complete() { return _complete; } public boolean failed() { return _failed; } public void run() { for(int i=0;i<_iter;i++) { String key = String.valueOf(_random.nextInt(3)); try { Thread.sleep(_random.nextInt(_delay)); } catch(InterruptedException e) { // ignored } V obj = null; try { obj = _pool.borrowObject(key); } catch(Exception e) { _exception = e; _failed = true; _complete = true; break; } try { Thread.sleep(_random.nextInt(_delay)); } catch(InterruptedException e) { // ignored } try { _pool.returnObject(key,obj); } catch(Exception e) { _exception = e; _failed = true; _complete = true; break; } } _complete = true; } } static class SimpleFactory implements KeyedPoolableObjectFactory { public SimpleFactory() { this(true); } public SimpleFactory(boolean valid) { this.valid = valid; } public String makeObject(K key) { synchronized(this) { activeCount++; if (activeCount > maxActive) { throw new IllegalStateException( "Too many active instances: " + activeCount); } } return String.valueOf(key) + String.valueOf(counter++); } public void destroyObject(K key, String obj) throws Exception { doWait(destroyLatency); synchronized(this) { activeCount--; } if (exceptionOnDestroy) { throw new Exception(); } } public boolean validateObject(K key, String obj) { if (enableValidation) { return validateCounter++%2 == 0 ? evenValid : oddValid; } else { return valid; } } public void activateObject(K key, String obj) throws Exception { if (exceptionOnActivate) { if (!(validateCounter++%2 == 0 ? evenValid : oddValid)) { throw new Exception(); } } } public void passivateObject(K key, String obj) throws Exception { if (exceptionOnPassivate) { throw new Exception(); } } public void setMaxActive(int maxActive) { this.maxActive = maxActive; } public void setDestroyLatency(long destroyLatency) { this.destroyLatency = destroyLatency; } public void setValidationEnabled(boolean b) { enableValidation = b; } void setEvenValid(boolean valid) { evenValid = valid; } void setValid(boolean valid) { evenValid = valid; oddValid = valid; } public void setThrowExceptionOnActivate(boolean b) { exceptionOnActivate = b; } public void setThrowExceptionOnDestroy(boolean b) { exceptionOnDestroy = b; } public void setThrowExceptionOnPassivate(boolean b) { exceptionOnPassivate = b; } int counter = 0; boolean valid; int activeCount = 0; int validateCounter = 0; boolean evenValid = true; boolean oddValid = true; boolean enableValidation = false; long destroyLatency = 0; int maxActive = Integer.MAX_VALUE; boolean exceptionOnPassivate = false; boolean exceptionOnActivate = false; boolean exceptionOnDestroy = false; private void doWait(long latency) { try { Thread.sleep(latency); } catch (InterruptedException ex) { // ignore } } } @Override protected boolean isLifo() { return true; } @Override protected boolean isFifo() { return false; } private String getExceptionTrace(Throwable t){ StringWriter sw = new StringWriter(); t.printStackTrace(new PrintWriter(sw)); return sw.toString(); } private String formatSettings(String title, String s, int i, String s0, boolean b0, String s1, int i1, String s2, int i2, String s3, int i3, String s4, int i4, String s5, int i5, String s6, int i6, int zeroLength, int oneLength, int twoLength){ StringBuffer sb = new StringBuffer(80); sb.append(title).append(' '); sb.append(s).append('=').append(i).append(' '); sb.append(s0).append('=').append(b0).append(' '); sb.append(s1).append('=').append(i1).append(' '); sb.append(s2).append('=').append(i2).append(' '); sb.append(s3).append('=').append(i3).append(' '); sb.append(s4).append('=').append(i4).append(' '); sb.append(s5).append('=').append(i5).append(' '); sb.append(s6).append('=').append(i6).append(' '); sb.append("Lengths=").append(zeroLength).append(',').append(oneLength).append(',').append(twoLength).append(' '); return sb.toString(); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPoolFactory.java100644 0 0 17613 11701070262 30457 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import org.apache.commons.pool.KeyedObjectPoolFactory; import org.apache.commons.pool.KeyedPoolableObjectFactory; import org.apache.commons.pool.TestKeyedObjectPoolFactory; /** * Tests for {@link GenericKeyedObjectPoolFactory}. * * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestGenericKeyedObjectPoolFactory extends TestKeyedObjectPoolFactory { public TestGenericKeyedObjectPoolFactory(final String name) { super(name); } @Override protected KeyedObjectPoolFactory makeFactory(final KeyedPoolableObjectFactory objectFactory) { return new GenericKeyedObjectPoolFactory(objectFactory); } public void testConstructors() throws Exception { GenericKeyedObjectPoolFactory factory = new GenericKeyedObjectPoolFactory(createObjectFactory()); factory.createPool().close(); GenericKeyedObjectPool pool; final GenericKeyedObjectPool.Config config = new GenericKeyedObjectPool.Config(); config.maxActive = 1; config.maxIdle = 2; config.maxWait = 3; config.minIdle = 4; config.minEvictableIdleTimeMillis = 5; config.numTestsPerEvictionRun = 6; config.testOnBorrow = true; config.testOnReturn = false; config.testWhileIdle = true; config.timeBetweenEvictionRunsMillis = 8; config.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; config.lifo = false; factory = new GenericKeyedObjectPoolFactory(createObjectFactory(), config); pool = (GenericKeyedObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxIdle()); assertEquals(3, pool.getMaxWait()); assertEquals(4, pool.getMinIdle()); assertEquals(5, pool.getMinEvictableIdleTimeMillis()); assertEquals(6, pool.getNumTestsPerEvictionRun()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(true, pool.getTestWhileIdle()); assertEquals(false, pool.getLifo()); assertEquals(8, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.close(); factory = new GenericKeyedObjectPoolFactory(createObjectFactory(), 1); pool = (GenericKeyedObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); pool.close(); factory = new GenericKeyedObjectPoolFactory(createObjectFactory(), 1, GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK, 125); pool = (GenericKeyedObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK, pool.getWhenExhaustedAction()); assertEquals(125, pool.getMaxWait()); pool.close(); factory = new GenericKeyedObjectPoolFactory(createObjectFactory(), 1, GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, 2, true, false); pool = (GenericKeyedObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.close(); factory = new GenericKeyedObjectPoolFactory(createObjectFactory(), 1, GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, 2, 3); pool = (GenericKeyedObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(3, pool.getMaxIdle()); assertEquals(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.close(); factory = new GenericKeyedObjectPoolFactory(createObjectFactory(), 1, GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, 2, 3, 4); pool = (GenericKeyedObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(3, pool.getMaxIdle()); assertEquals(4, pool.getMaxTotal()); assertEquals(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.close(); factory = new GenericKeyedObjectPoolFactory(createObjectFactory(), 1, GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, 2, 3, true, false); pool = (GenericKeyedObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(3, pool.getMaxIdle()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.close(); factory = new GenericKeyedObjectPoolFactory(createObjectFactory(), 1, GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, 2, 3, true, false, 4, 5, 6, false); pool = (GenericKeyedObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(3, pool.getMaxIdle()); assertEquals(4, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(5, pool.getNumTestsPerEvictionRun()); assertEquals(6, pool.getMinEvictableIdleTimeMillis()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(false, pool.getTestWhileIdle()); assertEquals(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.close(); factory = new GenericKeyedObjectPoolFactory(createObjectFactory(), 1, GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, 2, 3, 4, true, false, 5, 6, 7, true); pool = (GenericKeyedObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(3, pool.getMaxIdle()); assertEquals(4, pool.getMaxTotal()); assertEquals(5, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(6, pool.getNumTestsPerEvictionRun()); assertEquals(7, pool.getMinEvictableIdleTimeMillis()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(true, pool.getTestWhileIdle()); assertEquals(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.close(); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java100644 0 0 213011 11701070262 26153 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.math.BigInteger; import java.util.NoSuchElementException; import java.util.Random; import org.apache.commons.pool.BasePoolableObjectFactory; import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.PoolUtils; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.TestBaseObjectPool; import org.apache.commons.pool.VisitTracker; import org.apache.commons.pool.VisitTrackerFactory; /** * @author Rodney Waldhoff * @author Dirk Verbeeck * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestGenericObjectPool extends TestBaseObjectPool { public TestGenericObjectPool(String testName) { super(testName); } @Override protected ObjectPool makeEmptyPool(int mincap) { GenericObjectPool pool = new GenericObjectPool(new SimpleFactory()); pool.setMaxActive(mincap); pool.setMaxIdle(mincap); return pool; } @Override protected ObjectPool makeEmptyPool(final PoolableObjectFactory factory) { return new GenericObjectPool(factory); } @Override protected String getNthObject(int n) { return String.valueOf(n); } @Override public void setUp() throws Exception { super.setUp(); pool = new GenericObjectPool(new SimpleFactory()); } @Override public void tearDown() throws Exception { super.tearDown(); pool.clear(); pool.close(); pool = null; } public void testWhenExhaustedGrow() throws Exception { pool.setMaxActive(1); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW); String obj1 = pool.borrowObject(); assertNotNull(obj1); String obj2 = pool.borrowObject(); assertNotNull(obj2); pool.returnObject(obj2); pool.returnObject(obj1); pool.close(); } public void testWhenExhaustedFail() throws Exception { pool.setMaxActive(1); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); String obj1 = pool.borrowObject(); assertNotNull(obj1); try { pool.borrowObject(); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } pool.returnObject(obj1); assertEquals(1, pool.getNumIdle()); pool.close(); } public void testWhenExhaustedBlock() throws Exception { pool.setMaxActive(1); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); pool.setMaxWait(10L); String obj1 = pool.borrowObject(); assertNotNull(obj1); try { pool.borrowObject(); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } pool.returnObject(obj1); pool.close(); } public void testWhenExhaustedBlockInterupt() throws Exception { pool.setMaxActive(1); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); pool.setMaxWait(0); String obj1 = pool.borrowObject(); // Make sure an object was obtained assertNotNull(obj1); // Create a separate thread to try and borrow another object WaitingTestThread wtt = new WaitingTestThread(pool, 200); wtt.start(); // Give wtt time to start Thread.sleep(200); wtt.interrupt(); // Give interupt time to take effect Thread.sleep(200); // Check thread was interrupted assertTrue(wtt._thrown instanceof InterruptedException); // Return object to the pool pool.returnObject(obj1); // Bug POOL-162 - check there is now an object in the pool pool.setMaxWait(10L); String obj2 = null; try { obj2 = pool.borrowObject(); assertNotNull(obj2); } catch(NoSuchElementException e) { // Not expected fail("NoSuchElementException not expected"); } pool.returnObject(obj2); pool.close(); } public void testWhenExhaustedBlockClosePool() throws Exception { pool.setMaxActive(1); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); pool.setMaxWait(0); Object obj1 = pool.borrowObject(); // Make sure an object was obtained assertNotNull(obj1); // Create a separate thread to try and borrow another object WaitingTestThread wtt = new WaitingTestThread(pool, 200); wtt.start(); // Give wtt time to start Thread.sleep(200); // close the pool (Bug POOL-189) pool.close(); // Give interrupt time to take effect Thread.sleep(200); // Check thread was interrupted assertTrue(wtt._thrown instanceof IllegalStateException); } public void testEvictWhileEmpty() throws Exception { pool.evict(); pool.evict(); pool.close(); } /** * Tests addObject contention between ensureMinIdle triggered by * the Evictor with minIdle > 0 and borrowObject. */ public void testEvictAddObjects() throws Exception { SimpleFactory factory = new SimpleFactory(); factory.setMakeLatency(300); factory.setMaxActive(2); GenericObjectPool pool = new GenericObjectPool(factory); pool.setMaxActive(2); pool.setMinIdle(1); pool.borrowObject(); // numActive = 1, numIdle = 0 // Create a test thread that will run once and try a borrow after // 150ms fixed delay TestThread borrower = new TestThread(pool, 1, 150, false); Thread borrowerThread = new Thread(borrower); // Set evictor to run in 100 ms - will create idle instance pool.setTimeBetweenEvictionRunsMillis(100); borrowerThread.start(); // Off to the races borrowerThread.join(); assertTrue(!borrower.failed()); pool.close(); } public void testEvictLIFO() throws Exception { checkEvict(true); } public void testEvictFIFO() throws Exception { checkEvict(false); } public void checkEvict(boolean lifo) throws Exception { // yea this is hairy but it tests all the code paths in GOP.evict() final SimpleFactory factory = new SimpleFactory(); final GenericObjectPool pool = new GenericObjectPool(factory); pool.setSoftMinEvictableIdleTimeMillis(10); pool.setMinIdle(2); pool.setTestWhileIdle(true); pool.setLifo(lifo); PoolUtils.prefill(pool, 5); pool.evict(); factory.setEvenValid(false); factory.setOddValid(false); factory.setThrowExceptionOnActivate(true); pool.evict(); PoolUtils.prefill(pool, 5); factory.setThrowExceptionOnActivate(false); factory.setThrowExceptionOnPassivate(true); pool.evict(); factory.setThrowExceptionOnPassivate(false); factory.setEvenValid(true); factory.setOddValid(true); Thread.sleep(125); pool.evict(); assertEquals(2, pool.getNumIdle()); } /** * Test to make sure evictor visits least recently used objects first, * regardless of FIFO/LIFO * * JIRA: POOL-86 */ public void testEvictionOrder() throws Exception { checkEvictionOrder(false); checkEvictionOrder(true); } private void checkEvictionOrder(boolean lifo) throws Exception { SimpleFactory factory = new SimpleFactory(); GenericObjectPool pool = new GenericObjectPool(factory); pool.setNumTestsPerEvictionRun(2); pool.setMinEvictableIdleTimeMillis(100); pool.setLifo(lifo); for (int i = 0; i < 5; i++) { pool.addObject(); Thread.sleep(100); } // Order, oldest to youngest, is "0", "1", ...,"4" pool.evict(); // Should evict "0" and "1" Object obj = pool.borrowObject(); assertTrue("oldest not evicted", !obj.equals("0")); assertTrue("second oldest not evicted", !obj.equals("1")); // 2 should be next out for FIFO, 4 for LIFO assertEquals("Wrong instance returned", lifo ? "4" : "2" , obj); // Two eviction runs in sequence factory = new SimpleFactory(); pool = new GenericObjectPool(factory); pool.setNumTestsPerEvictionRun(2); pool.setMinEvictableIdleTimeMillis(100); pool.setLifo(lifo); for (int i = 0; i < 5; i++) { pool.addObject(); Thread.sleep(100); } pool.evict(); // Should evict "0" and "1" pool.evict(); // Should evict "2" and "3" obj = pool.borrowObject(); assertEquals("Wrong instance remaining in pool", "4", obj); } /** * Verifies that the evictor visits objects in expected order * and frequency. */ public void testEvictorVisiting() throws Exception { checkEvictorVisiting(true); checkEvictorVisiting(false); } private void checkEvictorVisiting(boolean lifo) throws Exception { VisitTrackerFactory factory = new VisitTrackerFactory(); GenericObjectPool> pool = new GenericObjectPool>(factory); pool.setNumTestsPerEvictionRun(2); pool.setMinEvictableIdleTimeMillis(-1); pool.setTestWhileIdle(true); pool.setLifo(lifo); pool.setTestOnReturn(false); pool.setTestOnBorrow(false); for (int i = 0; i < 8; i++) { pool.addObject(); } pool.evict(); // Visit oldest 2 - 0 and 1 VisitTracker obj = pool.borrowObject(); pool.returnObject(obj); obj = pool.borrowObject(); pool.returnObject(obj); // borrow, return, borrow, return // FIFO will move 0 and 1 to end // LIFO, 7 out, then in, then out, then in pool.evict(); // Should visit 2 and 3 in either case for (int i = 0; i < 8; i++) { VisitTracker tracker = pool.borrowObject(); if (tracker.getId() >= 4) { assertEquals("Unexpected instance visited " + tracker.getId(), 0, tracker.getValidateCount()); } else { assertEquals("Instance " + tracker.getId() + " visited wrong number of times.", 1, tracker.getValidateCount()); } } factory = new VisitTrackerFactory(); pool = new GenericObjectPool>(factory); pool.setNumTestsPerEvictionRun(3); pool.setMinEvictableIdleTimeMillis(-1); pool.setTestWhileIdle(true); pool.setLifo(lifo); pool.setTestOnReturn(false); pool.setTestOnBorrow(false); for (int i = 0; i < 8; i++) { pool.addObject(); } pool.evict(); // 0, 1, 2 pool.evict(); // 3, 4, 5 obj = pool.borrowObject(); pool.returnObject(obj); obj = pool.borrowObject(); pool.returnObject(obj); obj = pool.borrowObject(); pool.returnObject(obj); // borrow, return, borrow, return // FIFO 3,4,5,6,7,0,1,2 // LIFO 7,6,5,4,3,2,1,0 // In either case, pointer should be at 6 pool.evict(); // Should hit 6,7,0 - 0 for second time for (int i = 0; i < 8; i++) { VisitTracker tracker = pool.borrowObject(); if (tracker.getId() != 0) { assertEquals("Instance " + tracker.getId() + " visited wrong number of times.", 1, tracker.getValidateCount()); } else { assertEquals("Instance " + tracker.getId() + " visited wrong number of times.", 2, tracker.getValidateCount()); } } // Randomly generate a pools with random numTests // and make sure evictor cycles through elements appropriately int[] smallPrimes = {2, 3, 5, 7}; Random random = new Random(); random.setSeed(System.currentTimeMillis()); for (int i = 0; i < 4; i++) { pool.setNumTestsPerEvictionRun(smallPrimes[i]); for (int j = 0; j < 5; j++) { pool = new GenericObjectPool>(factory); pool.setNumTestsPerEvictionRun(3); pool.setMinEvictableIdleTimeMillis(-1); pool.setTestWhileIdle(true); pool.setLifo(lifo); pool.setTestOnReturn(false); pool.setTestOnBorrow(false); pool.setMaxIdle(-1); int instanceCount = 10 + random.nextInt(20); pool.setMaxActive(instanceCount); for (int k = 0; k < instanceCount; k++) { pool.addObject(); } // Execute a random number of evictor runs int runs = 10 + random.nextInt(50); for (int k = 0; k < runs; k++) { pool.evict(); } // Number of times evictor should have cycled through the pool int cycleCount = (runs * pool.getNumTestsPerEvictionRun()) / instanceCount; // Look at elements and make sure they are visited cycleCount // or cycleCount + 1 times VisitTracker tracker = null; int visitCount = 0; for (int k = 0; k < instanceCount; k++) { tracker = pool.borrowObject(); assertTrue(pool.getNumActive() <= pool.getMaxActive()); visitCount = tracker.getValidateCount(); assertTrue(visitCount >= cycleCount && visitCount <= cycleCount + 1); } } } } public void testExceptionOnPassivateDuringReturn() throws Exception { SimpleFactory factory = new SimpleFactory(); GenericObjectPool pool = new GenericObjectPool(factory); String obj = pool.borrowObject(); factory.setThrowExceptionOnPassivate(true); pool.returnObject(obj); assertEquals(0,pool.getNumIdle()); pool.close(); } public void testExceptionOnDestroyDuringBorrow() throws Exception { SimpleFactory factory = new SimpleFactory(); factory.setThrowExceptionOnDestroy(true); GenericObjectPool pool = new GenericObjectPool(factory); pool.setTestOnBorrow(true); pool.borrowObject(); factory.setValid(false); // Make validation fail on next borrow attempt try { pool.borrowObject(); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException ex) { // expected } assertEquals(1, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); } public void testExceptionOnDestroyDuringReturn() throws Exception { SimpleFactory factory = new SimpleFactory(); factory.setThrowExceptionOnDestroy(true); GenericObjectPool pool = new GenericObjectPool(factory); pool.setTestOnReturn(true); String obj1 = pool.borrowObject(); pool.borrowObject(); factory.setValid(false); // Make validation fail pool.returnObject(obj1); assertEquals(1, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); } public void testExceptionOnActivateDuringBorrow() throws Exception { SimpleFactory factory = new SimpleFactory(); GenericObjectPool pool = new GenericObjectPool(factory); String obj1 = pool.borrowObject(); String obj2 = pool.borrowObject(); pool.returnObject(obj1); pool.returnObject(obj2); factory.setThrowExceptionOnActivate(true); factory.setEvenValid(false); // Activation will now throw every other time // First attempt throws, but loop continues and second succeeds String obj = pool.borrowObject(); assertEquals(1, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); pool.returnObject(obj); factory.setValid(false); // Validation will now fail on activation when borrowObject returns // an idle instance, and then when attempting to create a new instance try { obj1 = pool.borrowObject(); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException ex) { // expected } assertEquals(0, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); } public void testSetFactoryWithActiveObjects() throws Exception { GenericObjectPool pool = new GenericObjectPool(); pool.setMaxIdle(10); pool.setFactory(new SimpleFactory()); String obj = pool.borrowObject(); assertNotNull(obj); try { pool.setFactory(null); fail("Expected IllegalStateException"); } catch(IllegalStateException e) { // expected } try { pool.setFactory(new SimpleFactory()); fail("Expected IllegalStateException"); } catch(IllegalStateException e) { // expected } } public void testSetFactoryWithNoActiveObjects() throws Exception { GenericObjectPool pool = new GenericObjectPool(); pool.setMaxIdle(10); pool.setFactory(new SimpleFactory()); String obj = pool.borrowObject(); pool.returnObject(obj); assertEquals(1,pool.getNumIdle()); pool.setFactory(new SimpleFactory()); assertEquals(0,pool.getNumIdle()); } public void testNegativeMaxActive() throws Exception { pool.setMaxActive(-1); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); String obj = pool.borrowObject(); assertEquals(getNthObject(0),obj); pool.returnObject(obj); } public void testMaxIdle() throws Exception { pool.setMaxActive(100); pool.setMaxIdle(8); String[] active = new String[100]; for(int i=0;i<100;i++) { active[i] = pool.borrowObject(); } assertEquals(100,pool.getNumActive()); assertEquals(0,pool.getNumIdle()); for(int i=0;i<100;i++) { pool.returnObject(active[i]); assertEquals(99 - i,pool.getNumActive()); assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle()); } } public void testMaxIdleZero() throws Exception { pool.setMaxActive(100); pool.setMaxIdle(0); String[] active = new String[100]; for(int i=0;i<100;i++) { active[i] = pool.borrowObject(); } assertEquals(100,pool.getNumActive()); assertEquals(0,pool.getNumIdle()); for(int i=0;i<100;i++) { pool.returnObject(active[i]); assertEquals(99 - i,pool.getNumActive()); assertEquals(0, pool.getNumIdle()); } } public void testMaxActive() throws Exception { pool.setMaxActive(3); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); pool.borrowObject(); pool.borrowObject(); pool.borrowObject(); try { pool.borrowObject(); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } } public void testTimeoutNoLeak() throws Exception { pool.setMaxActive(2); pool.setMaxWait(10); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); String obj = pool.borrowObject(); String obj2 = pool.borrowObject(); try { pool.borrowObject(); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException ex) { //xpected } pool.returnObject(obj2); pool.returnObject(obj); obj = pool.borrowObject(); obj2 = pool.borrowObject(); } public void testMaxActiveZero() throws Exception { pool.setMaxActive(0); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); try { pool.borrowObject(); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } } public void testMaxActiveUnderLoad() { // Config int numThreads = 199; // And main thread makes a round 200. int numIter = 20; int delay = 25; int maxActive = 10; SimpleFactory factory = new SimpleFactory(); factory.setMaxActive(maxActive); pool.setFactory(factory); pool.setMaxActive(maxActive); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); pool.setTimeBetweenEvictionRunsMillis(-1); // Start threads to borrow objects @SuppressWarnings("unchecked") TestThread[] threads = new TestThread[numThreads]; for(int i=0;i(pool, numIter * 2, delay * 2); Thread t = new Thread(threads[i]); t.start(); } // Give the threads a chance to start doing some work try { Thread.sleep(5000); } catch(InterruptedException e) { // ignored } for (int i = 0; i < numIter; i++) { String obj = null; try { try { Thread.sleep(delay); } catch(InterruptedException e) { // ignored } obj = pool.borrowObject(); // Under load, observed _numActive > _maxActive if (pool.getNumActive() > pool.getMaxActive()) { throw new IllegalStateException("Too many active objects"); } try { Thread.sleep(delay); } catch(InterruptedException e) { // ignored } } catch (Exception e) { // Shouldn't happen e.printStackTrace(); fail("Exception on borrow"); } finally { if (obj != null) { try { pool.returnObject(obj); } catch (Exception e) { // Ignore } } } } for(int i=0;i pool = new GenericObjectPool( new SimpleFactory(), GenericObjectPool.DEFAULT_MAX_ACTIVE, Byte.MAX_VALUE, GenericObjectPool.DEFAULT_MAX_WAIT, GenericObjectPool.DEFAULT_MAX_IDLE, false, false, GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, false ); assertNotNull(pool); fail("Expected IllegalArgumentException"); } catch(IllegalArgumentException e) { // expected } } public void testSettersAndGetters() throws Exception { GenericObjectPool pool = new GenericObjectPool(); { pool.setFactory(new SimpleFactory()); } { pool.setMaxActive(123); assertEquals(123,pool.getMaxActive()); } { pool.setMaxIdle(12); assertEquals(12,pool.getMaxIdle()); } { pool.setMaxWait(1234L); assertEquals(1234L,pool.getMaxWait()); } { pool.setMinEvictableIdleTimeMillis(12345L); assertEquals(12345L,pool.getMinEvictableIdleTimeMillis()); } { pool.setNumTestsPerEvictionRun(11); assertEquals(11,pool.getNumTestsPerEvictionRun()); } { pool.setTestOnBorrow(true); assertTrue(pool.getTestOnBorrow()); pool.setTestOnBorrow(false); assertTrue(!pool.getTestOnBorrow()); } { pool.setTestOnReturn(true); assertTrue(pool.getTestOnReturn()); pool.setTestOnReturn(false); assertTrue(!pool.getTestOnReturn()); } { pool.setTestWhileIdle(true); assertTrue(pool.getTestWhileIdle()); pool.setTestWhileIdle(false); assertTrue(!pool.getTestWhileIdle()); } { pool.setTimeBetweenEvictionRunsMillis(11235L); assertEquals(11235L,pool.getTimeBetweenEvictionRunsMillis()); } { pool.setSoftMinEvictableIdleTimeMillis(12135L); assertEquals(12135L,pool.getSoftMinEvictableIdleTimeMillis()); } { pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK,pool.getWhenExhaustedAction()); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_FAIL,pool.getWhenExhaustedAction()); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW,pool.getWhenExhaustedAction()); } } public void testDefaultConfiguration() throws Exception { GenericObjectPool pool = new GenericObjectPool(); assertConfiguration(new GenericObjectPool.Config(),pool); } public void testConstructors() throws Exception { { GenericObjectPool pool = new GenericObjectPool(); assertConfiguration(new GenericObjectPool.Config(),pool); } { GenericObjectPool pool = new GenericObjectPool(new SimpleFactory()); assertConfiguration(new GenericObjectPool.Config(),pool); } { GenericObjectPool.Config expected = new GenericObjectPool.Config(); expected.maxActive = 2; expected.maxIdle = 3; expected.maxWait = 5L; expected.minEvictableIdleTimeMillis = 7L; expected.numTestsPerEvictionRun = 9; expected.testOnBorrow = true; expected.testOnReturn = true; expected.testWhileIdle = true; expected.timeBetweenEvictionRunsMillis = 11L; expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; GenericObjectPool pool = new GenericObjectPool(null,expected); assertConfiguration(expected,pool); } { GenericObjectPool.Config expected = new GenericObjectPool.Config(); expected.maxActive = 2; GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive); assertConfiguration(expected,pool); } { GenericObjectPool.Config expected = new GenericObjectPool.Config(); expected.maxActive = 2; expected.maxWait = 5L; expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait); assertConfiguration(expected,pool); } { GenericObjectPool.Config expected = new GenericObjectPool.Config(); expected.maxActive = 2; expected.maxWait = 5L; expected.testOnBorrow = true; expected.testOnReturn = true; expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.testOnBorrow,expected.testOnReturn); assertConfiguration(expected,pool); } { GenericObjectPool.Config expected = new GenericObjectPool.Config(); expected.maxActive = 2; expected.maxIdle = 3; expected.maxWait = 5L; expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.maxIdle); assertConfiguration(expected,pool); } { GenericObjectPool.Config expected = new GenericObjectPool.Config(); expected.maxActive = 2; expected.maxIdle = 3; expected.maxWait = 5L; expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; expected.testOnBorrow = true; expected.testOnReturn = true; GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.maxIdle,expected.testOnBorrow,expected.testOnReturn); assertConfiguration(expected,pool); } { GenericObjectPool.Config expected = new GenericObjectPool.Config(); expected.maxActive = 2; expected.maxIdle = 3; expected.maxWait = 5L; expected.minEvictableIdleTimeMillis = 7L; expected.numTestsPerEvictionRun = 9; expected.testOnBorrow = true; expected.testOnReturn = true; expected.testWhileIdle = true; expected.timeBetweenEvictionRunsMillis = 11L; expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive, expected.whenExhaustedAction, expected.maxWait, expected.maxIdle, expected.testOnBorrow, expected.testOnReturn, expected.timeBetweenEvictionRunsMillis, expected.numTestsPerEvictionRun, expected.minEvictableIdleTimeMillis, expected.testWhileIdle); assertConfiguration(expected,pool); } { GenericObjectPool.Config expected = new GenericObjectPool.Config(); expected.maxActive = 2; expected.maxIdle = 3; expected.minIdle = 1; expected.maxWait = 5L; expected.minEvictableIdleTimeMillis = 7L; expected.numTestsPerEvictionRun = 9; expected.testOnBorrow = true; expected.testOnReturn = true; expected.testWhileIdle = true; expected.timeBetweenEvictionRunsMillis = 11L; expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive, expected.whenExhaustedAction, expected.maxWait, expected.maxIdle, expected.minIdle, expected.testOnBorrow, expected.testOnReturn, expected.timeBetweenEvictionRunsMillis, expected.numTestsPerEvictionRun, expected.minEvictableIdleTimeMillis, expected.testWhileIdle); assertConfiguration(expected,pool); } } public void testSetConfig() throws Exception { GenericObjectPool.Config expected = new GenericObjectPool.Config(); GenericObjectPool pool = new GenericObjectPool(); assertConfiguration(expected,pool); expected.maxActive = 2; expected.maxIdle = 3; expected.maxWait = 5L; expected.minEvictableIdleTimeMillis = 7L; expected.numTestsPerEvictionRun = 9; expected.testOnBorrow = true; expected.testOnReturn = true; expected.testWhileIdle = true; expected.timeBetweenEvictionRunsMillis = 11L; expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; pool.setConfig(expected); assertConfiguration(expected,pool); } public void testDebugInfo() throws Exception { GenericObjectPool pool = new GenericObjectPool(new SimpleFactory()); pool.setMaxIdle(3); assertNotNull(pool.debugInfo()); String obj = pool.borrowObject(); assertNotNull(pool.debugInfo()); pool.returnObject(obj); assertNotNull(pool.debugInfo()); } public void testStartAndStopEvictor() throws Exception { // set up pool without evictor pool.setMaxIdle(6); pool.setMaxActive(6); pool.setNumTestsPerEvictionRun(6); pool.setMinEvictableIdleTimeMillis(100L); for(int j=0;j<2;j++) { // populate the pool { String[] active = new String[6]; for(int i=0;i<6;i++) { active[i] = pool.borrowObject(); } for(int i=0;i<6;i++) { pool.returnObject(active[i]); } } // note that it stays populated assertEquals("Should have 6 idle",6,pool.getNumIdle()); // start the evictor pool.setTimeBetweenEvictionRunsMillis(50L); // wait a second (well, .2 seconds) try { Thread.sleep(200L); } catch(InterruptedException e) { } // assert that the evictor has cleared out the pool assertEquals("Should have 0 idle",0,pool.getNumIdle()); // stop the evictor pool.startEvictor(0L); } } public void testEvictionWithNegativeNumTests() throws Exception { // when numTestsPerEvictionRun is negative, it represents a fraction of the idle objects to test pool.setMaxIdle(6); pool.setMaxActive(6); pool.setNumTestsPerEvictionRun(-2); pool.setMinEvictableIdleTimeMillis(50L); pool.setTimeBetweenEvictionRunsMillis(100L); String[] active = new String[6]; for(int i=0;i<6;i++) { active[i] = pool.borrowObject(); } for(int i=0;i<6;i++) { pool.returnObject(active[i]); } try { Thread.sleep(100L); } catch(InterruptedException e) { } assertTrue("Should at most 6 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 6); try { Thread.sleep(100L); } catch(InterruptedException e) { } assertTrue("Should at most 3 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 3); try { Thread.sleep(100L); } catch(InterruptedException e) { } assertTrue("Should be at most 2 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 2); try { Thread.sleep(100L); } catch(InterruptedException e) { } assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle()); } public void testEviction() throws Exception { pool.setMaxIdle(500); pool.setMaxActive(500); pool.setNumTestsPerEvictionRun(100); pool.setMinEvictableIdleTimeMillis(250L); pool.setTimeBetweenEvictionRunsMillis(500L); pool.setTestWhileIdle(true); String[] active = new String[500]; for(int i=0;i<500;i++) { active[i] = pool.borrowObject(); } for(int i=0;i<500;i++) { pool.returnObject(active[i]); } try { Thread.sleep(1000L); } catch(InterruptedException e) { } assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle()); for(int i=0;i<500;i++) { active[i] = pool.borrowObject(); } for(int i=0;i<500;i++) { pool.returnObject(active[i]); } try { Thread.sleep(1000L); } catch(InterruptedException e) { } assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100); try { Thread.sleep(600L); } catch(InterruptedException e) { } assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle()); } public void testEvictionSoftMinIdle() throws Exception { class TimeTest extends BasePoolableObjectFactory { private final long createTime; public TimeTest() { createTime = System.currentTimeMillis(); } @Override public TimeTest makeObject() throws Exception { return new TimeTest(); } public long getCreateTime() { return createTime; } } GenericObjectPool pool = null; pool = new GenericObjectPool(new TimeTest()); pool.setMaxIdle(5); pool.setMaxActive(5); pool.setNumTestsPerEvictionRun(5); pool.setMinEvictableIdleTimeMillis(3000L); pool.setSoftMinEvictableIdleTimeMillis(1000L); pool.setMinIdle(2); TimeTest[] active = new TimeTest[5]; Long[] creationTime = new Long[5] ; for(int i=0;i<5;i++) { active[i] = pool.borrowObject(); creationTime[i] = new Long(active[i].getCreateTime()); } for(int i=0;i<5;i++) { pool.returnObject(active[i]); } // Soft evict all but minIdle(2) Thread.sleep(1500L); pool.evict(); assertEquals("Idle count different than expected.", 2, pool.getNumIdle()); // Hard evict the rest. Thread.sleep(2000L); pool.evict(); assertEquals("Idle count different than expected.", 0, pool.getNumIdle()); } public void testMinIdle() throws Exception { pool.setMaxIdle(500); pool.setMinIdle(5); pool.setMaxActive(10); pool.setNumTestsPerEvictionRun(0); pool.setMinEvictableIdleTimeMillis(50L); pool.setTimeBetweenEvictionRunsMillis(100L); pool.setTestWhileIdle(true); try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); String[] active = new String[5]; active[0] = pool.borrowObject(); try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); for(int i=1 ; i<5 ; i++) { active[i] = pool.borrowObject(); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); for(int i=0 ; i<5 ; i++) { pool.returnObject(active[i]); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10); } public void testMinIdleMaxActive() throws Exception { pool.setMaxIdle(500); pool.setMinIdle(5); pool.setMaxActive(10); pool.setNumTestsPerEvictionRun(0); pool.setMinEvictableIdleTimeMillis(50L); pool.setTimeBetweenEvictionRunsMillis(100L); pool.setTestWhileIdle(true); try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); String[] active = new String[10]; try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); for(int i=0 ; i<5 ; i++) { active[i] = pool.borrowObject(); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5); for(int i=0 ; i<5 ; i++) { pool.returnObject(active[i]); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10); for(int i=0 ; i<10 ; i++) { active[i] = pool.borrowObject(); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0); for(int i=0 ; i<10 ; i++) { pool.returnObject(active[i]); } try { Thread.sleep(150L); } catch(InterruptedException e) { } assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10); } /** * Kicks off test threads, each of which will go through * borrow-return cycles with random delay times <= delay * in between. */ public void runTestThreads(int numThreads, int iterations, int delay) { @SuppressWarnings("unchecked") TestThread[] threads = new TestThread[numThreads]; for(int i=0;i(pool,iterations,delay); Thread t = new Thread(threads[i]); t.start(); } for(int i=0;i(factory); pool.setMaxActive(maxActive); pool.setMaxIdle(-1); pool.setTestOnReturn(true); pool.setMaxWait(1000L); runTestThreads(5, 10, 50); } public void testConcurrentBorrowAndEvict() throws Exception { pool.setMaxActive(1); pool.addObject(); for( int i=0; i<5000; i++) { ConcurrentBorrowAndEvictThread one = new ConcurrentBorrowAndEvictThread(true); ConcurrentBorrowAndEvictThread two = new ConcurrentBorrowAndEvictThread(false); one.start(); two.start(); one.join(); two.join(); pool.returnObject(one.obj); /* Uncomment this for a progress indication if (i % 10 == 0) { System.out.println(i/10); } */ } } private class ConcurrentBorrowAndEvictThread extends Thread { private boolean borrow; public String obj; public ConcurrentBorrowAndEvictThread(boolean borrow) { this.borrow = borrow; } @Override public void run() { try { if (borrow) { obj = pool.borrowObject(); } else { pool.evict(); } } catch (Exception e) { /* Ignore */} } } static class TestThread implements Runnable { private final java.util.Random _random = new java.util.Random(); // Thread config items private final ObjectPool _pool; private final int _iter; private final int _delay; private final boolean _randomDelay; private final T _expectedObject; private volatile boolean _complete = false; private volatile boolean _failed = false; private volatile Throwable _error; public TestThread(ObjectPool pool) { this(pool, 100, 50, true, null); } public TestThread(ObjectPool pool, int iter) { this(pool, iter, 50, true, null); } public TestThread(ObjectPool pool, int iter, int delay) { this(pool, iter, delay, true, null); } public TestThread(ObjectPool pool, int iter, int delay, boolean randomDelay) { this(pool, iter, delay, randomDelay, null); } public TestThread(ObjectPool pool, int iter, int delay, boolean randomDelay, T obj) { _pool = pool; _iter = iter; _delay = delay; _randomDelay = randomDelay; _expectedObject = obj; } public boolean complete() { return _complete; } public boolean failed() { return _failed; } public void run() { for(int i=0;i<_iter;i++) { long delay = _randomDelay ? (long)_random.nextInt(_delay) : _delay; try { Thread.sleep(delay); } catch(InterruptedException e) { // ignored } T obj = null; try { obj = _pool.borrowObject(); } catch(Exception e) { _error = e; _failed = true; _complete = true; break; } if (_expectedObject != null && !_expectedObject.equals(obj)) { _error = new Throwable("Expected: "+_expectedObject+ " found: "+obj); _failed = true; _complete = true; break; } try { Thread.sleep(delay); } catch(InterruptedException e) { // ignored } try { _pool.returnObject(obj); } catch(Exception e) { _error = e; _failed = true; _complete = true; break; } } _complete = true; } } public void testFIFO() throws Exception { pool.setLifo(false); pool.addObject(); // "0" pool.addObject(); // "1" pool.addObject(); // "2" assertEquals("Oldest", "0", pool.borrowObject()); assertEquals("Middle", "1", pool.borrowObject()); assertEquals("Youngest", "2", pool.borrowObject()); assertEquals("new-3", "3", pool.borrowObject()); pool.returnObject("r"); assertEquals("returned", "r", pool.borrowObject()); assertEquals("new-4", "4", pool.borrowObject()); } public void testLIFO() throws Exception { pool.setLifo(true); pool.addObject(); // "0" pool.addObject(); // "1" pool.addObject(); // "2" assertEquals("Youngest", "2", pool.borrowObject()); assertEquals("Middle", "1", pool.borrowObject()); assertEquals("Oldest", "0", pool.borrowObject()); assertEquals("new-3", "3", pool.borrowObject()); pool.returnObject("r"); assertEquals("returned", "r", pool.borrowObject()); assertEquals("new-4", "4", pool.borrowObject()); } public void testAddObject() throws Exception { assertEquals("should be zero idle", 0, pool.getNumIdle()); pool.addObject(); assertEquals("should be one idle", 1, pool.getNumIdle()); assertEquals("should be zero active", 0, pool.getNumActive()); String obj = pool.borrowObject(); assertEquals("should be zero idle", 0, pool.getNumIdle()); assertEquals("should be one active", 1, pool.getNumActive()); pool.returnObject(obj); assertEquals("should be one idle", 1, pool.getNumIdle()); assertEquals("should be zero active", 0, pool.getNumActive()); ObjectPool op = new GenericObjectPool(); try { op.addObject(); fail("Expected IllegalStateException when there is no factory."); } catch (IllegalStateException ise) { //expected } op.close(); } protected GenericObjectPool pool = null; private void assertConfiguration(GenericObjectPool.Config expected, GenericObjectPool actual) throws Exception { assertEquals("testOnBorrow",expected.testOnBorrow,actual.getTestOnBorrow()); assertEquals("testOnReturn",expected.testOnReturn,actual.getTestOnReturn()); assertEquals("testWhileIdle",expected.testWhileIdle,actual.getTestWhileIdle()); assertEquals("whenExhaustedAction",expected.whenExhaustedAction,actual.getWhenExhaustedAction()); assertEquals("maxActive",expected.maxActive,actual.getMaxActive()); assertEquals("maxIdle",expected.maxIdle,actual.getMaxIdle()); assertEquals("maxWait",expected.maxWait,actual.getMaxWait()); assertEquals("minEvictableIdleTimeMillis",expected.minEvictableIdleTimeMillis,actual.getMinEvictableIdleTimeMillis()); assertEquals("numTestsPerEvictionRun",expected.numTestsPerEvictionRun,actual.getNumTestsPerEvictionRun()); assertEquals("timeBetweenEvictionRunsMillis",expected.timeBetweenEvictionRunsMillis,actual.getTimeBetweenEvictionRunsMillis()); } public class SimpleFactory implements PoolableObjectFactory { public SimpleFactory() { this(true); } public SimpleFactory(boolean valid) { this(valid,valid); } public SimpleFactory(boolean evalid, boolean ovalid) { evenValid = evalid; oddValid = ovalid; } public synchronized void setValid(boolean valid) { setEvenValid(valid); setOddValid(valid); } public synchronized void setEvenValid(boolean valid) { evenValid = valid; } public synchronized void setOddValid(boolean valid) { oddValid = valid; } public synchronized void setThrowExceptionOnPassivate(boolean bool) { exceptionOnPassivate = bool; } public synchronized void setMaxActive(int maxActive) { this.maxActive = maxActive; } public synchronized void setDestroyLatency(long destroyLatency) { this.destroyLatency = destroyLatency; } public synchronized void setMakeLatency(long makeLatency) { this.makeLatency = makeLatency; } public synchronized void setValidateLatency(long validateLatency) { this.validateLatency = validateLatency; } public String makeObject() { final long waitLatency; synchronized(this) { activeCount++; if (activeCount > maxActive) { throw new IllegalStateException( "Too many active instances: " + activeCount); } waitLatency = makeLatency; } if (waitLatency > 0) { doWait(waitLatency); } final int counter; synchronized(this) { counter = makeCounter++; } return String.valueOf(counter); } public void destroyObject(String obj) throws Exception { final long waitLatency; final boolean hurl; synchronized(this) { waitLatency = destroyLatency; hurl = exceptionOnDestroy; } if (waitLatency > 0) { doWait(waitLatency); } synchronized(this) { activeCount--; } if (hurl) { throw new Exception(); } } public boolean validateObject(String obj) { final boolean validate; final boolean evenTest; final boolean oddTest; final long waitLatency; final int counter; synchronized(this) { validate = enableValidation; evenTest = evenValid; oddTest = oddValid; counter = validateCounter++; waitLatency = validateLatency; } if (waitLatency > 0) { doWait(waitLatency); } if (validate) { return counter%2 == 0 ? evenTest : oddTest; } else { return true; } } public void activateObject(String obj) throws Exception { final boolean hurl; final boolean evenTest; final boolean oddTest; final int counter; synchronized(this) { hurl = exceptionOnActivate; evenTest = evenValid; oddTest = oddValid; counter = validateCounter++; } if (hurl) { if (!(counter%2 == 0 ? evenTest : oddTest)) { throw new Exception(); } } } public void passivateObject(String obj) throws Exception { final boolean hurl; synchronized(this) { hurl = exceptionOnPassivate; } if (hurl) { throw new Exception(); } } int makeCounter = 0; int validateCounter = 0; int activeCount = 0; boolean evenValid = true; boolean oddValid = true; boolean exceptionOnPassivate = false; boolean exceptionOnActivate = false; boolean exceptionOnDestroy = false; boolean enableValidation = true; long destroyLatency = 0; long makeLatency = 0; long validateLatency = 0; int maxActive = Integer.MAX_VALUE; public synchronized boolean isThrowExceptionOnActivate() { return exceptionOnActivate; } public synchronized void setThrowExceptionOnActivate(boolean b) { exceptionOnActivate = b; } public synchronized void setThrowExceptionOnDestroy(boolean b) { exceptionOnDestroy = b; } public synchronized boolean isValidationEnabled() { return enableValidation; } public synchronized void setValidationEnabled(boolean b) { enableValidation = b; } public synchronized int getMakeCounter() { return makeCounter; } private void doWait(long latency) { try { Thread.sleep(latency); } catch (InterruptedException ex) { // ignore } } } @Override protected boolean isLifo() { return true; } @Override protected boolean isFifo() { return false; } /* * Note: This test relies on timing for correct execution. There *should* be * enough margin for this to work correctly on most (all?) systems but be * aware of this if you see a failure of this test. */ public void testBorrowObjectFairness() { // Config int numThreads = 30; int maxActive = 10; SimpleFactory factory = new SimpleFactory(); factory.setMaxActive(maxActive); pool.setFactory(factory); pool.setMaxActive(maxActive); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); pool.setTimeBetweenEvictionRunsMillis(-1); // Start threads to borrow objects @SuppressWarnings("unchecked") TestThread[] threads = new TestThread[numThreads]; for(int i=0;i(pool, 1, 2000, false, String.valueOf(i % maxActive)); Thread t = new Thread(threads[i]); t.start(); // Short delay to ensure threads start in correct order try { Thread.sleep(50); } catch (InterruptedException e) { fail(e.toString()); } } // Wait for threads to finish for(int i=0;i extends Thread { private final GenericObjectPool _pool; private final long _pause; private Throwable _thrown; private long preborrow; // just before borrow private long postborrow; // borrow returned private long postreturn; // after object was returned private long ended; private String objectId; public WaitingTestThread(GenericObjectPool pool, long pause) { _pool = pool; _pause = pause; _thrown = null; } @Override public void run() { try { preborrow = System.currentTimeMillis(); T obj = _pool.borrowObject(); objectId=obj.toString(); postborrow = System.currentTimeMillis(); Thread.sleep(_pause); _pool.returnObject(obj); postreturn = System.currentTimeMillis(); } catch (Exception e) { _thrown = e; } finally{ ended = System.currentTimeMillis(); } } } private static final boolean DISPLAY_THREAD_DETAILS= Boolean.valueOf(System.getProperty("TestGenericObjectPool.display.thread.details", "false")).booleanValue(); // To pass this to a Maven test, use: // mvn test -DargLine="-DTestGenericObjectPool.display.thread.details=true" // @see http://jira.codehaus.org/browse/SUREFIRE-121 /* * Test multi-threaded pool access. * Multiple threads, but maxActive only allows half the threads to succeed. * * This test was prompted by Continuum build failures in the Commons DBCP test case: * TestPerUserPoolDataSource.testMultipleThreads2() * Let's see if the this fails on Continuum too! */ public void testMaxWaitMultiThreaded() throws Exception { final long maxWait = 500; // wait for connection final long holdTime = 2 * maxWait; // how long to hold connection final int threads = 10; // number of threads to grab the object initially SimpleFactory factory = new SimpleFactory(); GenericObjectPool pool = new GenericObjectPool(factory); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); pool.setMaxWait(maxWait); pool.setMaxActive(threads); // Create enough threads so half the threads will have to wait @SuppressWarnings("unchecked") WaitingTestThread wtt[] = new WaitingTestThread[threads * 2]; for(int i=0; i < wtt.length; i++){ wtt[i] = new WaitingTestThread(pool,holdTime); } long origin = System.currentTimeMillis()-1000; for(int i=0; i < wtt.length; i++){ wtt[i].start(); } int failed = 0; for(int i=0; i < wtt.length; i++){ wtt[i].join(); if (wtt[i]._thrown != null){ failed++; } } if (DISPLAY_THREAD_DETAILS || wtt.length/2 != failed){ System.out.println( "MaxWait: "+maxWait +" HoldTime: "+holdTime + " MaxActive: "+threads +" Threads: "+wtt.length +" Failed: "+failed ); for(int i=0; i < wtt.length; i++){ WaitingTestThread wt = wtt[i]; System.out.println( "Preborrow: "+(wt.preborrow-origin) + " Postborrow: "+(wt.postborrow != 0 ? wt.postborrow-origin : -1) + " BorrowTime: "+(wt.postborrow != 0 ? wt.postborrow-wt.preborrow : -1) + " PostReturn: "+(wt.postreturn != 0 ? wt.postreturn-origin : -1) + " Ended: "+(wt.ended-origin) + " ObjId: "+wt.objectId ); } } assertEquals("Expected half the threads to fail",wtt.length/2,failed); } /** * Test the following scenario: * Thread 1 borrows an instance * Thread 2 starts to borrow another instance before thread 1 returns its instance * Thread 1 returns its instance while thread 2 is validating its newly created instance * The test verifies that the instance created by Thread 2 is not leaked. */ public void testMakeConcurrentWithReturn() throws Exception { SimpleFactory factory = new SimpleFactory(); GenericObjectPool pool = new GenericObjectPool(factory); pool.setTestOnBorrow(true); factory.setValid(true); // Borrow and return an instance, with a short wait WaitingTestThread thread1 = new WaitingTestThread(pool, 200); thread1.start(); Thread.sleep(50); // wait for validation to succeed // Slow down validation and borrow an instance factory.setValidateLatency(400); String instance = pool.borrowObject(); // Now make sure that we have not leaked an instance assertEquals(factory.getMakeCounter(), pool.getNumIdle() + 1); pool.returnObject(instance); assertEquals(factory.getMakeCounter(), pool.getNumIdle()); } public void testPoolTypeSubclass() throws Exception { ObjectPool numberPool = new GenericObjectPool(new PoolableObjectFactory() { public Number makeObject() throws Exception { return BigInteger.ONE; } public void destroyObject(Number obj) throws Exception { // do nothing } public boolean validateObject(Number obj) { return false; } public void activateObject(Number obj) throws Exception { // do nothing } public void passivateObject(Number obj) throws Exception { // do nothing } }); Number n = numberPool.borrowObject(); numberPool.returnObject(n); BigInteger bi = (BigInteger) numberPool.borrowObject(); numberPool.returnObject(bi); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/TestGenericObjectPoolFactory.java100644 0 0 21720 11701070262 27467 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.util.NoSuchElementException; import org.apache.commons.pool.MethodCallPoolableObjectFactory; import org.apache.commons.pool.ObjectPoolFactory; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.TestObjectPoolFactory; /** * Tests for {@link GenericObjectPoolFactory}. * * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestGenericObjectPoolFactory extends TestObjectPoolFactory { public TestGenericObjectPoolFactory(final String name) { super(name); } @Override protected ObjectPoolFactory makeFactory(final PoolableObjectFactory objectFactory) throws UnsupportedOperationException { return new GenericObjectPoolFactory(objectFactory); } public void testConstructors() throws Exception { GenericObjectPoolFactory factory = new GenericObjectPoolFactory(new MethodCallPoolableObjectFactory()); GenericObjectPool pool; factory.createPool().close(); final GenericObjectPool.Config config = new GenericObjectPool.Config(); config.maxActive = 1; config.maxIdle = 2; config.maxWait = 3; config.minIdle = 4; config.minEvictableIdleTimeMillis = 5; config.numTestsPerEvictionRun = 6; config.softMinEvictableIdleTimeMillis = 7; config.testOnBorrow = true; config.testOnReturn = false; config.testWhileIdle = true; config.lifo = false; config.timeBetweenEvictionRunsMillis = 8; config.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; factory = new GenericObjectPoolFactory(new MethodCallPoolableObjectFactory(), config); pool = (GenericObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxIdle()); assertEquals(3, pool.getMaxWait()); assertEquals(4, pool.getMinIdle()); assertEquals(5, pool.getMinEvictableIdleTimeMillis()); assertEquals(6, pool.getNumTestsPerEvictionRun()); assertEquals(7, pool.getSoftMinEvictableIdleTimeMillis()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(true, pool.getTestWhileIdle()); assertEquals(false, pool.getLifo()); assertEquals(8, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.borrowObject(); pool.close(); factory = new GenericObjectPoolFactory(new MethodCallPoolableObjectFactory(), 1); pool = (GenericObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); pool.borrowObject(); pool.close(); factory = new GenericObjectPoolFactory(new MethodCallPoolableObjectFactory(), 1, GenericObjectPool.WHEN_EXHAUSTED_BLOCK, 125); pool = (GenericObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK, pool.getWhenExhaustedAction()); assertEquals(125, pool.getMaxWait()); pool.borrowObject(); long startTime = System.currentTimeMillis(); try { pool.borrowObject(); fail(); } catch (NoSuchElementException nsee) { // expected } long delay = System.currentTimeMillis() - startTime; assertTrue("delay: " + delay, delay > 100); pool.close(); factory = new GenericObjectPoolFactory(new MethodCallPoolableObjectFactory(), 1, GenericObjectPool.WHEN_EXHAUSTED_GROW, 2, true, false); pool = (GenericObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.borrowObject(); pool.close(); factory = new GenericObjectPoolFactory(new MethodCallPoolableObjectFactory(), 1, GenericObjectPool.WHEN_EXHAUSTED_GROW, 2, 3); pool = (GenericObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(3, pool.getMaxIdle()); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.borrowObject(); pool.close(); factory = new GenericObjectPoolFactory(new MethodCallPoolableObjectFactory(), 1, GenericObjectPool.WHEN_EXHAUSTED_GROW, 2, 3, true, false); pool = (GenericObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(3, pool.getMaxIdle()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.borrowObject(); pool.close(); factory = new GenericObjectPoolFactory(new MethodCallPoolableObjectFactory(), 1, GenericObjectPool.WHEN_EXHAUSTED_GROW, 2, 3, true, false, 4, 5, 6, false); pool = (GenericObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(3, pool.getMaxIdle()); assertEquals(4, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(5, pool.getNumTestsPerEvictionRun()); assertEquals(6, pool.getMinEvictableIdleTimeMillis()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(false, pool.getTestWhileIdle()); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.borrowObject(); pool.close(); factory = new GenericObjectPoolFactory(new MethodCallPoolableObjectFactory(), 1, GenericObjectPool.WHEN_EXHAUSTED_GROW, 2, 3, 4, true, false, 5, 6, 7, true); pool = (GenericObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(3, pool.getMaxIdle()); assertEquals(4, pool.getMinIdle()); assertEquals(5, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(6, pool.getNumTestsPerEvictionRun()); assertEquals(7, pool.getMinEvictableIdleTimeMillis()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(true, pool.getTestWhileIdle()); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.borrowObject(); pool.close(); factory = new GenericObjectPoolFactory(new MethodCallPoolableObjectFactory(), 1, GenericObjectPool.WHEN_EXHAUSTED_GROW, 2, 3, 4, true, false, 5, 6, 7, true, 8, false); pool = (GenericObjectPool)factory.createPool(); assertEquals(1, pool.getMaxActive()); assertEquals(2, pool.getMaxWait()); assertEquals(3, pool.getMaxIdle()); assertEquals(4, pool.getMinIdle()); assertEquals(5, pool.getTimeBetweenEvictionRunsMillis()); assertEquals(6, pool.getNumTestsPerEvictionRun()); assertEquals(7, pool.getMinEvictableIdleTimeMillis()); assertEquals(8, pool.getSoftMinEvictableIdleTimeMillis()); assertEquals(true, pool.getTestOnBorrow()); assertEquals(false, pool.getTestOnReturn()); assertEquals(true, pool.getTestWhileIdle()); assertEquals(false, pool.getLifo()); assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW, pool.getWhenExhaustedAction()); pool.borrowObject(); pool.close(); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/TestSoftReferenceObjectPool.java100644 0 0 4522 11701070262 27276 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.TestBaseObjectPool; /** * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestSoftReferenceObjectPool extends TestBaseObjectPool { public TestSoftReferenceObjectPool(String testName) { super(testName); } @Override protected ObjectPool makeEmptyPool(int cap) { return new SoftReferenceObjectPool( new PoolableObjectFactory() { int counter = 0; public String makeObject() { return String.valueOf(counter++); } public void destroyObject(String obj) { } public boolean validateObject(String obj) { return true; } public void activateObject(String obj) { } public void passivateObject(String obj) { } } ); } @Override protected ObjectPool makeEmptyPool(final PoolableObjectFactory factory) { return new SoftReferenceObjectPool(factory); } @Override protected String getNthObject(int n) { return String.valueOf(n); } @Override protected boolean isLifo() { return false; } @Override protected boolean isFifo() { return false; } } commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/TestSoftRefOutOfMemory.java100644 0 0 20777 11701070262 26333 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import junit.framework.TestCase; import org.apache.commons.pool.BasePoolableObjectFactory; import org.apache.commons.pool.PoolableObjectFactory; /** * @author Dirk Verbeeck * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestSoftRefOutOfMemory extends TestCase { private SoftReferenceObjectPool pool; public TestSoftRefOutOfMemory(String testName) { super(testName); } @Override public void tearDown() throws Exception { if (pool != null) { pool.close(); pool = null; } System.gc(); } public void testOutOfMemory() throws Exception { pool = new SoftReferenceObjectPool(new SmallPoolableObjectFactory()); String obj = pool.borrowObject(); assertEquals("1", obj); pool.returnObject(obj); obj = null; assertEquals(1, pool.getNumIdle()); final List garbage = new LinkedList(); final Runtime runtime = Runtime.getRuntime(); while (pool.getNumIdle() > 0) { try { long freeMemory = runtime.freeMemory(); if (freeMemory > Integer.MAX_VALUE) { freeMemory = Integer.MAX_VALUE; } garbage.add(new byte[Math.min(1024 * 1024, (int)freeMemory/2)]); } catch (OutOfMemoryError oome) { System.gc(); } System.gc(); } garbage.clear(); System.gc(); obj = pool.borrowObject(); assertEquals("2", obj); pool.returnObject(obj); obj = null; assertEquals(1, pool.getNumIdle()); } public void testOutOfMemory1000() throws Exception { pool = new SoftReferenceObjectPool(new SmallPoolableObjectFactory()); for (int i = 0 ; i < 1000 ; i++) { pool.addObject(); } String obj = pool.borrowObject(); assertEquals("1000", obj); pool.returnObject(obj); obj = null; assertEquals(1000, pool.getNumIdle()); final List garbage = new LinkedList(); final Runtime runtime = Runtime.getRuntime(); while (pool.getNumIdle() > 0) { try { long freeMemory = runtime.freeMemory(); if (freeMemory > Integer.MAX_VALUE) { freeMemory = Integer.MAX_VALUE; } garbage.add(new byte[Math.min(1024 * 1024, (int)freeMemory/2)]); } catch (OutOfMemoryError oome) { System.gc(); } System.gc(); } garbage.clear(); System.gc(); obj = pool.borrowObject(); assertEquals("1001", obj); pool.returnObject(obj); obj = null; assertEquals(1, pool.getNumIdle()); } public void testOutOfMemoryLarge() throws Exception { pool = new SoftReferenceObjectPool(new LargePoolableObjectFactory(1000000)); String obj = pool.borrowObject(); assertTrue(obj.startsWith("1.")); pool.returnObject(obj); obj = null; assertEquals(1, pool.getNumIdle()); final List garbage = new LinkedList(); final Runtime runtime = Runtime.getRuntime(); while (pool.getNumIdle() > 0) { try { long freeMemory = runtime.freeMemory(); if (freeMemory > Integer.MAX_VALUE) { freeMemory = Integer.MAX_VALUE; } garbage.add(new byte[Math.min(1024 * 1024, (int)freeMemory/2)]); } catch (OutOfMemoryError oome) { System.gc(); } System.gc(); } garbage.clear(); System.gc(); obj = pool.borrowObject(); assertTrue(obj.startsWith("2.")); pool.returnObject(obj); obj = null; assertEquals(1, pool.getNumIdle()); } /** * Makes sure an {@link OutOfMemoryError} isn't swallowed. */ public void testOutOfMemoryError() throws Exception { pool = new SoftReferenceObjectPool(new BasePoolableObjectFactory() { @Override public String makeObject() throws Exception { throw new OutOfMemoryError(); } }); try { pool.borrowObject(); fail("Expected out of memory."); } catch (OutOfMemoryError ex) { // expected } pool.close(); pool = new SoftReferenceObjectPool(new BasePoolableObjectFactory() { @Override public String makeObject() throws Exception { return new String(); } @Override public boolean validateObject(String obj) { throw new OutOfMemoryError(); } }); try { pool.borrowObject(); fail("Expected out of memory."); } catch (OutOfMemoryError ex) { // expected } pool.close(); pool = new SoftReferenceObjectPool(new BasePoolableObjectFactory() { @Override public String makeObject() throws Exception { return new String(); } @Override public boolean validateObject(String obj) { throw new IllegalAccessError(); } @Override public void destroyObject(String obj) throws Exception { throw new OutOfMemoryError(); } }); try { pool.borrowObject(); fail("Expected out of memory."); } catch (OutOfMemoryError ex) { // expected } pool.close(); } public static class SmallPoolableObjectFactory implements PoolableObjectFactory { private int counter = 0; public String makeObject() { counter++; // It seems that as of Java 1.4 String.valueOf may return an // intern()'ed String this may cause problems when the tests // depend on the returned object to be eventually garbaged // collected. Either way, making sure a new String instance // is returned eliminated false failures. return new String(String.valueOf(counter)); } public boolean validateObject(String obj) { return true; } public void activateObject(String obj) { } public void passivateObject(String obj) { } public void destroyObject(String obj) { } } public static class LargePoolableObjectFactory implements PoolableObjectFactory { private String buffer; private int counter = 0; public LargePoolableObjectFactory(int size) { char[] data = new char[size]; Arrays.fill(data, '.'); buffer = new String(data); } public String makeObject() { counter++; return String.valueOf(counter) + buffer; } public boolean validateObject(String obj) { return true; } public void activateObject(String obj) { } public void passivateObject(String obj) { } public void destroyObject(String obj) { } } }commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java100644 0 0 31265 11701070262 26617 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.util.BitSet; import java.util.HashMap; import java.util.NoSuchElementException; import org.apache.commons.pool.KeyedObjectPool; import org.apache.commons.pool.KeyedPoolableObjectFactory; import org.apache.commons.pool.TestBaseKeyedObjectPool; /** * @author Rodney Waldhoff * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestStackKeyedObjectPool extends TestBaseKeyedObjectPool { public TestStackKeyedObjectPool(String testName) { super(testName); } @Override protected KeyedObjectPool makeEmptyPool(int mincapacity) { StackKeyedObjectPool pool = new StackKeyedObjectPool(new SimpleFactory(),mincapacity); return pool; } @Override protected KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory) { return new StackKeyedObjectPool(factory); } @Override protected String getNthObject(Object key, int n) { return String.valueOf(key) + String.valueOf(n); } @Override protected String makeKey(int n) { return String.valueOf(n); } private StackKeyedObjectPool pool = null; @Override public void setUp() throws Exception { super.setUp(); pool = new StackKeyedObjectPool( new KeyedPoolableObjectFactory() { int counter = 0; public String makeObject(String key) { return String.valueOf(key) + String.valueOf(counter++); } public void destroyObject(String key, String obj) { } public boolean validateObject(String key, String obj) { return true; } public void activateObject(String key, String obj) { } public void passivateObject(String key, String obj) { } } ); } @Override public void tearDown() throws Exception { super.tearDown(); pool = null; } public void testCloseBug() throws Exception { { String obj0 = pool.borrowObject(""); String obj1 = pool.borrowObject(""); assertEquals(2,pool.getNumActive("")); assertEquals(0,pool.getNumIdle("")); pool.returnObject("",obj1); pool.returnObject("",obj0); assertEquals(0,pool.getNumActive("")); assertEquals(2,pool.getNumIdle("")); } { String obj0 = pool.borrowObject("2"); String obj1 = pool.borrowObject("2"); assertEquals(2,pool.getNumActive("2")); assertEquals(0,pool.getNumIdle("2")); pool.returnObject("2",obj1); pool.returnObject("2",obj0); assertEquals(0,pool.getNumActive("2")); assertEquals(2,pool.getNumIdle("2")); } pool.close(); } public void testIdleCap() throws Exception { String[] active = new String[100]; for(int i=0;i<100;i++) { active[i] = pool.borrowObject(""); } assertEquals(100,pool.getNumActive("")); assertEquals(0,pool.getNumIdle("")); for(int i=0;i<100;i++) { pool.returnObject("",active[i]); assertEquals(99 - i,pool.getNumActive("")); assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle("")); } } /** * Verifies maxSleeping contract: When returnObject triggers maxSleeping exceeded, * the bottom (oldest) instance in the pool is destroyed to make room for the newly * returning instance, which is pushed onto the idle object stack. */ public void testRemoveOldest() throws Exception { pool._maxSleeping = 2; String obj0 = pool.borrowObject(""); String obj1 = pool.borrowObject(""); String obj2 = pool.borrowObject(""); pool.returnObject("", obj0); // Push 0 onto bottom of stack pool.returnObject("", obj1); // Push 1 pool.returnObject("", obj2); // maxSleeping exceeded -> 0 destroyed, 2 pushed assertEquals("2", pool.borrowObject("")); // 2 was pushed on top assertEquals("1", pool.borrowObject("")); // 1 still there assertEquals("3", pool.borrowObject("")); // New instance created (0 is gone) } public void testPoolWithNullFactory() throws Exception { KeyedObjectPool pool = new StackKeyedObjectPool(10); for(int i=0;i<10;i++) { pool.returnObject("X",new Integer(i)); } for(int j=0;j<3;j++) { Integer[] borrowed = new Integer[10]; BitSet found = new BitSet(); for(int i=0;i<10;i++) { borrowed[i] = pool.borrowObject("X"); assertNotNull(borrowed); assertTrue(!found.get(borrowed[i].intValue())); found.set(borrowed[i].intValue()); } for(int i=0;i<10;i++) { pool.returnObject("X",borrowed[i]); } } pool.invalidateObject("X",pool.borrowObject("X")); pool.invalidateObject("X",pool.borrowObject("X")); pool.clear("X"); pool.clear(); } public void testVariousConstructors() throws Exception { { StackKeyedObjectPool pool = new StackKeyedObjectPool(); assertNotNull(pool); } { StackKeyedObjectPool pool = new StackKeyedObjectPool(10); assertNotNull(pool); } { StackKeyedObjectPool pool = new StackKeyedObjectPool(10,5); assertNotNull(pool); } { StackKeyedObjectPool pool = new StackKeyedObjectPool(null); assertNotNull(pool); } { StackKeyedObjectPool pool = new StackKeyedObjectPool(null,10); assertNotNull(pool); } { StackKeyedObjectPool pool = new StackKeyedObjectPool(null,10,5); assertNotNull(pool); } } @Override public void testToString() throws Exception { StackKeyedObjectPool pool = new StackKeyedObjectPool(new SimpleFactory()); assertNotNull(pool.toString()); String obj = pool.borrowObject("key"); assertNotNull(pool.toString()); pool.returnObject("key",obj); assertNotNull(pool.toString()); } public void testBorrowFromEmptyPoolWithNullFactory() throws Exception { KeyedObjectPool pool = new StackKeyedObjectPool(); try { pool.borrowObject("x"); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } } public void testSetFactory() throws Exception { KeyedObjectPool pool = new StackKeyedObjectPool(); try { pool.borrowObject("x"); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } pool.setFactory(new SimpleFactory()); String obj = pool.borrowObject("x"); assertNotNull(obj); pool.returnObject("x",obj); } public void testCantResetFactoryWithActiveObjects() throws Exception { KeyedObjectPool pool = new StackKeyedObjectPool(); pool.setFactory(new SimpleFactory()); Object obj = pool.borrowObject("x"); assertNotNull(obj); try { pool.setFactory(new SimpleFactory()); fail("Expected IllegalStateException"); } catch(IllegalStateException e) { // expected } } public void testCanResetFactoryWithoutActiveObjects() throws Exception { KeyedObjectPool pool = new StackKeyedObjectPool(); { pool.setFactory(new SimpleFactory()); String obj = pool.borrowObject("x"); assertNotNull(obj); pool.returnObject("x",obj); } { pool.setFactory(new SimpleFactory()); String obj = pool.borrowObject("x"); assertNotNull(obj); pool.returnObject("x",obj); } } public void testBorrowReturnWithSometimesInvalidObjects() throws Exception { KeyedObjectPool pool = new StackKeyedObjectPool( new KeyedPoolableObjectFactory() { int counter = 0; public Integer makeObject(String key) { return new Integer(counter++); } public void destroyObject(String key, Integer obj) { } public boolean validateObject(String key, Integer obj) { return ((obj.intValue() % 2) == 1); } public void activateObject(String key, Integer obj) { } public void passivateObject(String key, Integer obj) { if((obj.intValue() % 3) == 0) { throw new RuntimeException("Couldn't passivate"); } } } ); Integer[] obj = new Integer[10]; for(int i=0;i<10;i++) { Integer object = null; int k = 0; while (object == null && k < 100) { // bound not really needed try { k++; object = pool.borrowObject("key"); obj[i] = object; } catch (NoSuchElementException ex) { // Expected for evens, which fail validation } } assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive()); } // 1,3,5,...,19 pass validation, get checked out for(int i=0;i<10;i++) { pool.returnObject("key",obj[i]); assertEquals("Each time we borrow, get one less active.", 9-i, pool.getNumActive()); } // 3, 9, 15 fail passivation. assertEquals(7,pool.getNumIdle()); assertEquals(new Integer(19), pool.borrowObject("key")); assertEquals(new Integer(17), pool.borrowObject("key")); assertEquals(new Integer(13), pool.borrowObject("key")); assertEquals(new Integer(11), pool.borrowObject("key")); assertEquals(new Integer(7), pool.borrowObject("key")); assertEquals(new Integer(5), pool.borrowObject("key")); assertEquals(new Integer(1), pool.borrowObject("key")); } class SimpleFactory implements KeyedPoolableObjectFactory { HashMap map = new HashMap(); public String makeObject(String key) { int counter = 0; Integer Counter = map.get(key); if(null != Counter) { counter = Counter.intValue(); } map.put(key,new Integer(counter + 1)); return String.valueOf(key) + String.valueOf(counter); } public void destroyObject(String key, String obj) { } public boolean validateObject(String key, String obj) { return true; } public void activateObject(String key, String obj) { } public void passivateObject(String key, String obj) { } } @Override protected boolean isLifo() { return true; } @Override protected boolean isFifo() { return false; } } commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPoolFactory.java100644 0 0 6131 11701070262 30121 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import org.apache.commons.pool.KeyedObjectPoolFactory; import org.apache.commons.pool.KeyedPoolableObjectFactory; import org.apache.commons.pool.TestKeyedObjectPoolFactory; /** * Tests for {@link StackKeyedObjectPoolFactory}. * * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestStackKeyedObjectPoolFactory extends TestKeyedObjectPoolFactory { public TestStackKeyedObjectPoolFactory(final String name) { super(name); } @Override protected KeyedObjectPoolFactory makeFactory(final KeyedPoolableObjectFactory objectFactory) throws UnsupportedOperationException { return new StackKeyedObjectPoolFactory(objectFactory); } public void testConstructors() throws Exception { StackKeyedObjectPoolFactory factory = new StackKeyedObjectPoolFactory(); factory.createPool().close(); factory = new StackKeyedObjectPoolFactory(1); StackKeyedObjectPool pool = (StackKeyedObjectPool)factory.createPool(); assertEquals(1,pool._maxSleeping); pool.close(); factory = new StackKeyedObjectPoolFactory(1, 2); pool = (StackKeyedObjectPool)factory.createPool(); assertEquals(1,pool._maxSleeping); assertEquals(2,pool._initSleepingCapacity); pool.close(); factory = new StackKeyedObjectPoolFactory(createObjectFactory()); pool = (StackKeyedObjectPool)factory.createPool(); pool.close(); factory = new StackKeyedObjectPoolFactory(createObjectFactory(), 1); pool = (StackKeyedObjectPool)factory.createPool(); assertEquals(1,pool._maxSleeping); pool.close(); factory = new StackKeyedObjectPoolFactory(createObjectFactory(), 1, 2); pool = (StackKeyedObjectPool)factory.createPool(); assertEquals(1,pool._maxSleeping); assertEquals(2,pool._initSleepingCapacity); pool.close(); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java100644 0 0 56761 11701070262 25645 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import java.util.ArrayList; import java.util.BitSet; import java.util.List; import java.util.NoSuchElementException; import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.TestBaseObjectPool; /** * @author Rodney Waldhoff * @author Dirk Verbeeck * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestStackObjectPool extends TestBaseObjectPool { public TestStackObjectPool(String testName) { super(testName); } @Override protected ObjectPool makeEmptyPool(int mincap) { return new StackObjectPool(new SimpleFactory()); } @Override protected ObjectPool makeEmptyPool(final PoolableObjectFactory factory) { return new StackObjectPool(factory); } @Override protected String getNthObject(int n) { return String.valueOf(n); } public void testIdleCap() throws Exception { ObjectPool pool = makeEmptyPool(8); String[] active = new String[100]; for(int i=0;i<100;i++) { active[i] = pool.borrowObject(); } assertEquals(100,pool.getNumActive()); assertEquals(0,pool.getNumIdle()); for(int i=0;i<100;i++) { pool.returnObject(active[i]); assertEquals(99 - i,pool.getNumActive()); assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle()); } } /** * @deprecated - to be removed in pool 2.0 */ @Deprecated public void testPoolWithNullFactory() throws Exception { ObjectPool pool = new StackObjectPool(10); for(int i=0;i<10;i++) { pool.returnObject(new Integer(i)); } for(int j=0;j<3;j++) { Integer[] borrowed = new Integer[10]; BitSet found = new BitSet(); for(int i=0;i<10;i++) { borrowed[i] = pool.borrowObject(); assertNotNull(borrowed); assertTrue(!found.get(borrowed[i].intValue())); found.set(borrowed[i].intValue()); } for(int i=0;i<10;i++) { pool.returnObject(borrowed[i]); } } pool.invalidateObject(pool.borrowObject()); pool.invalidateObject(pool.borrowObject()); pool.clear(); } /** * @deprecated - to be removed in pool 2.0 */ @Deprecated public void testBorrowFromEmptyPoolWithNullFactory() throws Exception { ObjectPool pool = new StackObjectPool(); try { pool.borrowObject(); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } } /** * @deprecated - to be removed in pool 2.0 */ @Deprecated @Override public void testSetFactory() throws Exception { ObjectPool pool = new StackObjectPool(); try { pool.borrowObject(); fail("Expected NoSuchElementException"); } catch(NoSuchElementException e) { // expected } pool.setFactory(new SimpleFactory()); String obj = pool.borrowObject(); assertNotNull(obj); pool.returnObject(obj); } /** * @deprecated - to be removed in pool 2.0 */ @Deprecated public void testCantResetFactoryWithActiveObjects() throws Exception { ObjectPool pool = new StackObjectPool(); pool.setFactory(new SimpleFactory()); String obj = pool.borrowObject(); assertNotNull(obj); try { pool.setFactory(new SimpleFactory()); fail("Expected IllegalStateException"); } catch(IllegalStateException e) { // expected } } /** * @deprecated - to be removed in pool 2.0 */ @Deprecated public void testCanResetFactoryWithoutActiveObjects() throws Exception { ObjectPool pool = new StackObjectPool(); { pool.setFactory(new SimpleFactory()); String obj = pool.borrowObject(); assertNotNull(obj); pool.returnObject(obj); } { pool.setFactory(new SimpleFactory()); String obj = pool.borrowObject(); assertNotNull(obj); pool.returnObject(obj); } } /** * Verifies that validation failures when borrowing newly created instances * from the pool result in NoSuchElementExceptions and passivation failures * result in instances not being returned to the pool. */ public void testBorrowWithSometimesInvalidObjects() throws Exception { SelectiveFactory factory = new SelectiveFactory(); factory.setValidateSelectively(true); // Even numbers fail validation factory.setPassivateSelectively(true); // Multiples of 3 fail passivation ObjectPool pool = new StackObjectPool(factory, 20); Integer[] obj = new Integer[10]; for(int i=0;i<10;i++) { Integer object = null; int k = 0; while (object == null && k < 100) { // bound not really needed try { k++; object = pool.borrowObject(); if (object.intValue() % 2 == 0) { fail("Expecting NoSuchElementException"); } else { obj[i] = object; } } catch (NoSuchElementException ex) { // Should fail for evens } } assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive()); } // 1,3,5,...,19 pass validation, get checked out for(int i=0;i<10;i++) { pool.returnObject(obj[i]); assertEquals("Each time we return, get one less active.", 9-i, pool.getNumActive()); } // 3, 9, 15 fail passivation. assertEquals(7,pool.getNumIdle()); assertEquals(new Integer(19), pool.borrowObject()); assertEquals(new Integer(17), pool.borrowObject()); assertEquals(new Integer(13), pool.borrowObject()); assertEquals(new Integer(11), pool.borrowObject()); assertEquals(new Integer(7), pool.borrowObject()); assertEquals(new Integer(5), pool.borrowObject()); assertEquals(new Integer(1), pool.borrowObject()); } /** * Verifies that validation and passivation failures returning objects are handled * properly - instances destroyed and not returned to the pool, but no exceptions propagated. */ public void testBorrowReturnWithSometimesInvalidObjects() throws Exception { SelectiveFactory factory = new SelectiveFactory(); ObjectPool pool = new StackObjectPool(factory, 20); Integer[] obj = new Integer[10]; for(int i=0;i<10;i++) { obj[i] = pool.borrowObject(); assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive()); } factory.setValidateSelectively(true); // Even numbers fail validation factory.setPassivateSelectively(true); // Multiples of 3 fail passivation for(int i=0;i<10;i++) { pool.returnObject(obj[i]); assertEquals("Each time we return, get one less active.", 9-i, pool.getNumActive()); } // 0,2,4,6,8 fail validation, 3, 9 fail passivation - 3 left. assertEquals(3,pool.getNumIdle()); } public void testVariousConstructors() throws Exception { { StackObjectPool pool = new StackObjectPool(); assertNotNull(pool); } { StackObjectPool pool = new StackObjectPool(10); assertNotNull(pool); } { StackObjectPool pool = new StackObjectPool(10,5); assertNotNull(pool); } { StackObjectPool pool = new StackObjectPool(null); assertNotNull(pool); } { StackObjectPool pool = new StackObjectPool(null,10); assertNotNull(pool); } { StackObjectPool pool = new StackObjectPool(null,10,5); assertNotNull(pool); } } /** * Verify that out of range constructor arguments are ignored. */ public void testMaxIdleInitCapacityOutOfRange() throws Exception { SimpleFactory factory = new SimpleFactory(); StackObjectPool pool = new StackObjectPool(factory, -1, 0); assertEquals(pool.getMaxSleeping(), StackObjectPool.DEFAULT_MAX_SLEEPING); pool.addObject(); pool.close(); } /** * Verifies that when returning objects cause maxSleeping exceeded, oldest instances * are destroyed to make room for returning objects. */ public void testReturnObjectDiscardOrder() throws Exception { SelectiveFactory factory = new SelectiveFactory(); ObjectPool pool = new StackObjectPool(factory, 3); // borrow more objects than the pool can hold Integer i0 = pool.borrowObject(); Integer i1 = pool.borrowObject(); Integer i2 = pool.borrowObject(); Integer i3 = pool.borrowObject(); // tests // return as many as the pool will hold. pool.returnObject(i0); pool.returnObject(i1); pool.returnObject(i2); // the pool should now be full. assertEquals("No returned objects should have been destroyed yet.", 0, factory.getDestroyed().size()); // cause the pool to discard a stale object. pool.returnObject(i3); assertEquals("One object should have been destroyed.", 1, factory.getDestroyed().size()); // check to see what object was destroyed Integer d = factory.getDestroyed().get(0); assertEquals("Destoryed object should be the stalest object.", i0, d); } /** * Verifies that exceptions thrown by factory activate method are not propagated to * the caller. Objects that throw on activate are destroyed and if none succeed, * the caller gets NoSuchElementException. */ public void testExceptionOnActivate() throws Exception { SelectiveFactory factory = new SelectiveFactory(); ObjectPool pool = new StackObjectPool(factory); pool.addObject(); pool.addObject(); factory.setThrowOnActivate(true); try { pool.borrowObject(); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException ex) { // expected } assertEquals(0, pool.getNumIdle()); assertEquals(0, pool.getNumActive()); } /** * Verifies that exceptions thrown by factory destroy are swallowed * by both addObject and returnObject. */ public void testExceptionOnDestroy() throws Exception { SelectiveFactory factory = new SelectiveFactory(); ObjectPool pool = new StackObjectPool(factory, 2); factory.setThrowOnDestroy(true); for (int i = 0; i < 3; i++) { pool.addObject(); // Third one will destroy, exception should be swallowed } assertEquals(2, pool.getNumIdle()); Integer[] objects = new Integer[3]; for (int i = 0; i < 3; i++) { objects[i] = pool.borrowObject(); } for (int i = 0; i < 3; i++) { pool.returnObject(objects[i]); // Third triggers destroy } assertEquals(2, pool.getNumIdle()); } /** * Verifies that addObject propagates exceptions thrown by * factory passivate, but returnObject swallows these. */ public void testExceptionOnPassivate() throws Exception { SelectiveFactory factory = new SelectiveFactory(); ObjectPool pool = new StackObjectPool(factory, 2); factory.setThrowOnPassivate(true); // addObject propagates try { pool.addObject(); fail("Expecting IntegerFactoryException"); } catch (IntegerFactoryException ex) { assertEquals("passivateObject", ex.getType()); assertEquals(0, ex.getValue()); } assertEquals(0, pool.getNumIdle()); // returnObject swallows Integer obj = pool.borrowObject(); pool.returnObject(obj); assertEquals(0, pool.getNumIdle()); } /** * Verifies that validation exceptions always propagate */ public void testExceptionOnValidate() throws Exception { SelectiveFactory factory = new SelectiveFactory(); ObjectPool pool = new StackObjectPool(factory, 2); factory.setThrowOnValidate(true); // addObject try { pool.addObject(); fail("Expecting IntegerFactoryException"); } catch (IntegerFactoryException ex) { assertEquals("validateObject", ex.getType()); } assertEquals(0, pool.getNumIdle()); // returnObject factory.setThrowOnValidate(false); Integer obj = pool.borrowObject(); factory.setThrowOnValidate(true); try { pool.returnObject(obj); fail("Expecting IntegerFactoryException"); } catch (IntegerFactoryException ex) { assertEquals("validateObject", ex.getType()); } assertEquals(0, pool.getNumIdle()); // borrowObject - throws NoSuchElementException try { pool.borrowObject(); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException ex) { // Expected } } /** * Verifies that exceptions thrown by makeObject are propagated. */ public void testExceptionOnMake() throws Exception { SelectiveFactory factory = new SelectiveFactory(); factory.setThrowOnMake(true); ObjectPool pool = new StackObjectPool(factory); try { pool.borrowObject(); fail("Expecting IntegerFactoryException"); } catch (IntegerFactoryException ex) { assertEquals("makeObject", ex.getType()); } try { pool.addObject(); fail("Expecting IntegerFactoryException"); } catch (IntegerFactoryException ex) { assertEquals("makeObject", ex.getType()); } } /** * Verifies NoSuchElementException when the factory returns a null object in borrowObject */ public void testMakeNull() throws Exception { SelectiveFactory factory = new SelectiveFactory(); ObjectPool pool = new StackObjectPool(factory); factory.setMakeNull(true); try { pool.borrowObject(); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException ex) { // Expected } } /** * Verifies that initIdleCapacity is not a hard limit, but maxIdle is. */ public void testInitIdleCapacityExceeded() throws Exception { PoolableObjectFactory factory = new SimpleFactory(); ObjectPool pool = new StackObjectPool(factory, 2, 1); pool.addObject(); pool.addObject(); assertEquals(2, pool.getNumIdle()); pool.close(); pool = new StackObjectPool(factory, 1, 2); pool.addObject(); pool.addObject(); assertEquals(1, pool.getNumIdle()); } /** * Verifies close contract - idle instances are destroyed, returning instances * are destroyed, add/borrowObject throw IllegalStateException. */ @Override public void testClose() throws Exception { SelectiveFactory factory = new SelectiveFactory(); ObjectPool pool = new StackObjectPool(factory); pool.addObject(); // 0 pool.addObject(); // 1 pool.addObject(); // 2 Integer two = pool.borrowObject(); assertEquals(2, two.intValue()); pool.close(); assertEquals(0, pool.getNumIdle()); assertEquals(1, pool.getNumActive()); List destroyed = factory.getDestroyed(); assertEquals(2, destroyed.size()); assertTrue(destroyed.contains(new Integer(0))); assertTrue(destroyed.contains(new Integer(0))); pool.returnObject(two); assertTrue(destroyed.contains(two)); try { pool.addObject(); fail("Expecting IllegalStateException"); } catch (IllegalStateException ex) { // Expected } try { pool.borrowObject(); fail("Expecting IllegalStateException"); } catch (IllegalStateException ex) { // Expected } } /** * Simple factory that creates Integers. Validation and other factory methods * always succeed. */ static class SimpleFactory implements PoolableObjectFactory { int counter = 0; public String makeObject() { return String.valueOf(counter++); } public void destroyObject(String obj) { } public boolean validateObject(String obj) { return true; } public void activateObject(String obj) { } public void passivateObject(String obj) { } } /** * Integer factory that fails validation and other factory methods "selectively" and * tracks object destruction. */ static class SelectiveFactory implements PoolableObjectFactory { private List destroyed = new ArrayList(); private int counter = 0; private boolean validateSelectively = false; // true <-> validate returns false for even Integers private boolean passivateSelectively = false; // true <-> passivate throws RTE if Integer = 0 mod 3 private boolean throwOnDestroy = false; // true <-> destroy throws RTE (always) private boolean throwOnActivate = false; // true <-> activate throws RTE (always) private boolean throwOnMake = false; // true <-> make throws RTE (always) private boolean throwOnValidate= false; // true <-> validate throws RTE (always) private boolean throwOnPassivate = false; // true <-> passivate throws RTE (always) private boolean makeNull = false; // true <-> make returns null public Integer makeObject() { if (throwOnMake) { final int next = counter + 1; throw new IntegerFactoryException("makeObject", next); } else { return makeNull? null : new Integer(counter++); } } public void destroyObject(Integer obj) { if (throwOnDestroy) { final Integer integer = obj; throw new IntegerFactoryException("destroyObject", integer.intValue()); } destroyed.add(obj); } public boolean validateObject(Integer obj) { if (throwOnValidate) { final Integer integer = obj; throw new IntegerFactoryException("validateObject", integer.intValue()); } if (validateSelectively) { // only odd objects are valid return ((obj.intValue() % 2) == 1); } return true; } public void activateObject(Integer obj) { if (throwOnActivate) { final Integer integer = obj; throw new IntegerFactoryException("activateObject", integer.intValue()); } } public void passivateObject(Integer obj) { if (throwOnPassivate) { final Integer integer = obj; throw new IntegerFactoryException("passivateObject", integer.intValue()); } if (passivateSelectively) { final Integer integer = obj; if (integer.intValue() % 3 == 0) { throw new IntegerFactoryException("passivateObject", integer.intValue()); } } } public List getDestroyed() { return destroyed; } public void setCounter(int counter) { this.counter = counter; } public void setValidateSelectively(boolean validateSelectively) { this.validateSelectively = validateSelectively; } public void setPassivateSelectively(boolean passivateSelectively) { this.passivateSelectively = passivateSelectively; } public void setThrowOnDestroy(boolean throwOnDestroy) { this.throwOnDestroy = throwOnDestroy; } public void setThrowOnActivate(boolean throwOnActivate) { this.throwOnActivate = throwOnActivate; } public void setThrowOnMake(boolean throwOnMake) { this.throwOnMake = throwOnMake; } public void setThrowOnPassivate(boolean throwOnPassivate) { this.throwOnPassivate = throwOnPassivate; } public void setThrowOnValidate(boolean throwOnValidate) { this.throwOnValidate = throwOnValidate; } public void setMakeNull(boolean makeNull) { this.makeNull = makeNull; } } static class IntegerFactoryException extends RuntimeException { private String type; private int value; public IntegerFactoryException(String type, int value) { super(type + " failed. Value: " + value); this.type = type; this.value = value; } public String getType() { return type; } public int getValue() { return value; } } @Override protected boolean isLifo() { return true; } @Override protected boolean isFifo() { return false; } } commons-pool-1.6-src/src/test/org/apache/commons/pool/impl/TestStackObjectPoolFactory.java100644 0 0 5020 11701070262 27133 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.impl; import org.apache.commons.pool.MethodCallPoolableObjectFactory; import org.apache.commons.pool.ObjectPoolFactory; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.TestObjectPoolFactory; /** * Tests for {@link StackObjectPoolFactory}. * * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestStackObjectPoolFactory extends TestObjectPoolFactory { public TestStackObjectPoolFactory(final String name) { super(name); } @Override protected ObjectPoolFactory makeFactory(final PoolableObjectFactory objectFactory) throws UnsupportedOperationException { return new StackObjectPoolFactory(objectFactory); } public void testConstructors() throws Exception { StackObjectPoolFactory factory = new StackObjectPoolFactory(); factory.createPool().close(); factory = new StackObjectPoolFactory(1); StackObjectPool pool = (StackObjectPool)factory.createPool(); pool.close(); factory = new StackObjectPoolFactory(1, 1); pool = (StackObjectPool)factory.createPool(); pool.close(); factory = new StackObjectPoolFactory(new MethodCallPoolableObjectFactory(), 1); pool = (StackObjectPool)factory.createPool(); Integer a = pool.borrowObject(); Integer b = pool.borrowObject(); pool.returnObject(a); pool.returnObject(b); assertEquals(1, pool.getNumIdle()); pool.close(); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/MethodCall.java100644 0 0 7170 11701070262 23000 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * Holds method names, parameters, and return values for tracing method calls. * * @author Sandy McArthur * @version $Revision: 1222710 $ $Date: 2011-12-23 10:58:12 -0500 (Fri, 23 Dec 2011) $ */ public class MethodCall { private final String name; private final List params; private Object returned; public MethodCall(final String name) { this(name, null); } public MethodCall(final String name, final Object param) { this(name, Collections.singletonList(param)); } public MethodCall(final String name, final Object param1, final Object param2) { this(name, Arrays.asList(new Object[] {param1, param2})); } public MethodCall(final String name, final List params) { if (name == null) { throw new IllegalArgumentException("name must not be null."); } this.name = name; if (params != null) { this.params = params; } else { this.params = Collections.EMPTY_LIST; } } public String getName() { return name; } public List getParams() { return params; } public Object getReturned() { return returned; } public void setReturned(final Object returned) { this.returned = returned; } public MethodCall returned(Object obj) { setReturned(obj); return this; } @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final MethodCall that = (MethodCall)o; if (name != null ? !name.equals(that.name) : that.name != null) return false; if (params != null ? !params.equals(that.params) : that.params != null) return false; if (returned != null ? !returned.equals(that.returned) : that.returned != null) return false; return true; } @Override public int hashCode() { int result; result = (name != null ? name.hashCode() : 0); result = 29 * result + (params != null ? params.hashCode() : 0); result = 29 * result + (returned != null ? returned.hashCode() : 0); return result; } @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("MethodCall"); sb.append("{name='").append(name).append('\''); if (!params.isEmpty()) { sb.append(", params=").append(params); } if (returned != null) { sb.append(", returned=").append(returned); } sb.append('}'); return sb.toString(); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/MethodCallPoolableObjectFactory.java100644 0 0 11455 11701070262 27156 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import java.util.ArrayList; import java.util.List; /** * A poolable object factory that tracks how {@link MethodCall methods are called}. * * @author Sandy McArthur * @version $Revision: 1222710 $ $Date: 2011-12-23 10:58:12 -0500 (Fri, 23 Dec 2011) $ * @see MethodCall */ public class MethodCallPoolableObjectFactory implements PoolableObjectFactory { private final List methodCalls = new ArrayList(); private int count = 0; private boolean valid = true; private boolean makeObjectFail; private boolean activateObjectFail; private boolean validateObjectFail; private boolean passivateObjectFail; private boolean destroyObjectFail; public void reset() { count = 0; getMethodCalls().clear(); setMakeObjectFail(false); setActivateObjectFail(false); setValid(true); setValidateObjectFail(false); setPassivateObjectFail(false); setDestroyObjectFail(false); } public List getMethodCalls() { return methodCalls; } public int getCurrentCount() { return count; } public void setCurrentCount(final int count) { this.count = count; } public boolean isMakeObjectFail() { return makeObjectFail; } public void setMakeObjectFail(final boolean makeObjectFail) { this.makeObjectFail = makeObjectFail; } public boolean isDestroyObjectFail() { return destroyObjectFail; } public void setDestroyObjectFail(final boolean destroyObjectFail) { this.destroyObjectFail = destroyObjectFail; } public boolean isValid() { return valid; } public void setValid(final boolean valid) { this.valid = valid; } public boolean isValidateObjectFail() { return validateObjectFail; } public void setValidateObjectFail(final boolean validateObjectFail) { this.validateObjectFail = validateObjectFail; } public boolean isActivateObjectFail() { return activateObjectFail; } public void setActivateObjectFail(final boolean activateObjectFail) { this.activateObjectFail = activateObjectFail; } public boolean isPassivateObjectFail() { return passivateObjectFail; } public void setPassivateObjectFail(final boolean passivateObjectFail) { this.passivateObjectFail = passivateObjectFail; } public Integer makeObject() throws Exception { final MethodCall call = new MethodCall("makeObject"); methodCalls.add(call); int count = this.count++; if (makeObjectFail) { throw new PrivateException("makeObject"); } final Integer obj = new Integer(count); call.setReturned(obj); return obj; } public void activateObject(final Integer obj) throws Exception { methodCalls.add(new MethodCall("activateObject", obj)); if (activateObjectFail) { throw new PrivateException("activateObject"); } } public boolean validateObject(final Integer obj) { final MethodCall call = new MethodCall("validateObject", obj); methodCalls.add(call); if (validateObjectFail) { throw new PrivateException("validateObject"); } final boolean r = valid; call.returned(new Boolean(r)); return r; } public void passivateObject(final Integer obj) throws Exception { methodCalls.add(new MethodCall("passivateObject", obj)); if (passivateObjectFail) { throw new PrivateException("passivateObject"); } } public void destroyObject(final Integer obj) throws Exception { methodCalls.add(new MethodCall("destroyObject", obj)); if (destroyObjectFail) { throw new PrivateException("destroyObject"); } } } commons-pool-1.6-src/src/test/org/apache/commons/pool/performance/PerformanceTest.java100644 0 0 15077 11701070262 26413 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.performance; import org.apache.commons.pool.impl.GenericObjectPool; /** * Multi-thread performance test * * @author Dirk Verbeeck * @version $Revision: 1221705 $ $Date: 2011-12-21 08:03:54 -0500 (Wed, 21 Dec 2011) $ */ public class PerformanceTest { private int logLevel = 0; private int nrIterations = 5; private GenericObjectPool pool; private boolean start = false; private volatile int waiting = 0; private volatile int complete = 0; private volatile long totalBorrowTime = 0; private volatile long totalReturnTime = 0; private volatile int nrSamples = 0; public void setLogLevel(int i) { logLevel = i; } private void init() { start = false; waiting = 0; complete = 0; totalBorrowTime = 0; totalReturnTime = 0; nrSamples = 0; } class MyThread implements Runnable { long borrowTime; long returnTime; public void runOnce() { try { waiting++; if (logLevel >= 5) { String name = "thread" + Thread.currentThread().getName(); System.out.println(name + " waiting: " + waiting + " complete: " + complete); } long bbegin = System.currentTimeMillis(); Integer o = pool.borrowObject(); long bend = System.currentTimeMillis(); waiting--; do { Thread.yield(); } while (!start); if (logLevel >= 3) { String name = "thread" + Thread.currentThread().getName(); System.out.println(name + " waiting: " + waiting + " complete: " + complete); } long rbegin = System.currentTimeMillis(); pool.returnObject(o); long rend = System.currentTimeMillis(); Thread.yield(); complete++; borrowTime = (bend-bbegin); returnTime = (rend-rbegin); } catch (Exception e) { e.printStackTrace(); } } public void run() { runOnce(); // warmup for (int i = 0; i= 2) { String name = "thread" + Thread.currentThread().getName(); System.out.println( "result " + nrSamples + "\t" + name + "\t" + "borrow time: " + borrowTime + "\t" + "return time: " + returnTime + "\t" + "waiting: " + waiting + "\t" + "complete: " + complete); } } } } private void run(int nrIterations, int nrThreads, int maxActive, int maxIdle) { this.nrIterations = nrIterations; init(); SleepingObjectFactory factory = new SleepingObjectFactory(); if (logLevel >= 4) { factory.setDebug(true); } pool = new GenericObjectPool(factory); pool.setMaxActive(maxActive); pool.setMaxIdle(maxIdle); pool.setTestOnBorrow(true); Thread[] threads = new Thread[nrThreads]; for (int i = 0; i < threads.length; i++) { threads[i]= new Thread(new MyThread(), Integer.toString(i)); Thread.yield(); } if (logLevel >= 1) { System.out.println("created"); } Thread.yield(); for (int i = 0; i < threads.length; i++) { threads[i].start(); Thread.yield(); } if (logLevel >= 1) { System.out.println("started"); } Thread.yield(); start = true; if (logLevel >= 1) { System.out.println("go"); } Thread.yield(); for (int i = 0; i < threads.length; i++) { try { threads[i].join(); } catch (InterruptedException e) { e.printStackTrace(); } } if (logLevel >= 1) { System.out.println("finish"); } System.out.println("-----------------------------------------"); System.out.println("nrIterations: " + nrIterations); System.out.println("nrThreads: " + nrThreads); System.out.println("maxActive: " + maxActive); System.out.println("maxIdle: " + maxIdle); System.out.println("nrSamples: " + nrSamples); System.out.println("totalBorrowTime: " + totalBorrowTime); System.out.println("totalReturnTime: " + totalReturnTime); System.out.println("avg BorrowTime: " + totalBorrowTime/nrSamples); System.out.println("avg ReturnTime: " + totalReturnTime/nrSamples); } public static void main(String[] args) { PerformanceTest test = new PerformanceTest(); test.setLogLevel(0); System.out.println("Increase threads"); test.run(1, 50, 5, 5); test.run(1, 100, 5, 5); test.run(1, 200, 5, 5); test.run(1, 400, 5, 5); System.out.println("Increase threads & poolsize"); test.run(1, 50, 5, 5); test.run(1, 100, 10, 10); test.run(1, 200, 20, 20); test.run(1, 400, 40, 40); System.out.println("Increase maxIdle"); test.run(1, 400, 40, 5); test.run(1, 400, 40, 40); // System.out.println("Show creation/destruction of objects"); // test.setLogLevel(4); // test.run(1, 400, 40, 5); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/performance/SleepingObjectFactory.java100644 0 0 4742 11701070262 27514 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool.performance; import org.apache.commons.pool.PoolableObjectFactory; /** * Sleepy ObjectFactory (everything takes a while longer) * * @author Dirk Verbeeck * @version $Revision: 1221705 $ $Date: 2011-12-21 08:03:54 -0500 (Wed, 21 Dec 2011) $ */ public class SleepingObjectFactory implements PoolableObjectFactory { private int counter = 0; private boolean debug = false; public Integer makeObject() throws Exception { Integer obj = new Integer(counter++); debug("makeObject", obj); sleep(500); return obj; } public void destroyObject(Integer obj) throws Exception { debug("destroyObject", obj); sleep(250); } public boolean validateObject(Integer obj) { debug("validateObject", obj); sleep(30); return true; } public void activateObject(Integer obj) throws Exception { debug("activateObject", obj); sleep(10); } public void passivateObject(Integer obj) throws Exception { debug("passivateObject", obj); sleep(10); } private void debug(String method, Object obj) { if (debug) { String thread = "thread" + Thread.currentThread().getName(); System.out.println(thread + ": " + method + " " + obj); } } private void sleep(long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { } } public boolean isDebug() { return debug; } public void setDebug(boolean b) { debug = b; } } commons-pool-1.6-src/src/test/org/apache/commons/pool/PrivateException.java100644 0 0 2052 11701070262 24247 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * An exception that only is thrown by these tests. */ public class PrivateException extends RuntimeException { public PrivateException(final String message) { super(message); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/TestBaseKeyedObjectPool.java100644 0 0 33556 11701070262 25470 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestBaseKeyedObjectPool extends TestKeyedObjectPool { private KeyedObjectPool _pool = null; public TestBaseKeyedObjectPool(final String testName) { super(testName); } @Override protected KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory) { if (this.getClass() != TestBaseKeyedObjectPool.class) { fail("Subclasses of TestBaseKeyedObjectPool must reimplement this method."); } throw new UnsupportedOperationException("BaseKeyedObjectPool isn't a complete implementation."); } /** * Create an {@link KeyedObjectPool} instance * that can contain at least mincapacity * idle and active objects, or * throw {@link IllegalArgumentException} * if such a pool cannot be created. */ protected KeyedObjectPool makeEmptyPool(int mincapacity) { if (this.getClass() != TestBaseKeyedObjectPool.class) { fail("Subclasses of TestBaseKeyedObjectPool must reimplement this method."); } throw new UnsupportedOperationException("BaseKeyedObjectPool isn't a complete implementation."); } /** * Return what we expect to be the nth * object (zero indexed) created by the pool * for the given key. */ protected V getNthObject(Object key, int n) { if (this.getClass() != TestBaseKeyedObjectPool.class) { fail("Subclasses of TestBaseKeyedObjectPool must reimplement this method."); } throw new UnsupportedOperationException("BaseKeyedObjectPool isn't a complete implementation."); } protected K makeKey(int n) { if (this.getClass() != TestBaseKeyedObjectPool.class) { fail("Subclasses of TestBaseKeyedObjectPool must reimplement this method."); } throw new UnsupportedOperationException("BaseKeyedObjectPool isn't a complete implementation."); } @Override public void setUp() throws Exception { super.setUp(); } @Override public void tearDown() throws Exception { _pool = null; super.tearDown(); } public void testUnsupportedOperations() throws Exception { if (!getClass().equals(TestBaseKeyedObjectPool.class)) { return; // skip redundant tests } KeyedObjectPool pool = new BaseKeyedObjectPool() { @Override public String borrowObject(String key) { return null; } @Override public void returnObject(String key, String obj) { } @Override public void invalidateObject(String key, String obj) { } }; try { pool.addObject("key"); fail("Expected UnsupportedOperationException"); } catch(UnsupportedOperationException e) { // expected } assertTrue("Negative expected.", pool.getNumIdle() < 0); assertTrue("Negative expected.", pool.getNumIdle("key") < 0); assertTrue("Negative expected.", pool.getNumActive() < 0); assertTrue("Negative expected.", pool.getNumActive("key") < 0); try { pool.clear(); fail("Expected UnsupportedOperationException"); } catch(UnsupportedOperationException e) { // expected } try { pool.clear("key"); fail("Expected UnsupportedOperationException"); } catch(UnsupportedOperationException e) { // expected } try { pool.setFactory(null); fail("Expected UnsupportedOperationException"); } catch(UnsupportedOperationException e) { // expected } pool.close(); // a no-op, probably should be remove } protected boolean isLifo() { if (getClass() != TestBaseKeyedObjectPool.class) { fail("Subclasses of TestBaseKeyedObjectPool must reimplement this method."); } return false; } protected boolean isFifo() { if (getClass() != TestBaseKeyedObjectPool.class) { fail("Subclasses of TestBaseKeyedObjectPool must reimplement this method."); } return false; } public void testBaseBorrowReturn() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException uoe) { return; // skip this test if unsupported } K keya = makeKey(0); V obj0 = _pool.borrowObject(keya); assertEquals(getNthObject(keya,0),obj0); V obj1 = _pool.borrowObject(keya); assertEquals(getNthObject(keya,1),obj1); V obj2 = _pool.borrowObject(keya); assertEquals(getNthObject(keya,2),obj2); _pool.returnObject(keya,obj2); obj2 = _pool.borrowObject(keya); assertEquals(getNthObject(keya,2),obj2); _pool.returnObject(keya,obj1); obj1 = _pool.borrowObject(keya); assertEquals(getNthObject(keya,1),obj1); _pool.returnObject(keya,obj0); _pool.returnObject(keya,obj2); obj2 = _pool.borrowObject(keya); if (isLifo()) { assertEquals(getNthObject(keya,2),obj2); } if (isFifo()) { assertEquals(getNthObject(keya,0),obj2); } obj0 = _pool.borrowObject(keya); if (isLifo()) { assertEquals(getNthObject(keya,0),obj0); } if (isFifo()) { assertEquals(getNthObject(keya,2),obj0); } } public void testBaseBorrow() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException uoe) { return; // skip this test if unsupported } K keya = makeKey(0); K keyb = makeKey(1); assertEquals("1",getNthObject(keya,0),_pool.borrowObject(keya)); assertEquals("2",getNthObject(keyb,0),_pool.borrowObject(keyb)); assertEquals("3",getNthObject(keyb,1),_pool.borrowObject(keyb)); assertEquals("4",getNthObject(keya,1),_pool.borrowObject(keya)); assertEquals("5",getNthObject(keyb,2),_pool.borrowObject(keyb)); assertEquals("6",getNthObject(keya,2),_pool.borrowObject(keya)); } public void testBaseNumActiveNumIdle() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException uoe) { return; // skip this test if unsupported } K keya = makeKey(0); assertEquals(0,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); V obj0 = _pool.borrowObject(keya); assertEquals(1,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); V obj1 = _pool.borrowObject(keya); assertEquals(2,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); _pool.returnObject(keya,obj1); assertEquals(1,_pool.getNumActive(keya)); assertEquals(1,_pool.getNumIdle(keya)); _pool.returnObject(keya,obj0); assertEquals(0,_pool.getNumActive(keya)); assertEquals(2,_pool.getNumIdle(keya)); // cast to KeyedObjectPool to use the wrong key type. @SuppressWarnings("unchecked") final KeyedObjectPool rawPool = (KeyedObjectPool)_pool; assertEquals(0,rawPool.getNumActive("xyzzy12345")); assertEquals(0,rawPool.getNumIdle("xyzzy12345")); } public void testBaseNumActiveNumIdle2() throws Exception { try { _pool = makeEmptyPool(6); } catch(UnsupportedOperationException uoe) { return; // skip this test if unsupported } K keya = makeKey(0); K keyb = makeKey(1); assertEquals(0,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); assertEquals(0,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); assertEquals(0,_pool.getNumActive(keyb)); assertEquals(0,_pool.getNumIdle(keyb)); V objA0 = _pool.borrowObject(keya); V objB0 = _pool.borrowObject(keyb); assertEquals(2,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); assertEquals(1,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); assertEquals(1,_pool.getNumActive(keyb)); assertEquals(0,_pool.getNumIdle(keyb)); V objA1 = _pool.borrowObject(keya); V objB1 = _pool.borrowObject(keyb); assertEquals(4,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); assertEquals(2,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); assertEquals(2,_pool.getNumActive(keyb)); assertEquals(0,_pool.getNumIdle(keyb)); _pool.returnObject(keya,objA0); _pool.returnObject(keyb,objB0); assertEquals(2,_pool.getNumActive()); assertEquals(2,_pool.getNumIdle()); assertEquals(1,_pool.getNumActive(keya)); assertEquals(1,_pool.getNumIdle(keya)); assertEquals(1,_pool.getNumActive(keyb)); assertEquals(1,_pool.getNumIdle(keyb)); _pool.returnObject(keya,objA1); _pool.returnObject(keyb,objB1); assertEquals(0,_pool.getNumActive()); assertEquals(4,_pool.getNumIdle()); assertEquals(0,_pool.getNumActive(keya)); assertEquals(2,_pool.getNumIdle(keya)); assertEquals(0,_pool.getNumActive(keyb)); assertEquals(2,_pool.getNumIdle(keyb)); } public void testBaseClear() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException uoe) { return; // skip this test if unsupported } K keya = makeKey(0); assertEquals(0,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); V obj0 = _pool.borrowObject(keya); V obj1 = _pool.borrowObject(keya); assertEquals(2,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); _pool.returnObject(keya,obj1); _pool.returnObject(keya,obj0); assertEquals(0,_pool.getNumActive(keya)); assertEquals(2,_pool.getNumIdle(keya)); _pool.clear(keya); assertEquals(0,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); Object obj2 = _pool.borrowObject(keya); assertEquals(getNthObject(keya,2),obj2); } public void testBaseInvalidateObject() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException uoe) { return; // skip this test if unsupported } K keya = makeKey(0); assertEquals(0,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); V obj0 = _pool.borrowObject(keya); V obj1 = _pool.borrowObject(keya); assertEquals(2,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); _pool.invalidateObject(keya,obj0); assertEquals(1,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); _pool.invalidateObject(keya,obj1); assertEquals(0,_pool.getNumActive(keya)); assertEquals(0,_pool.getNumIdle(keya)); } public void testBaseAddObject() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException uoe) { return; // skip this test if unsupported } K key = makeKey(0); try { assertEquals(0,_pool.getNumIdle()); assertEquals(0,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle(key)); assertEquals(0,_pool.getNumActive(key)); _pool.addObject(key); assertEquals(1,_pool.getNumIdle()); assertEquals(0,_pool.getNumActive()); assertEquals(1,_pool.getNumIdle(key)); assertEquals(0,_pool.getNumActive(key)); V obj = _pool.borrowObject(key); assertEquals(getNthObject(key,0),obj); assertEquals(0,_pool.getNumIdle()); assertEquals(1,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle(key)); assertEquals(1,_pool.getNumActive(key)); _pool.returnObject(key,obj); assertEquals(1,_pool.getNumIdle()); assertEquals(0,_pool.getNumActive()); assertEquals(1,_pool.getNumIdle(key)); assertEquals(0,_pool.getNumActive(key)); } catch(UnsupportedOperationException e) { return; // skip this test if one of those calls is unsupported } } } commons-pool-1.6-src/src/test/org/apache/commons/pool/TestBaseKeyedPoolableObjectFactory.java100644 0 0 3361 11701070262 27613 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import junit.framework.TestCase; /** * @author Rodney Waldhoff * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestBaseKeyedPoolableObjectFactory extends TestCase { public TestBaseKeyedPoolableObjectFactory(String testName) { super(testName); } public void testDefaultMethods() throws Exception { KeyedPoolableObjectFactory factory = new BaseKeyedPoolableObjectFactory() { @Override public Object makeObject(String key) throws Exception { return null; } }; factory.activateObject("key",null); // a no-op factory.passivateObject("key",null); // a no-op factory.destroyObject("key",null); // a no-op assertTrue(factory.validateObject("key",null)); // constant true } } commons-pool-1.6-src/src/test/org/apache/commons/pool/TestBaseObjectPool.java100644 0 0 23552 11701070262 24501 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestBaseObjectPool extends TestObjectPool { private ObjectPool _pool = null; public TestBaseObjectPool(String testName) { super(testName); } protected ObjectPool makeEmptyPool(int mincapacity) { if (this.getClass() != TestBaseObjectPool.class) { fail("Subclasses of TestBaseObjectPool must reimplement this method."); } throw new UnsupportedOperationException("BaseObjectPool isn't a complete implementation."); } @Override protected ObjectPool makeEmptyPool(final PoolableObjectFactory factory) { if (this.getClass() != TestBaseObjectPool.class) { fail("Subclasses of TestBaseObjectPool must reimplement this method."); } throw new UnsupportedOperationException("BaseObjectPool isn't a complete implementation."); } protected T getNthObject(final int n) { if (this.getClass() != TestBaseObjectPool.class) { fail("Subclasses of TestBaseObjectPool must reimplement this method."); } throw new UnsupportedOperationException("BaseObjectPool isn't a complete implementation."); } protected boolean isLifo() { if (this.getClass() != TestBaseObjectPool.class) { fail("Subclasses of TestBaseObjectPool must reimplement this method."); } return false; } protected boolean isFifo() { if (this.getClass() != TestBaseObjectPool.class) { fail("Subclasses of TestBaseObjectPool must reimplement this method."); } return false; } // tests public void testUnsupportedOperations() throws Exception { if (!getClass().equals(TestBaseObjectPool.class)) { return; // skip redundant tests } ObjectPool pool = new BaseObjectPool() { @Override public Object borrowObject() { return null; } @Override public void returnObject(Object obj) { } @Override public void invalidateObject(Object obj) { } }; assertTrue("Negative expected.", pool.getNumIdle() < 0); assertTrue("Negative expected.", pool.getNumActive() < 0); try { pool.clear(); fail("Expected UnsupportedOperationException"); } catch(UnsupportedOperationException e) { // expected } try { pool.addObject(); fail("Expected UnsupportedOperationException"); } catch(UnsupportedOperationException e) { // expected } try { pool.setFactory(null); fail("Expected UnsupportedOperationException"); } catch(UnsupportedOperationException e) { // expected } } public void testClose() throws Exception { ObjectPool pool = new BaseObjectPool() { @Override public Object borrowObject() { return null; } @Override public void returnObject(Object obj) { } @Override public void invalidateObject(Object obj) { } }; pool.close(); pool.close(); // should not error as of Pool 2.0. } public void testBaseBorrow() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException e) { return; // skip this test if unsupported } assertEquals(getNthObject(0),_pool.borrowObject()); assertEquals(getNthObject(1),_pool.borrowObject()); assertEquals(getNthObject(2),_pool.borrowObject()); } public void testBaseAddObject() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException e) { return; // skip this test if unsupported } try { assertEquals(0,_pool.getNumIdle()); assertEquals(0,_pool.getNumActive()); _pool.addObject(); assertEquals(1,_pool.getNumIdle()); assertEquals(0,_pool.getNumActive()); T obj = _pool.borrowObject(); assertEquals(getNthObject(0),obj); assertEquals(0,_pool.getNumIdle()); assertEquals(1,_pool.getNumActive()); _pool.returnObject(obj); assertEquals(1,_pool.getNumIdle()); assertEquals(0,_pool.getNumActive()); } catch(UnsupportedOperationException e) { return; // skip this test if one of those calls is unsupported } } public void testBaseBorrowReturn() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException e) { return; // skip this test if unsupported } T obj0 = _pool.borrowObject(); assertEquals(getNthObject(0),obj0); T obj1 = _pool.borrowObject(); assertEquals(getNthObject(1),obj1); T obj2 = _pool.borrowObject(); assertEquals(getNthObject(2),obj2); _pool.returnObject(obj2); obj2 = _pool.borrowObject(); assertEquals(getNthObject(2),obj2); _pool.returnObject(obj1); obj1 = _pool.borrowObject(); assertEquals(getNthObject(1),obj1); _pool.returnObject(obj0); _pool.returnObject(obj2); obj2 = _pool.borrowObject(); if (isLifo()) { assertEquals(getNthObject(2),obj2); } if (isFifo()) { assertEquals(getNthObject(0),obj2); } obj0 = _pool.borrowObject(); if (isLifo()) { assertEquals(getNthObject(0),obj0); } if (isFifo()) { assertEquals(getNthObject(2),obj0); } } public void testBaseNumActiveNumIdle() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException e) { return; // skip this test if unsupported } assertEquals(0,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); T obj0 = _pool.borrowObject(); assertEquals(1,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); T obj1 = _pool.borrowObject(); assertEquals(2,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); _pool.returnObject(obj1); assertEquals(1,_pool.getNumActive()); assertEquals(1,_pool.getNumIdle()); _pool.returnObject(obj0); assertEquals(0,_pool.getNumActive()); assertEquals(2,_pool.getNumIdle()); } public void testBaseClear() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException e) { return; // skip this test if unsupported } assertEquals(0,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); T obj0 = _pool.borrowObject(); T obj1 = _pool.borrowObject(); assertEquals(2,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); _pool.returnObject(obj1); _pool.returnObject(obj0); assertEquals(0,_pool.getNumActive()); assertEquals(2,_pool.getNumIdle()); _pool.clear(); assertEquals(0,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); Object obj2 = _pool.borrowObject(); assertEquals(getNthObject(2),obj2); } public void testBaseInvalidateObject() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException e) { return; // skip this test if unsupported } assertEquals(0,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); T obj0 = _pool.borrowObject(); T obj1 = _pool.borrowObject(); assertEquals(2,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); _pool.invalidateObject(obj0); assertEquals(1,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); _pool.invalidateObject(obj1); assertEquals(0,_pool.getNumActive()); assertEquals(0,_pool.getNumIdle()); } public void testBaseClosePool() throws Exception { try { _pool = makeEmptyPool(3); } catch(UnsupportedOperationException e) { return; // skip this test if unsupported } T obj = _pool.borrowObject(); _pool.returnObject(obj); _pool.close(); try { _pool.borrowObject(); fail("Expected IllegalStateException"); } catch(IllegalStateException e) { // expected } } } commons-pool-1.6-src/src/test/org/apache/commons/pool/TestBasePoolableObjectFactory.java100644 0 0 3254 11701070262 26632 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import junit.framework.TestCase; /** * @author Rodney Waldhoff * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestBasePoolableObjectFactory extends TestCase { public TestBasePoolableObjectFactory(String testName) { super(testName); } public void testDefaultMethods() throws Exception { PoolableObjectFactory factory = new BasePoolableObjectFactory() { @Override public Object makeObject() throws Exception { return null; } }; factory.activateObject(null); // a no-op factory.passivateObject(null); // a no-op factory.destroyObject(null); // a no-op assertTrue(factory.validateObject(null)); // constant true } } commons-pool-1.6-src/src/test/org/apache/commons/pool/TestKeyedObjectPool.java100644 0 0 51306 11701070262 24666 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; import junit.framework.TestCase; import org.apache.commons.pool.impl.GenericKeyedObjectPool; import org.apache.commons.pool.impl.StackKeyedObjectPool; /** * Abstract {@link TestCase} for {@link ObjectPool} implementations. * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222710 $ $Date: 2011-12-23 10:58:12 -0500 (Fri, 23 Dec 2011) $ */ public abstract class TestKeyedObjectPool extends TestCase { public TestKeyedObjectPool(String testName) { super(testName); } /** * Create an KeyedObjectPool with the specified factory. * The pool should be in a default configuration and conform to the expected * behaviors described in {@link KeyedObjectPool}. * Generally speaking there should be no limits on the various object counts. */ protected abstract KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory); protected final String KEY = "key"; public void testClosedPoolBehavior() throws Exception { final KeyedObjectPool pool; try { pool = makeEmptyPool(new BaseKeyedPoolableObjectFactory() { @Override public Integer makeObject(final Object key) throws Exception { return new Integer(1234567890); } }); } catch(UnsupportedOperationException uoe) { return; // test not supported } Integer o1 = pool.borrowObject(KEY); Integer o2 = pool.borrowObject(KEY); pool.close(); try { pool.addObject(KEY); fail("A closed pool must throw an IllegalStateException when addObject is called."); } catch (IllegalStateException ise) { // expected } try { pool.borrowObject(KEY); fail("A closed pool must throw an IllegalStateException when borrowObject is called."); } catch (IllegalStateException ise) { // expected } // The following should not throw exceptions just because the pool is closed. assertEquals("A closed pool shouldn't have any idle objects.", 0, pool.getNumIdle(KEY)); assertEquals("A closed pool shouldn't have any idle objects.", 0, pool.getNumIdle()); pool.getNumActive(); pool.getNumActive(KEY); pool.returnObject(KEY, o1); assertEquals("returnObject should not add items back into the idle object pool for a closed pool.", 0, pool.getNumIdle(KEY)); assertEquals("returnObject should not add items back into the idle object pool for a closed pool.", 0, pool.getNumIdle()); pool.invalidateObject(KEY, o2); pool.clear(KEY); pool.clear(); pool.close(); } private final Integer ZERO = new Integer(0); private final Integer ONE = new Integer(1); public void testKPOFAddObjectUsage() throws Exception { final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory(); final KeyedObjectPool pool; try { pool = makeEmptyPool(factory); } catch(UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); // addObject should make a new object, pasivate it and put it in the pool pool.addObject(KEY); expectedMethods.add(new MethodCall("makeObject", KEY).returned(ZERO)); if (pool instanceof StackKeyedObjectPool) { expectedMethods.add(new MethodCall( "validateObject", KEY, ZERO).returned(Boolean.TRUE)); } expectedMethods.add(new MethodCall("passivateObject", KEY, ZERO)); assertEquals(expectedMethods, factory.getMethodCalls()); //// Test exception handling of addObject reset(pool, factory, expectedMethods); // makeObject Exceptions should be propagated to client code from addObject factory.setMakeObjectFail(true); try { pool.addObject(KEY); fail("Expected addObject to propagate makeObject exception."); } catch (PrivateException pe) { // expected } expectedMethods.add(new MethodCall("makeObject", KEY)); assertEquals(expectedMethods, factory.getMethodCalls()); clear(factory, expectedMethods); // passivateObject Exceptions should be propagated to client code from addObject factory.setMakeObjectFail(false); factory.setPassivateObjectFail(true); try { pool.addObject(KEY); fail("Expected addObject to propagate passivateObject exception."); } catch (PrivateException pe) { // expected } expectedMethods.add(new MethodCall("makeObject", KEY).returned(ONE)); if (pool instanceof StackKeyedObjectPool) { expectedMethods.add(new MethodCall( "validateObject", KEY, ONE).returned(Boolean.TRUE)); } expectedMethods.add(new MethodCall("passivateObject", KEY, ONE)); assertEquals(expectedMethods, factory.getMethodCalls()); } public void testKPOFBorrowObjectUsages() throws Exception { final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory(); final KeyedObjectPool pool; try { pool = makeEmptyPool(factory); } catch(UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); Integer obj; if (pool instanceof GenericKeyedObjectPool) { ((GenericKeyedObjectPool) pool).setTestOnBorrow(true); } /// Test correct behavior code paths // existing idle object should be activated and validated pool.addObject(KEY); clear(factory, expectedMethods); obj = pool.borrowObject(KEY); expectedMethods.add(new MethodCall("activateObject", KEY, ZERO)); expectedMethods.add(new MethodCall("validateObject", KEY, ZERO).returned(Boolean.TRUE)); assertEquals(expectedMethods, factory.getMethodCalls()); pool.returnObject(KEY, obj); //// Test exception handling of borrowObject reset(pool, factory, expectedMethods); // makeObject Exceptions should be propagated to client code from borrowObject factory.setMakeObjectFail(true); try { obj = pool.borrowObject(KEY); fail("Expected borrowObject to propagate makeObject exception."); } catch (PrivateException pe) { // expected } expectedMethods.add(new MethodCall("makeObject", KEY)); assertEquals(expectedMethods, factory.getMethodCalls()); // when activateObject fails in borrowObject, a new object should be borrowed/created reset(pool, factory, expectedMethods); pool.addObject(KEY); clear(factory, expectedMethods); factory.setActivateObjectFail(true); expectedMethods.add(new MethodCall("activateObject", KEY, obj)); try { obj = pool.borrowObject(KEY); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException e) { //Activate should fail } // After idle object fails validation, new on is created and activation // fails again for the new one. expectedMethods.add(new MethodCall("makeObject", KEY).returned(ONE)); expectedMethods.add(new MethodCall("activateObject", KEY, ONE)); TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls()); // The exact timing of destroyObject is flexible here. assertEquals(expectedMethods, factory.getMethodCalls()); // when validateObject fails in borrowObject, a new object should be borrowed/created reset(pool, factory, expectedMethods); pool.addObject(KEY); clear(factory, expectedMethods); factory.setValidateObjectFail(true); // testOnBorrow is on, so this will throw when the newly created instance // fails validation try { obj = pool.borrowObject(KEY); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException ex) { // expected } // Activate, then validate for idle instance expectedMethods.add(new MethodCall("activateObject", KEY, ZERO)); expectedMethods.add(new MethodCall("validateObject", KEY, ZERO)); // Make new instance, activate succeeds, validate fails expectedMethods.add(new MethodCall("makeObject", KEY).returned(ONE)); expectedMethods.add(new MethodCall("activateObject", KEY, ONE)); expectedMethods.add(new MethodCall("validateObject", KEY, ONE)); TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls()); assertEquals(expectedMethods, factory.getMethodCalls()); } public void testKPOFReturnObjectUsages() throws Exception { final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory(); final KeyedObjectPool pool; try { pool = makeEmptyPool(factory); } catch(UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); Integer obj; /// Test correct behavior code paths obj = pool.borrowObject(KEY); clear(factory, expectedMethods); // returned object should be passivated pool.returnObject(KEY, obj); if (pool instanceof StackKeyedObjectPool) { expectedMethods.add(new MethodCall( "validateObject", KEY, obj).returned(Boolean.TRUE)); } expectedMethods.add(new MethodCall("passivateObject", KEY, obj)); assertEquals(expectedMethods, factory.getMethodCalls()); //// Test exception handling of returnObject reset(pool, factory, expectedMethods); // passivateObject should swallow exceptions and not add the object to the pool pool.addObject(KEY); pool.addObject(KEY); pool.addObject(KEY); assertEquals(3, pool.getNumIdle(KEY)); obj = pool.borrowObject(KEY); obj = pool.borrowObject(KEY); assertEquals(1, pool.getNumIdle(KEY)); assertEquals(2, pool.getNumActive(KEY)); clear(factory, expectedMethods); factory.setPassivateObjectFail(true); pool.returnObject(KEY, obj); if (pool instanceof StackKeyedObjectPool) { expectedMethods.add(new MethodCall( "validateObject", KEY, obj).returned(Boolean.TRUE)); } expectedMethods.add(new MethodCall("passivateObject", KEY, obj)); TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls()); // The exact timing of destroyObject is flexible here. assertEquals(expectedMethods, factory.getMethodCalls()); assertEquals(1, pool.getNumIdle(KEY)); // Not added assertEquals(1, pool.getNumActive(KEY)); // But not active reset(pool, factory, expectedMethods); obj = pool.borrowObject(KEY); clear(factory, expectedMethods); factory.setPassivateObjectFail(true); factory.setDestroyObjectFail(true); try { pool.returnObject(KEY, obj); if (!(pool instanceof GenericKeyedObjectPool)) { // ugh, 1.3-compat fail("Expecting destroyObject exception to be propagated"); } } catch (PrivateException ex) { // Expected } } public void testKPOFInvalidateObjectUsages() throws Exception { final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory(); final KeyedObjectPool pool; try { pool = makeEmptyPool(factory); } catch(UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); Integer obj; /// Test correct behavior code paths obj = pool.borrowObject(KEY); clear(factory, expectedMethods); // invalidated object should be destroyed pool.invalidateObject(KEY, obj); expectedMethods.add(new MethodCall("destroyObject", KEY, obj)); assertEquals(expectedMethods, factory.getMethodCalls()); //// Test exception handling of invalidateObject reset(pool, factory, expectedMethods); obj = pool.borrowObject(KEY); clear(factory, expectedMethods); factory.setDestroyObjectFail(true); try { pool.invalidateObject(KEY, obj); fail("Expecting destroy exception to propagate"); } catch (PrivateException ex) { // Expected } Thread.sleep(250); // could be defered TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls()); assertEquals(expectedMethods, factory.getMethodCalls()); } public void testKPOFClearUsages() throws Exception { final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory(); final KeyedObjectPool pool; try { pool = makeEmptyPool(factory); } catch(UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); /// Test correct behavior code paths PoolUtils.prefill(pool, KEY, 5); pool.clear(); //// Test exception handling clear should swallow destory object failures reset(pool, factory, expectedMethods); factory.setDestroyObjectFail(true); PoolUtils.prefill(pool, KEY, 5); pool.clear(); } public void testKPOFCloseUsages() throws Exception { final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory(); KeyedObjectPool pool; try { pool = makeEmptyPool(factory); } catch(UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); /// Test correct behavior code paths PoolUtils.prefill(pool, KEY, 5); pool.close(); //// Test exception handling close should swallow failures pool = makeEmptyPool(factory); reset(pool, factory, expectedMethods); factory.setDestroyObjectFail(true); PoolUtils.prefill(pool, KEY, 5); pool.close(); } public void testToString() throws Exception { final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory(); try { makeEmptyPool(factory).toString(); } catch(UnsupportedOperationException uoe) { return; // test not supported } } private void reset(final KeyedObjectPool pool, final FailingKeyedPoolableObjectFactory factory, final List expectedMethods) throws Exception { pool.clear(); clear(factory, expectedMethods); factory.reset(); } private void clear(final FailingKeyedPoolableObjectFactory factory, final List expectedMethods) { factory.getMethodCalls().clear(); expectedMethods.clear(); } protected static class FailingKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory { private final List methodCalls = new ArrayList(); private int count = 0; private boolean makeObjectFail; private boolean activateObjectFail; private boolean validateObjectFail; private boolean passivateObjectFail; private boolean destroyObjectFail; public FailingKeyedPoolableObjectFactory() { } public void reset() { count = 0; getMethodCalls().clear(); setMakeObjectFail(false); setActivateObjectFail(false); setValidateObjectFail(false); setPassivateObjectFail(false); setDestroyObjectFail(false); } public List getMethodCalls() { return methodCalls; } public int getCurrentCount() { return count; } public void setCurrentCount(final int count) { this.count = count; } public boolean isMakeObjectFail() { return makeObjectFail; } public void setMakeObjectFail(boolean makeObjectFail) { this.makeObjectFail = makeObjectFail; } public boolean isDestroyObjectFail() { return destroyObjectFail; } public void setDestroyObjectFail(boolean destroyObjectFail) { this.destroyObjectFail = destroyObjectFail; } public boolean isValidateObjectFail() { return validateObjectFail; } public void setValidateObjectFail(boolean validateObjectFail) { this.validateObjectFail = validateObjectFail; } public boolean isActivateObjectFail() { return activateObjectFail; } public void setActivateObjectFail(boolean activateObjectFail) { this.activateObjectFail = activateObjectFail; } public boolean isPassivateObjectFail() { return passivateObjectFail; } public void setPassivateObjectFail(boolean passivateObjectFail) { this.passivateObjectFail = passivateObjectFail; } public Integer makeObject(final Object key) throws Exception { final MethodCall call = new MethodCall("makeObject", key); methodCalls.add(call); int count = this.count++; if (makeObjectFail) { throw new PrivateException("makeObject"); } final Integer obj = new Integer(count); call.setReturned(obj); return obj; } public void activateObject(final Object key, final Integer obj) throws Exception { methodCalls.add(new MethodCall("activateObject", key, obj)); if (activateObjectFail) { throw new PrivateException("activateObject"); } } public boolean validateObject(final Object key, final Integer obj) { final MethodCall call = new MethodCall("validateObject", key, obj); methodCalls.add(call); if (validateObjectFail) { throw new PrivateException("validateObject"); } final boolean r = true; call.returned(new Boolean(r)); return r; } public void passivateObject(final Object key, final Integer obj) throws Exception { methodCalls.add(new MethodCall("passivateObject", key, obj)); if (passivateObjectFail) { throw new PrivateException("passivateObject"); } } public void destroyObject(final Object key, final Integer obj) throws Exception { methodCalls.add(new MethodCall("destroyObject", key, obj)); if (destroyObjectFail) { throw new PrivateException("destroyObject"); } } } } commons-pool-1.6-src/src/test/org/apache/commons/pool/TestKeyedObjectPoolFactory.java100644 0 0 5117 11701070262 26175 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import junit.framework.TestCase; /** * Tests for all {@link KeyedObjectPoolFactory}s. * * @author Sandy McArthur * @version $Revision: 1221705 $ $Date: 2011-12-21 08:03:54 -0500 (Wed, 21 Dec 2011) $ */ public abstract class TestKeyedObjectPoolFactory extends TestCase { protected TestKeyedObjectPoolFactory(final String name) { super(name); } /** * @throws UnsupportedOperationException when this is unsupported by this KeyedPoolableObjectFactory type. */ protected KeyedObjectPoolFactory makeFactory() throws UnsupportedOperationException { return makeFactory(createObjectFactory()); } /** * @throws UnsupportedOperationException when this is unsupported by this KeyedPoolableObjectFactory type. */ protected abstract KeyedObjectPoolFactory makeFactory(KeyedPoolableObjectFactory objectFactory) throws UnsupportedOperationException; protected static KeyedPoolableObjectFactory createObjectFactory() { return PoolUtils.adapt(new MethodCallPoolableObjectFactory()); } public void testCreatePool() throws Exception { final KeyedObjectPoolFactory factory; try { factory = makeFactory(); } catch (UnsupportedOperationException uoe) { return; } final KeyedObjectPool pool = factory.createPool(); pool.close(); } public void testToString() { final KeyedObjectPoolFactory factory; try { factory = makeFactory(); } catch (UnsupportedOperationException uoe) { return; } factory.toString(); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/TestObjectPool.java100644 0 0 44030 11701070262 23700 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import junit.framework.TestCase; import org.apache.commons.pool.impl.GenericObjectPool; import org.apache.commons.pool.impl.SoftReferenceObjectPool; import org.apache.commons.pool.impl.StackObjectPool; /** * Abstract {@link TestCase} for {@link ObjectPool} implementations. * @author Rodney Waldhoff * @author Sandy McArthur * @version $Revision: 1222710 $ $Date: 2011-12-23 10:58:12 -0500 (Fri, 23 Dec 2011) $ */ public abstract class TestObjectPool extends TestCase { public TestObjectPool(String testName) { super(testName); } /** * Create an ObjectPool with the specified factory. * The pool should be in a default configuration and conform to the expected * behaviors described in {@link ObjectPool}. * Generally speaking there should be no limits on the various object counts. * @throws UnsupportedOperationException if the pool being tested does not follow pool contracts. */ protected abstract ObjectPool makeEmptyPool(PoolableObjectFactory factory) throws UnsupportedOperationException; public void testClosedPoolBehavior() throws Exception { final ObjectPool pool; try { pool = makeEmptyPool(new MethodCallPoolableObjectFactory()); } catch (UnsupportedOperationException uoe) { return; // test not supported } Integer o1 = pool.borrowObject(); Integer o2 = pool.borrowObject(); pool.close(); try { pool.addObject(); fail("A closed pool must throw an IllegalStateException when addObject is called."); } catch (IllegalStateException ise) { // expected } try { pool.borrowObject(); fail("A closed pool must throw an IllegalStateException when borrowObject is called."); } catch (IllegalStateException ise) { // expected } // The following should not throw exceptions just because the pool is closed. if (pool.getNumIdle() >= 0) { assertEquals("A closed pool shouldn't have any idle objects.", 0, pool.getNumIdle()); } if (pool.getNumActive() >= 0) { assertEquals("A closed pool should still keep count of active objects.", 2, pool.getNumActive()); } pool.returnObject(o1); if (pool.getNumIdle() >= 0) { assertEquals("returnObject should not add items back into the idle object pool for a closed pool.", 0, pool.getNumIdle()); } if (pool.getNumActive() >= 0) { assertEquals("A closed pool should still keep count of active objects.", 1, pool.getNumActive()); } pool.invalidateObject(o2); if (pool.getNumIdle() >= 0) { assertEquals("invalidateObject must not add items back into the idle object pool.", 0, pool.getNumIdle()); } if (pool.getNumActive() >= 0) { assertEquals("A closed pool should still keep count of active objects.", 0, pool.getNumActive()); } pool.clear(); pool.close(); } private final Integer ZERO = new Integer(0); private final Integer ONE = new Integer(1); public void testPOFAddObjectUsage() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); final ObjectPool pool; try { pool = makeEmptyPool(factory); } catch(UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); assertEquals(0, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); // addObject should make a new object, pasivate it and put it in the pool pool.addObject(); assertEquals(0, pool.getNumActive()); assertEquals(1, pool.getNumIdle()); expectedMethods.add(new MethodCall("makeObject").returned(ZERO)); // StackObjectPool, SoftReferenceObjectPool also validate on add if (pool instanceof StackObjectPool || pool instanceof SoftReferenceObjectPool) { expectedMethods.add(new MethodCall( "validateObject", ZERO).returned(Boolean.TRUE)); } expectedMethods.add(new MethodCall("passivateObject", ZERO)); assertEquals(expectedMethods, factory.getMethodCalls()); //// Test exception handling of addObject reset(pool, factory, expectedMethods); // makeObject Exceptions should be propagated to client code from addObject factory.setMakeObjectFail(true); try { pool.addObject(); fail("Expected addObject to propagate makeObject exception."); } catch (PrivateException pe) { // expected } expectedMethods.add(new MethodCall("makeObject")); assertEquals(expectedMethods, factory.getMethodCalls()); clear(factory, expectedMethods); // passivateObject Exceptions should be propagated to client code from addObject factory.setMakeObjectFail(false); factory.setPassivateObjectFail(true); try { pool.addObject(); fail("Expected addObject to propagate passivateObject exception."); } catch (PrivateException pe) { // expected } expectedMethods.add(new MethodCall("makeObject").returned(ONE)); // StackObjectPool, SofReferenceObjectPool also validate on add if (pool instanceof StackObjectPool || pool instanceof SoftReferenceObjectPool) { expectedMethods.add(new MethodCall( "validateObject", ONE).returned(Boolean.TRUE)); } expectedMethods.add(new MethodCall("passivateObject", ONE)); assertEquals(expectedMethods, factory.getMethodCalls()); } public void testPOFBorrowObjectUsages() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); final ObjectPool pool; try { pool = makeEmptyPool(factory); } catch (UnsupportedOperationException uoe) { return; // test not supported } if (pool instanceof GenericObjectPool) { ((GenericObjectPool) pool).setTestOnBorrow(true); } final List expectedMethods = new ArrayList(); Integer obj; /// Test correct behavior code paths // existing idle object should be activated and validated pool.addObject(); clear(factory, expectedMethods); obj = pool.borrowObject(); expectedMethods.add(new MethodCall("activateObject", ZERO)); expectedMethods.add(new MethodCall("validateObject", ZERO).returned(Boolean.TRUE)); assertEquals(expectedMethods, factory.getMethodCalls()); pool.returnObject(obj); //// Test exception handling of borrowObject reset(pool, factory, expectedMethods); // makeObject Exceptions should be propagated to client code from borrowObject factory.setMakeObjectFail(true); try { obj = pool.borrowObject(); fail("Expected borrowObject to propagate makeObject exception."); } catch (PrivateException pe) { // expected } expectedMethods.add(new MethodCall("makeObject")); assertEquals(expectedMethods, factory.getMethodCalls()); // when activateObject fails in borrowObject, a new object should be borrowed/created reset(pool, factory, expectedMethods); pool.addObject(); clear(factory, expectedMethods); factory.setActivateObjectFail(true); expectedMethods.add(new MethodCall("activateObject", obj)); try { obj = pool.borrowObject(); fail("Expecting NoSuchElementException"); } catch (NoSuchElementException ex) { // Expected - newly created object will also fail to activate } // Idle object fails activation, new one created, also fails expectedMethods.add(new MethodCall("makeObject").returned(ONE)); expectedMethods.add(new MethodCall("activateObject", ONE)); removeDestroyObjectCall(factory.getMethodCalls()); // The exact timing of destroyObject is flexible here. assertEquals(expectedMethods, factory.getMethodCalls()); // when validateObject fails in borrowObject, a new object should be borrowed/created reset(pool, factory, expectedMethods); pool.addObject(); clear(factory, expectedMethods); factory.setValidateObjectFail(true); expectedMethods.add(new MethodCall("activateObject", ZERO)); expectedMethods.add(new MethodCall("validateObject", ZERO)); try { obj = pool.borrowObject(); } catch (NoSuchElementException ex) { // Expected - newly created object will also fail to validate } // Idle object is activated, but fails validation. // New instance is created, activated and then fails validation expectedMethods.add(new MethodCall("makeObject").returned(ONE)); expectedMethods.add(new MethodCall("activateObject", ONE)); expectedMethods.add(new MethodCall("validateObject", ONE)); removeDestroyObjectCall(factory.getMethodCalls()); // The exact timing of destroyObject is flexible here. // Second activate and validate are missing from expectedMethods assertTrue(factory.getMethodCalls().containsAll(expectedMethods)); } public void testPOFReturnObjectUsages() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); final ObjectPool pool; try { pool = makeEmptyPool(factory); } catch (UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); Integer obj; /// Test correct behavior code paths obj = pool.borrowObject(); clear(factory, expectedMethods); // returned object should be passivated pool.returnObject(obj); // StackObjectPool, SoftReferenceObjectPool also validate on return if (pool instanceof StackObjectPool || pool instanceof SoftReferenceObjectPool) { expectedMethods.add(new MethodCall( "validateObject", obj).returned(Boolean.TRUE)); } expectedMethods.add(new MethodCall("passivateObject", obj)); assertEquals(expectedMethods, factory.getMethodCalls()); //// Test exception handling of returnObject reset(pool, factory, expectedMethods); pool.addObject(); pool.addObject(); pool.addObject(); assertEquals(3, pool.getNumIdle()); // passivateObject should swallow exceptions and not add the object to the pool obj = pool.borrowObject(); pool.borrowObject(); assertEquals(1, pool.getNumIdle()); assertEquals(2, pool.getNumActive()); clear(factory, expectedMethods); factory.setPassivateObjectFail(true); pool.returnObject(obj); // StackObjectPool, SoftReferenceObjectPool also validate on return if (pool instanceof StackObjectPool || pool instanceof SoftReferenceObjectPool) { expectedMethods.add(new MethodCall( "validateObject", obj).returned(Boolean.TRUE)); } expectedMethods.add(new MethodCall("passivateObject", obj)); removeDestroyObjectCall(factory.getMethodCalls()); // The exact timing of destroyObject is flexible here. assertEquals(expectedMethods, factory.getMethodCalls()); assertEquals(1, pool.getNumIdle()); // Not returned assertEquals(1, pool.getNumActive()); // But not in active count // destroyObject should swallow exceptions too reset(pool, factory, expectedMethods); obj = pool.borrowObject(); clear(factory, expectedMethods); factory.setPassivateObjectFail(true); factory.setDestroyObjectFail(true); pool.returnObject(obj); } public void testPOFInvalidateObjectUsages() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); final ObjectPool pool; try { pool = makeEmptyPool(factory); } catch (UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); Integer obj; /// Test correct behavior code paths obj = pool.borrowObject(); clear(factory, expectedMethods); // invalidated object should be destroyed pool.invalidateObject(obj); expectedMethods.add(new MethodCall("destroyObject", obj)); assertEquals(expectedMethods, factory.getMethodCalls()); //// Test exception handling of invalidateObject reset(pool, factory, expectedMethods); obj = pool.borrowObject(); clear(factory, expectedMethods); factory.setDestroyObjectFail(true); try { pool.invalidateObject(obj); fail("Expecting destroy exception to propagate"); } catch (PrivateException ex) { // Expected } Thread.sleep(250); // could be defered removeDestroyObjectCall(factory.getMethodCalls()); assertEquals(expectedMethods, factory.getMethodCalls()); } public void testPOFClearUsages() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); final ObjectPool pool; try { pool = makeEmptyPool(factory); } catch (UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); /// Test correct behavior code paths PoolUtils.prefill(pool, 5); pool.clear(); //// Test exception handling clear should swallow destory object failures reset(pool, factory, expectedMethods); factory.setDestroyObjectFail(true); PoolUtils.prefill(pool, 5); pool.clear(); } public void testPOFCloseUsages() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); ObjectPool pool; try { pool = makeEmptyPool(factory); } catch (UnsupportedOperationException uoe) { return; // test not supported } final List expectedMethods = new ArrayList(); /// Test correct behavior code paths PoolUtils.prefill(pool, 5); pool.close(); //// Test exception handling close should swallow failures try { pool = makeEmptyPool(factory); } catch (UnsupportedOperationException uoe) { return; // test not supported } reset(pool, factory, expectedMethods); factory.setDestroyObjectFail(true); PoolUtils.prefill(pool, 5); pool.close(); } public void testSetFactory() throws Exception { ObjectPool pool; try { pool = makeEmptyPool(new MethodCallPoolableObjectFactory()); } catch (UnsupportedOperationException uoe) { return; // test not supported } final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); try { pool.setFactory(factory); } catch (UnsupportedOperationException uoe) { return; } } public void testToString() { ObjectPool pool; try { pool = makeEmptyPool(new MethodCallPoolableObjectFactory()); } catch (UnsupportedOperationException uoe) { return; // test not supported } pool.toString(); } static void removeDestroyObjectCall(List calls) { Iterator iter = calls.iterator(); while (iter.hasNext()) { MethodCall call = iter.next(); if ("destroyObject".equals(call.getName())) { iter.remove(); } } } private static void reset(final ObjectPool pool, final MethodCallPoolableObjectFactory factory, final List expectedMethods) throws Exception { pool.clear(); clear(factory, expectedMethods); factory.reset(); } private static void clear(final MethodCallPoolableObjectFactory factory, final List expectedMethods) { factory.getMethodCalls().clear(); expectedMethods.clear(); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/TestObjectPoolFactory.java100644 0 0 4540 11701070262 25212 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import junit.framework.TestCase; /** * Unit tests for all {@link ObjectPoolFactory}. * * @author Sandy McArthur * @version $Revision: 1221705 $ $Date: 2011-12-21 08:03:54 -0500 (Wed, 21 Dec 2011) $ */ public abstract class TestObjectPoolFactory extends TestCase { protected TestObjectPoolFactory(final String name) { super(name); } /** * @throws UnsupportedOperationException when this is unsupported by this PoolableObjectFactory type. */ protected ObjectPoolFactory makeFactory() throws UnsupportedOperationException { return makeFactory(new MethodCallPoolableObjectFactory()); } /** * @throws UnsupportedOperationException when this is unsupported by this PoolableObjectFactory type. */ protected abstract ObjectPoolFactory makeFactory(PoolableObjectFactory objectFactory) throws UnsupportedOperationException; public void testCreatePool() throws Exception { final ObjectPoolFactory factory; try { factory = makeFactory(); } catch (UnsupportedOperationException uoe) { return; } final ObjectPool pool = factory.createPool(); pool.close(); } public void testToString() { final ObjectPoolFactory factory; try { factory = makeFactory(); } catch (UnsupportedOperationException uoe) { return; } factory.toString(); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/TestPoolUtils.java100644 0 0 120675 11701070262 23624 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TimerTask; import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.apache.commons.pool.impl.GenericKeyedObjectPool; import org.apache.commons.pool.impl.GenericObjectPool; /** * Unit tests for {@link PoolUtils}. * * @author Sandy McArthur * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ */ public class TestPoolUtils extends TestCase { /** Period between checks for minIdle tests. Increase this if you happen to get too many false failures. */ private static final int CHECK_PERIOD = 300; /** Times to let the minIdle check run. */ private static final int CHECK_COUNT = 4; /** Sleep time to let the minIdle tests run CHECK_COUNT times. */ private static final int CHECK_SLEEP_PERIOD = CHECK_PERIOD * (CHECK_COUNT - 1) + CHECK_PERIOD / 2; public void testJavaBeanInstantiation() { new PoolUtils(); } public void testAdaptKeyedPoolableObjectFactory() throws Exception { try { PoolUtils.adapt((KeyedPoolableObjectFactory)null); fail("PoolUtils.adapt(KeyedPoolableObjectFactory) must not allow null factory."); } catch (IllegalArgumentException iae) { // expected } } public void testAdaptKeyedPoolableObjectFactoryKey() throws Exception { try { PoolUtils.adapt((KeyedPoolableObjectFactory)null, new Object()); fail("PoolUtils.adapt(KeyedPoolableObjectFactory, key) must not allow null factory."); } catch (IllegalArgumentException iae) { // expected } try { @SuppressWarnings("unchecked") final KeyedPoolableObjectFactory proxy = createProxy(KeyedPoolableObjectFactory.class, (List)null); PoolUtils.adapt(proxy, null); fail("PoolUtils.adapt(KeyedPoolableObjectFactory, key) must not allow null key."); } catch (IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") final KeyedPoolableObjectFactory kpof = createProxy(KeyedPoolableObjectFactory.class, calledMethods); final PoolableObjectFactory pof = PoolUtils.adapt(kpof); final List expectedMethods = invokeEveryMethod(pof); assertEquals(expectedMethods, calledMethods); } public void testAdaptPoolableObjectFactory() throws Exception { try { PoolUtils.adapt((PoolableObjectFactory)null); fail("PoolUtils.adapt(PoolableObjectFactory) must not allow null factory."); } catch (IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); final PoolableObjectFactory pof = createProxy(PoolableObjectFactory.class, calledMethods); final KeyedPoolableObjectFactory kpof = PoolUtils.adapt(pof); final List expectedMethods = invokeEveryMethod(kpof); assertEquals(expectedMethods, calledMethods); } public void testAdaptKeyedObjectPool() throws Exception { try { PoolUtils.adapt((KeyedObjectPool)null); fail("PoolUtils.adapt(KeyedObjectPool) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } } public void testAdaptKeyedObjectPoolKey() throws Exception { try { PoolUtils.adapt((KeyedObjectPool)null, new Object()); fail("PoolUtils.adapt(KeyedObjectPool, key) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } try { @SuppressWarnings("unchecked") final KeyedObjectPool proxy = createProxy(KeyedObjectPool.class, (List)null); PoolUtils.adapt(proxy, null); fail("PoolUtils.adapt(KeyedObjectPool, key) must not allow a null key."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") final KeyedObjectPool kop = createProxy(KeyedObjectPool.class, calledMethods); final ObjectPool op = PoolUtils.adapt(kop, new Object()); final List expectedMethods = invokeEveryMethod(op); assertEquals(expectedMethods, calledMethods); } public void testAdaptObjectPool() throws Exception { try { PoolUtils.adapt((ObjectPool)null); fail("PoolUtils.adapt(ObjectPool) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") final ObjectPool op = createProxy(ObjectPool.class, calledMethods); final KeyedObjectPool kop = PoolUtils.adapt(op); final List expectedMethods = invokeEveryMethod(kop); assertEquals(expectedMethods, calledMethods); } public void testCheckedPoolObjectPool() throws Exception { try { PoolUtils.checkedPool((ObjectPool)null, Object.class); fail("PoolUtils.checkedPool(ObjectPool, Class) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } try { final ObjectPool proxy = createProxy(ObjectPool.class, (List)null); PoolUtils.checkedPool(proxy, null); fail("PoolUtils.checkedPool(ObjectPool, Class) must not allow a null type."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") ObjectPool op = createProxy(ObjectPool.class, calledMethods); ObjectPool cop = PoolUtils.checkedPool(op, Object.class); final List expectedMethods = invokeEveryMethod(cop); assertEquals(expectedMethods, calledMethods); op = new BaseObjectPool() { @Override public Object borrowObject() throws Exception { return new Integer(0); } @Override public void returnObject(Object obj) {} @Override public void invalidateObject(Object obj) {} }; // cast to ObjectPool to be able to use String.class @SuppressWarnings({ "rawtypes", "unchecked" }) final ObjectPool checkedPool = PoolUtils.checkedPool((ObjectPool)op, String.class); @SuppressWarnings("unchecked") final ObjectPool cop2 = checkedPool; try { cop2.borrowObject(); fail("borrowObject should have failed as Integer !instanceof String."); } catch (ClassCastException cce) { // expected } try { cop2.returnObject(new Integer(1)); fail("returnObject should have failed as Integer !instanceof String."); } catch (ClassCastException cce) { // expected } try { cop2.invalidateObject(new Integer(2)); fail("invalidateObject should have failed as Integer !instanceof String."); } catch (ClassCastException cce) { // expected } } public void testCheckedPoolKeyedObjectPool() throws Exception { try { PoolUtils.checkedPool((KeyedObjectPool)null, Object.class); fail("PoolUtils.checkedPool(KeyedObjectPool, Class) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } try { PoolUtils.checkedPool((KeyedObjectPool)createProxy(KeyedObjectPool.class, (List)null), null); fail("PoolUtils.checkedPool(KeyedObjectPool, Class) must not allow a null type."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") KeyedObjectPool op = createProxy(KeyedObjectPool.class, calledMethods); KeyedObjectPool cop = PoolUtils.checkedPool(op, Object.class); final List expectedMethods = invokeEveryMethod(cop); assertEquals(expectedMethods, calledMethods); op = new BaseKeyedObjectPool() { @Override public Integer borrowObject(Object key) { return new Integer(0); } @Override public void returnObject(Object key, Object obj) {} @Override public void invalidateObject(Object key, Object obj) {} }; @SuppressWarnings("rawtypes") final KeyedObjectPool rawPool = op; @SuppressWarnings("unchecked") KeyedObjectPool cop2 = PoolUtils.checkedPool(rawPool, String.class); try { cop2.borrowObject(null); fail("borrowObject should have failed as Integer !instanceof String."); } catch (ClassCastException cce) { // expected } try { cop2.returnObject(null, new Integer(1)); fail("returnObject should have failed as Integer !instanceof String."); } catch (ClassCastException cce) { // expected } try { cop2.invalidateObject(null, new Integer(2)); fail("invalidateObject should have failed as Integer !instanceof String."); } catch (ClassCastException cce) { // expected } } public void testCheckMinIdleObjectPool() throws Exception { try { PoolUtils.checkMinIdle(null, 1, 1); fail("PoolUtils.checkMinIdle(ObjectPool,,) must not allow null pool."); } catch (IllegalArgumentException iae) { // expected } try { final ObjectPool pool = createProxy(ObjectPool.class, (List)null); PoolUtils.checkMinIdle(pool, -1, 1); fail("PoolUtils.checkMinIdle(ObjectPool,,) must not accept negative min idle values."); } catch (IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); // Test that the minIdle check doesn't add too many idle objects @SuppressWarnings("unchecked") final PoolableObjectFactory pof = createProxy(PoolableObjectFactory.class, calledMethods); final ObjectPool op = new GenericObjectPool(pof); PoolUtils.checkMinIdle(op, 2, 100); Thread.sleep(400); assertEquals(2, op.getNumIdle()); op.close(); int makeObjectCount = 0; final Iterator iter = calledMethods.iterator(); while (iter.hasNext()) { final String methodName = iter.next(); if ("makeObject".equals(methodName)) { makeObjectCount++; } } assertEquals("makeObject should have been called two time", 2, makeObjectCount); // Because this isn't deterministic and you can get false failures, try more than once. AssertionFailedError afe = null; int triesLeft = 3; do { afe = null; try { calledMethods.clear(); @SuppressWarnings("unchecked") final ObjectPool pool = createProxy(ObjectPool.class, calledMethods); final TimerTask task = PoolUtils.checkMinIdle(pool, 1, CHECK_PERIOD); // checks minIdle immediately Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times. task.cancel(); task.toString(); final List expectedMethods = new ArrayList(); for (int i=0; i < CHECK_COUNT; i++) { expectedMethods.add("getNumIdle"); expectedMethods.add("addObject"); } expectedMethods.add("toString"); assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler } catch (AssertionFailedError e) { afe = e; } } while (--triesLeft > 0 && afe != null); if (afe != null) { throw afe; } } public void testCheckMinIdleKeyedObjectPool() throws Exception { try { PoolUtils.checkMinIdle(null, new Object(), 1, 1); fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not allow null pool."); } catch (IllegalArgumentException iae) { // expected } try { @SuppressWarnings("unchecked") final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List)null); PoolUtils.checkMinIdle(pool, (Object)null, 1, 1); fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept null keys."); } catch (IllegalArgumentException iae) { // expected } try { @SuppressWarnings("unchecked") final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List)null); PoolUtils.checkMinIdle(pool, new Object(), -1, 1); fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept negative min idle values."); } catch (IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); final Object key = new Object(); // Test that the minIdle check doesn't add too many idle objects @SuppressWarnings("unchecked") final KeyedPoolableObjectFactory kpof = createProxy(KeyedPoolableObjectFactory.class, calledMethods); final KeyedObjectPool kop = new GenericKeyedObjectPool(kpof); PoolUtils.checkMinIdle(kop, key, 2, 100); Thread.sleep(400); assertEquals(2, kop.getNumIdle(key)); assertEquals(2, kop.getNumIdle()); kop.close(); int makeObjectCount = 0; final Iterator iter = calledMethods.iterator(); while (iter.hasNext()) { final String methodName = iter.next(); if ("makeObject".equals(methodName)) { makeObjectCount++; } } assertEquals("makeObject should have been called two time", 2, makeObjectCount); // Because this isn't deterministic and you can get false failures, try more than once. AssertionFailedError afe = null; int triesLeft = 3; do { afe = null; try { calledMethods.clear(); @SuppressWarnings("unchecked") final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, calledMethods); final TimerTask task = PoolUtils.checkMinIdle(pool, key, 1, CHECK_PERIOD); // checks minIdle immediately Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times. task.cancel(); task.toString(); final List expectedMethods = new ArrayList(); for (int i=0; i < CHECK_COUNT; i++) { expectedMethods.add("getNumIdle"); expectedMethods.add("addObject"); } expectedMethods.add("toString"); assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler } catch (AssertionFailedError e) { afe = e; } } while (--triesLeft > 0 && afe != null); if (afe != null) { throw afe; } } public void testCheckMinIdleKeyedObjectPoolKeys() throws Exception { try { @SuppressWarnings("unchecked") final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List)null); PoolUtils.checkMinIdle(pool, (Collection)null, 1, 1); fail("PoolUtils.checkMinIdle(KeyedObjectPool,Collection,int,long) must not accept null keys."); } catch (IllegalArgumentException iae) { // expected } // Because this isn't determinist and you can get false failures, try more than once. AssertionFailedError afe = null; int triesLeft = 3; do { afe = null; try { final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, calledMethods); final Collection keys = new ArrayList(2); keys.add("one"); keys.add("two"); final Map tasks = PoolUtils.checkMinIdle(pool, keys, 1, CHECK_PERIOD); // checks minIdle immediately Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times. final Iterator iter = tasks.values().iterator(); while (iter.hasNext()) { final TimerTask task = iter.next(); task.cancel(); } final List expectedMethods = new ArrayList(); for (int i=0; i < CHECK_COUNT * keys.size(); i++) { expectedMethods.add("getNumIdle"); expectedMethods.add("addObject"); } assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler } catch (AssertionFailedError e) { afe = e; } } while (--triesLeft > 0 && afe != null); if (afe != null) { throw afe; } } public void testPrefillObjectPool() throws Exception { try { PoolUtils.prefill(null, 1); fail("PoolUtils.prefill(ObjectPool,int) must not allow null pool."); } catch (IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); final ObjectPool pool = createProxy(ObjectPool.class, calledMethods); PoolUtils.prefill(pool, 0); final List expectedMethods = new ArrayList(); assertEquals(expectedMethods, calledMethods); calledMethods.clear(); PoolUtils.prefill(pool, 3); for (int i=0; i < 3; i++) { expectedMethods.add("addObject"); } assertEquals(expectedMethods, calledMethods); } public void testPrefillKeyedObjectPool() throws Exception { try { PoolUtils.prefill(null, new Object(), 1); fail("PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null pool."); } catch (IllegalArgumentException iae) { // expected } try { @SuppressWarnings("unchecked") final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List)null); PoolUtils.prefill(pool, (Object)null, 1); fail("PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null key."); } catch (IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, calledMethods); PoolUtils.prefill(pool, new Object(), 0); final List expectedMethods = new ArrayList(); assertEquals(expectedMethods, calledMethods); calledMethods.clear(); PoolUtils.prefill(pool, new Object(), 3); for (int i=0; i < 3; i++) { expectedMethods.add("addObject"); } assertEquals(expectedMethods, calledMethods); } public void testPrefillKeyedObjectPoolCollection() throws Exception { try { @SuppressWarnings("unchecked") final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List)null); PoolUtils.prefill(pool, (Collection)null, 1); fail("PoolUtils.prefill(KeyedObjectPool,Collection,int) must not accept null keys."); } catch (IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, calledMethods); final Set keys = new HashSet(); PoolUtils.prefill(pool, keys, 0); final List expectedMethods = new ArrayList(); assertEquals(expectedMethods, calledMethods); calledMethods.clear(); keys.add(new Integer(1)); keys.add(new Long(2)); keys.add(new Double(3.1415926)); PoolUtils.prefill(pool, keys, 3); for (int i=0; i < keys.size() * 3; i++) { expectedMethods.add("addObject"); } assertEquals(expectedMethods, calledMethods); } public void testSynchronizedPoolObjectPool() throws Exception { try { PoolUtils.synchronizedPool((ObjectPool)null); fail("PoolUtils.synchronizedPool(ObjectPool) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") final ObjectPool op = createProxy(ObjectPool.class, calledMethods); final ObjectPool sop = PoolUtils.synchronizedPool(op); final List expectedMethods = invokeEveryMethod(sop); assertEquals(expectedMethods, calledMethods); // TODO: Anyone feel motivated to construct a test that verifies proper synchronization? } public void testSynchronizedPoolKeyedObjectPool() throws Exception { try { PoolUtils.synchronizedPool((KeyedObjectPool)null); fail("PoolUtils.synchronizedPool(KeyedObjectPool) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") final KeyedObjectPool kop = createProxy(KeyedObjectPool.class, calledMethods); final KeyedObjectPool skop = PoolUtils.synchronizedPool(kop); final List expectedMethods = invokeEveryMethod(skop); assertEquals(expectedMethods, calledMethods); // TODO: Anyone feel motivated to construct a test that verifies proper synchronization? } public void testSynchronizedPoolableFactoryPoolableObjectFactory() throws Exception { try { PoolUtils.synchronizedPoolableFactory((PoolableObjectFactory)null); fail("PoolUtils.synchronizedPoolableFactory(PoolableObjectFactory) must not allow a null factory."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") final PoolableObjectFactory pof = createProxy(PoolableObjectFactory.class, calledMethods); final PoolableObjectFactory spof = PoolUtils.synchronizedPoolableFactory(pof); final List expectedMethods = invokeEveryMethod(spof); assertEquals(expectedMethods, calledMethods); // TODO: Anyone feel motivated to construct a test that verifies proper synchronization? } public void testSynchronizedPoolableFactoryKeyedPoolableObjectFactory() throws Exception { try { PoolUtils.synchronizedPoolableFactory((KeyedPoolableObjectFactory)null); fail("PoolUtils.synchronizedPoolableFactory(KeyedPoolableObjectFactory) must not allow a null factory."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); @SuppressWarnings("unchecked") final KeyedPoolableObjectFactory kpof = createProxy(KeyedPoolableObjectFactory.class, calledMethods); final KeyedPoolableObjectFactory skpof = PoolUtils.synchronizedPoolableFactory(kpof); final List expectedMethods = invokeEveryMethod(skpof); assertEquals(expectedMethods, calledMethods); // TODO: Anyone feel motivated to construct a test that verifies proper synchronization? } public void testErodingPoolObjectPool() throws Exception { try { PoolUtils.erodingPool((ObjectPool)null); fail("PoolUtils.erodingPool(ObjectPool) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } try { PoolUtils.erodingPool((ObjectPool)null, 1f); fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } try { PoolUtils.erodingPool((ObjectPool)null, 0); fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a non-positive factor."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); final InvocationHandler handler = new MethodCallLogger(calledMethods) { @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { Object o = super.invoke(proxy, method, args); if (o instanceof Integer) { // so getNumActive/getNumIdle are not zero. o = new Integer(1); } return o; } }; // If the logic behind PoolUtils.erodingPool changes then this will need to be tweaked. float factor = 0.01f; // about ~9 seconds until first discard @SuppressWarnings("unchecked") final ObjectPool pool = PoolUtils.erodingPool((ObjectPool)createProxy(ObjectPool.class, handler), factor); final List expectedMethods = new ArrayList(); assertEquals(expectedMethods, calledMethods); Object o = pool.borrowObject(); expectedMethods.add("borrowObject"); assertEquals(expectedMethods, calledMethods); pool.returnObject(o); expectedMethods.add("returnObject"); assertEquals(expectedMethods, calledMethods); for (int i=0; i < 5; i ++) { o = pool.borrowObject(); expectedMethods.add("borrowObject"); Thread.sleep(50); pool.returnObject(o); expectedMethods.add("returnObject"); assertEquals(expectedMethods, calledMethods); expectedMethods.clear(); calledMethods.clear(); } Thread.sleep(10000); // 10 seconds o = pool.borrowObject(); expectedMethods.add("borrowObject"); pool.returnObject(o); expectedMethods.add("getNumIdle"); expectedMethods.add("invalidateObject"); assertEquals(expectedMethods, calledMethods); } public void testErodingPoolKeyedObjectPool() throws Exception { try { PoolUtils.erodingPool((KeyedObjectPool)null); fail("PoolUtils.erodingPool(KeyedObjectPool) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } try { PoolUtils.erodingPool((KeyedObjectPool)null, 1f); fail("PoolUtils.erodingPool(KeyedObjectPool, float) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } try { PoolUtils.erodingPool((KeyedObjectPool)null, 0); fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a non-positive factor."); } catch(IllegalArgumentException iae) { // expected } try { PoolUtils.erodingPool((KeyedObjectPool)null, 1f, true); fail("PoolUtils.erodingPool(KeyedObjectPool, float, boolean) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } try { PoolUtils.erodingPool((KeyedObjectPool)null, 0, false); fail("PoolUtils.erodingPool(ObjectPool, float, boolean) must not allow a non-positive factor."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); final InvocationHandler handler = new MethodCallLogger(calledMethods) { @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { Object o = super.invoke(proxy, method, args); if (o instanceof Integer) { // so getNumActive/getNumIdle are not zero. o = new Integer(1); } return o; } }; // If the logic behind PoolUtils.erodingPool changes then this will need to be tweaked. float factor = 0.01f; // about ~9 seconds until first discard @SuppressWarnings("unchecked") final KeyedObjectPool pool = PoolUtils.erodingPool((KeyedObjectPool)createProxy(KeyedObjectPool.class, handler), factor); final List expectedMethods = new ArrayList(); assertEquals(expectedMethods, calledMethods); final Object key = "key"; Object o = pool.borrowObject(key); expectedMethods.add("borrowObject"); assertEquals(expectedMethods, calledMethods); pool.returnObject(key, o); expectedMethods.add("returnObject"); assertEquals(expectedMethods, calledMethods); for (int i=0; i < 5; i ++) { o = pool.borrowObject(key); expectedMethods.add("borrowObject"); Thread.sleep(50); pool.returnObject(key, o); expectedMethods.add("returnObject"); assertEquals(expectedMethods, calledMethods); expectedMethods.clear(); calledMethods.clear(); } Thread.sleep(10000); // 10 seconds o = pool.borrowObject(key); expectedMethods.add("borrowObject"); pool.returnObject(key, o); expectedMethods.add("getNumIdle"); expectedMethods.add("invalidateObject"); assertEquals(expectedMethods, calledMethods); } public void testErodingPerKeyKeyedObjectPool() throws Exception { try { PoolUtils.erodingPool((KeyedObjectPool)null, 1, true); fail("PoolUtils.erodingPool(KeyedObjectPool) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } try { PoolUtils.erodingPool((KeyedObjectPool)null, 0, true); fail("PoolUtils.erodingPool(ObjectPool, float) must not allow a non-positive factor."); } catch(IllegalArgumentException iae) { // expected } try { PoolUtils.erodingPool((KeyedObjectPool)null, 1f, true); fail("PoolUtils.erodingPool(KeyedObjectPool, float, boolean) must not allow a null pool."); } catch(IllegalArgumentException iae) { // expected } final List calledMethods = new ArrayList(); final InvocationHandler handler = new MethodCallLogger(calledMethods) { @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { Object o = super.invoke(proxy, method, args); if (o instanceof Integer) { // so getNumActive/getNumIdle are not zero. o = new Integer(1); } return o; } }; // If the logic behind PoolUtils.erodingPool changes then this will need to be tweaked. float factor = 0.01f; // about ~9 seconds until first discard @SuppressWarnings("unchecked") final KeyedObjectPool pool = PoolUtils.erodingPool((KeyedObjectPool)createProxy(KeyedObjectPool.class, handler), factor, true); final List expectedMethods = new ArrayList(); assertEquals(expectedMethods, calledMethods); final Object key = "key"; Object o = pool.borrowObject(key); expectedMethods.add("borrowObject"); assertEquals(expectedMethods, calledMethods); pool.returnObject(key, o); expectedMethods.add("returnObject"); assertEquals(expectedMethods, calledMethods); for (int i=0; i < 5; i ++) { o = pool.borrowObject(key); expectedMethods.add("borrowObject"); Thread.sleep(50); pool.returnObject(key, o); expectedMethods.add("returnObject"); assertEquals(expectedMethods, calledMethods); expectedMethods.clear(); calledMethods.clear(); } Thread.sleep(10000); // 10 seconds o = pool.borrowObject(key); expectedMethods.add("borrowObject"); pool.returnObject(key, o); expectedMethods.add("getNumIdle"); expectedMethods.add("invalidateObject"); assertEquals(expectedMethods, calledMethods); } private static List invokeEveryMethod(ObjectPool op) throws Exception { op.addObject(); op.borrowObject(); op.clear(); op.close(); op.getNumActive(); op.getNumIdle(); op.invalidateObject(new Object()); op.returnObject(new Object()); @SuppressWarnings("unchecked") final PoolableObjectFactory proxy = createProxy(PoolableObjectFactory.class, (List)null); op.setFactory(proxy); op.toString(); final List expectedMethods = Arrays.asList(new String[] { "addObject", "borrowObject", "clear", "close", "getNumActive", "getNumIdle", "invalidateObject", "returnObject", "setFactory", "toString" }); return expectedMethods; } private static List invokeEveryMethod(KeyedObjectPool kop) throws Exception { kop.addObject(null); kop.borrowObject(null); kop.clear(); kop.clear(null); kop.close(); kop.getNumActive(); kop.getNumActive(null); kop.getNumIdle(); kop.getNumIdle(null); kop.invalidateObject(null, new Object()); kop.returnObject(null, new Object()); @SuppressWarnings("unchecked") final KeyedPoolableObjectFactory proxy = createProxy(KeyedPoolableObjectFactory.class, (List)null); kop.setFactory(proxy); kop.toString(); final List expectedMethods = Arrays.asList(new String[] { "addObject", "borrowObject", "clear", "clear", "close", "getNumActive", "getNumActive", "getNumIdle", "getNumIdle", "invalidateObject", "returnObject", "setFactory", "toString" }); return expectedMethods; } private static List invokeEveryMethod(PoolableObjectFactory pof) throws Exception { pof.activateObject(null); pof.destroyObject(null); pof.makeObject(); pof.passivateObject(null); pof.validateObject(null); pof.toString(); final List expectedMethods = Arrays.asList(new String[] { "activateObject", "destroyObject", "makeObject", "passivateObject", "validateObject", "toString", }); return expectedMethods; } private static List invokeEveryMethod(KeyedPoolableObjectFactory kpof) throws Exception { kpof.activateObject(null, null); kpof.destroyObject(null, null); kpof.makeObject(null); kpof.passivateObject(null, null); kpof.validateObject(null, null); kpof.toString(); final List expectedMethods = Arrays.asList(new String[] { "activateObject", "destroyObject", "makeObject", "passivateObject", "validateObject", "toString", }); return expectedMethods; } /** * Call sites can use @SuppressWarnings("unchecked") */ private static T createProxy(final Class clazz, final List logger) { return createProxy(clazz, new MethodCallLogger(logger)); } /** * Call sites can use @SuppressWarnings("unchecked") */ private static T createProxy(final Class clazz, final InvocationHandler handler) { return clazz.cast(Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, handler)); } private static class MethodCallLogger implements InvocationHandler { private final List calledMethods; MethodCallLogger(final List calledMethods) { this.calledMethods = calledMethods; } public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { calledMethods.add(method.getName()); if (boolean.class.equals(method.getReturnType())) { return Boolean.FALSE; } else if (int.class.equals(method.getReturnType())) { return new Integer(0); } else if (long.class.equals(method.getReturnType())) { return new Long(0); } else if (Object.class.equals(method.getReturnType())) { return new Object(); } else { return null; } } } } commons-pool-1.6-src/src/test/org/apache/commons/pool/VisitTracker.java100644 0 0 5503 11701070262 23374 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * Test pooled object class. Keeps track of how many times it has been * validated, activated, passivated. * */ public class VisitTracker { private int validateCount = 0; private int activateCount = 0; private int passivateCount = 0; private boolean destroyed = false; private int id = 0; private K key = null; public VisitTracker() { super(); reset(); } public VisitTracker(int id) { super(); this.id = id; reset(); } public VisitTracker(int id, K key) { super(); this.id = id; this.key = key; reset(); } public boolean validate() { if (destroyed) { fail("attempted to validate a destroyed object"); } validateCount++; return true; } public void activate() { if (destroyed) { fail("attempted to activate a destroyed object"); } activateCount++; } public void passivate() { if (destroyed) { fail("attempted to passivate a destroyed object"); } passivateCount++; } public void reset() { validateCount = 0; activateCount = 0; passivateCount = 0; destroyed = false; } public void destroy() { destroyed = true; } public int getValidateCount() { return validateCount; } public int getActivateCount() { return activateCount; } public int getPassivateCount() { return passivateCount; } public boolean isDestroyed() { return destroyed; } public int getId() { return id; } public K getKey() { return key; } @Override public String toString() { return "Key: " + key + " id: " + id; } private void fail(String message) { throw new IllegalStateException(message); } } commons-pool-1.6-src/src/test/org/apache/commons/pool/VisitTrackerFactory.java100644 0 0 4326 11701070262 24726 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** * Factory that creates VisitTracker instances. Used to * test Evictor runs. * */ public class VisitTrackerFactory implements PoolableObjectFactory>, KeyedPoolableObjectFactory> { private int nextId = 0; public VisitTrackerFactory() { super(); } public VisitTracker makeObject() { return new VisitTracker(nextId++); } public VisitTracker makeObject(K key) { return new VisitTracker(nextId++, key); } public void destroyObject(VisitTracker obj) { obj.destroy(); } public void destroyObject(K key, VisitTracker obj) { obj.destroy(); } public boolean validateObject(VisitTracker obj) { return obj.validate(); } public boolean validateObject(K key, VisitTracker obj) { return obj.validate(); } public void activateObject(VisitTracker obj) throws Exception { obj.activate(); } public void activateObject(K key, VisitTracker obj) throws Exception { obj.activate(); } public void passivateObject(VisitTracker obj) throws Exception { obj.passivate(); } public void passivateObject(K key, VisitTracker obj) throws Exception { obj.passivate(); } public void resetId() { nextId = 0; } } commons-pool-1.6-src/src/test/org/apache/commons/pool/Waiter.java100644 0 0 10427 11701070262 22236 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; /** *

Object created by {@link WaiterFactory}. Maintains active / valid state, * last passivated and idle times. Waits with configurable latency when * {@link #doWait()} method is called.

* *

This class is *not* threadsafe.

*/ public class Waiter { private boolean active = false; private boolean valid = true; private long latency = 0; private long lastPassivated = 0; private long lastIdleTimeMs = 0; public Waiter(boolean active, boolean valid, long latency) { this.active = active; this.valid = valid; this.latency = latency; this.lastPassivated = System.currentTimeMillis(); } /** * Wait for {@link #getLatency()} ms. */ public void doWait() { try { Thread.sleep(latency); } catch (InterruptedException ex) { // ignore } } /** * Whether or not the instance is active. * * @return true if the last lifecycle event for this instance was activation. */ public boolean isActive() { return active; } /** *

Sets the active state and updates {@link #getLastIdleTimeMs() lastIdleTime} * or {@link #getLastPassivated() lastPassivated} as appropriate.

* *

If the active state is changing from inactive to active, lastIdleTime * is updated with the current time minus lastPassivated. If the state is * changing from active to inactive, lastPassivated is updated with the * current time.

* *

{@link WaiterFactory#activateObject(Waiter)} and * {@link WaiterFactory#passivateObject(Waiter)} invoke this method on their * actual parameter, passing true and false, * respectively.

* * @param active new active state */ public void setActive(boolean active) { final boolean activeState = this.active; if (activeState == active) { return; } this.active = active; final long currentTime = System.currentTimeMillis(); if (active) { // activating lastIdleTimeMs = currentTime - lastPassivated; } else { // passivating lastPassivated = currentTime; } } public long getLatency() { return latency; } public void setLatency(long latency) { this.latency = latency; } public boolean isValid() { return valid; } public void setValid(boolean valid) { this.valid = valid; } /** *

Returns the system time of this instance's last passivation.

* *

When an instance is created, this field is initialized to the system time.

* * @return time of last passivation */ public long getLastPassivated() { return lastPassivated; } /** *

Returns the last idle time for this instance in ms.

* *

When an instance is created, and each subsequent time it is passivated, * the {@link #getLastPassivated() lastPassivated} property is updated with the * current time. When the next activation occurs, lastIdleTime is * updated with the elapsed time since passivation.

* * @return last idle time */ public long getLastIdleTimeMs() { return lastIdleTimeMs; } } commons-pool-1.6-src/src/test/org/apache/commons/pool/WaiterFactory.java100644 0 0 16473 11701070262 23575 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * Object factory with configurable latencies for object lifecycle methods. * This factory will also track and enforce maxActive, maxActivePerKey contracts. * If the factory's maxActive / maxActivePerKey are set to match those of the * pool, makeObject will throw IllegalStateException if the number of makes - destroys * (per key) exceeds the configured max. * */ public class WaiterFactory implements PoolableObjectFactory, KeyedPoolableObjectFactory { /** Latency of activateObject */ private final long activateLatency; /** Latency of destroyObject */ private final long destroyLatency; /** Latency of makeObject */ private final long makeLatency; /** Latency of passivateObject */ private final long passivateLatency; /** Latency of validateObject */ private final long validateLatency; /** Latency of doWait for Waiter instances created by this factory */ private final long waiterLatency; /** Probability that passivation will invalidate Waiter instances */ private final double passivateInvalidationProbability; /** Count of (makes - destroys) since last reset */ private long activeCount = 0; /** Count of (makes - destroys) per key since last reset */ private Map activeCounts = new HashMap(); /** Maximum of (makes - destroys) - if exceeded IllegalStateException */ private final long maxActive; // GKOP 1.x calls this maxTotal /** Maximum of (makes - destroys) per key */ private final long maxActivePerKey; // GKOP 1.x calls this maxActive public WaiterFactory(long activateLatency, long destroyLatency, long makeLatency, long passivateLatency, long validateLatency, long waiterLatency,long maxActive, long maxActivePerKey, double passivateInvalidationProbability) { this.activateLatency = activateLatency; this.destroyLatency = destroyLatency; this.makeLatency = makeLatency; this.passivateLatency = passivateLatency; this.validateLatency = validateLatency; this.waiterLatency = waiterLatency; this.maxActive = maxActive; this.maxActivePerKey = maxActivePerKey; this.passivateInvalidationProbability = passivateInvalidationProbability; } public WaiterFactory(long activateLatency, long destroyLatency, long makeLatency, long passivateLatency, long validateLatency, long waiterLatency) { this(activateLatency, destroyLatency, makeLatency, passivateLatency, validateLatency, waiterLatency, Long.MAX_VALUE, Long.MAX_VALUE, 0); } public WaiterFactory(long activateLatency, long destroyLatency, long makeLatency, long passivateLatency, long validateLatency, long waiterLatency,long maxActive) { this(activateLatency, destroyLatency, makeLatency, passivateLatency, validateLatency, waiterLatency, maxActive, Long.MAX_VALUE, 0); } public void activateObject(Waiter obj) throws Exception { doWait(activateLatency); obj.setActive(true); } public void destroyObject(Waiter obj) throws Exception { doWait(destroyLatency); obj.setValid(false); obj.setActive(false); // Decrement *after* destroy synchronized (this) { activeCount--; } } public Waiter makeObject() throws Exception { // Increment and test *before* make synchronized (this) { if (activeCount >= maxActive) { throw new IllegalStateException("Too many active instances: " + activeCount + " in circulation with maxActive = " + maxActive); } else { activeCount++; } } doWait(makeLatency); return new Waiter(false, true, waiterLatency); } public void passivateObject(Waiter arg0) throws Exception { arg0.setActive(false); doWait(passivateLatency); if (Math.random() < passivateInvalidationProbability) { arg0.setValid(false); } } public boolean validateObject(Waiter arg0) { doWait(validateLatency); return arg0.isValid(); } protected void doWait(long latency) { try { Thread.sleep(latency); } catch (InterruptedException ex) { // ignore } } public synchronized void reset() { activeCount = 0; if (activeCounts.isEmpty()) { return; } Iterator it = activeCounts.keySet().iterator(); while (it.hasNext()) { K key = it.next(); activeCounts.put(key, new Integer (0)); } } /** * @return the maxActive */ public synchronized long getMaxActive() { return maxActive; } // KeyedPoolableObjectFactory methods public void activateObject(K key, Waiter obj) throws Exception { activateObject(obj); } public void destroyObject(K key, Waiter obj) throws Exception { destroyObject(obj); synchronized (this) { Integer count = activeCounts.get(key); activeCounts.put(key, new Integer(count.intValue() - 1)); } } public Waiter makeObject(K key) throws Exception { synchronized (this) { Integer count = activeCounts.get(key); if (count == null) { count = new Integer(1); activeCounts.put(key, count); } else { if (count.intValue() >= maxActivePerKey) { throw new IllegalStateException("Too many active " + "instances for key = " + key + ": " + count.intValue() + " in circulation " + "with maxActivePerKey = " + maxActivePerKey); } else { activeCounts.put(key, new Integer(count.intValue() + 1)); } } } return makeObject(); } public void passivateObject(K key, Waiter obj) throws Exception { passivateObject(obj); } public boolean validateObject(K key, Waiter obj) { return validateObject(obj); } } sivation.

* *

When an instance is created, this field is initialized to the system time.

* * @return time of last passivation */ public long getLastPassivated() { return lastPassivated; } /** *

Returns the last idle time for this instance in ms.

* *

When an instance is created, and each subsequent time it is passivated, * the {@link #getLastPassivated() lastPassivated} property is updated with the * current time. When the next activation occurs, lastIdleTime is * updated with the elapsed time since passivation.

* * @return last idle time */ public long getLastIdleTimeMs() { return lastIdleTimeMs; } } commons-pool-1.6-src/src/test/org/apache/commons/pool/WaiterFactory.java100644 0 0 16473 11701070262 23575 0ustar 0 0 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.pool; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * Object factory with configurable latencies for object lifecycle methods. * This factory will also track and enforce maxActive, maxActivePerKey contracts. * If the factory's maxActive / maxActivePerKey are set to match those of the * pool, makeObject will throw IllegalStateException if the number of makes - destroys * (per key) exceeds the configured max. * */ public class WaiterFactory implements PoolableObjectFactory, KeyedPoolableObjectFactory { /** Latency of activateObject */ private final long activateLatency; /** Latency of destroyObject */ private final long destroyLatency; /** Latency of makeObject */ private final long makeLatency; /** Latency of passivateObject */ private final long passivateLatency; /** Latency of validateObject */ private final long validateLatency; /** Latency of doWait for Waiter instances created by this factory */ private final long waiterLatency; /** Probability that passivation will invalidate Waiter instances */ private final double passivateInvalidationProbability; /** Count of (makes - destroys) since last reset */ private long activeCount = 0; /** Count of (makes - destroys) per key since last reset */ private Map activeCounts = new HashMap(); /** Maximum of (makes - destroys) - if exceeded IllegalStateException */ private final long maxActive; // GKOP 1.x calls this maxTotal /** Maximum of (makes - destroys) per key */ private final long maxActivePerKey; // GKOP 1.x calls this maxActive public WaiterFactory(long activateLatency, long destroyLatency, long makeLatency, long passivateLatency, long validateLatency, long waiterLatency,long maxActive, long maxActivePerKey, double passivateInvalidationProbability) { this.activateLatency = activateLatency; this.destroyLatency = destroyLatency; this.makeLatency = makeLatency; this.passivateLatency = passivateLatency; this.validateLatency = validateLatency; this.waiterLatency = waiterLatency; this.maxActive = maxActive; this.maxActivePerKey = maxActivePerKey; this.passivateInvalidationProbability = passivateInvalidationProbability; } public WaiterFactory(long activateLatency, long destroyLatency, long makeLatency, long passivateLatency, long validateLatency, long waiterLatency) { this(activateLatency, d