View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.pool2;
18  
19  import java.io.Closeable;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.List;
23  import java.util.NoSuchElementException;
24  
25  /**
26   * A "keyed" pooling interface.
27   * <p>
28   * A keyed pool maintains a pool of instances for each key value.
29   * </p>
30   * <p>
31   * Example of use:
32   * </p>
33   * <pre style="border:solid thin; padding: 1ex;"
34   * > Object obj = <code style="color:#00C">null</code>;
35   * Object key = <code style="color:#C00">"Key"</code>;
36   *
37   * <code style="color:#00C">try</code> {
38   *     obj = pool.borrowObject(key);
39   *     <code style="color:#0C0">//...use the object...</code>
40   * } <code style="color:#00C">catch</code> (Exception e) {
41   *     <code style="color:#0C0">// invalidate the object</code>
42   *     pool.invalidateObject(key, obj);
43   *     <code style="color:#0C0">// do not return the object to the pool twice</code>
44   *     obj = <code style="color:#00C">null</code>;
45   * } <code style="color:#00C">finally</code> {
46   *     <code style="color:#0C0">// make sure the object is returned to the pool</code>
47   *     <code style="color:#00C">if</code> (<code style="color:#00C">null</code> != obj) {
48   *         pool.returnObject(key, obj);
49   *     }
50   * }</pre>
51   * <p>
52   * {@link KeyedObjectPool} implementations <em>may</em> choose to store at most
53   * one instance per key value, or may choose to maintain a pool of instances
54   * for each key (essentially creating a {@link java.util.Map Map} of
55   * {@link ObjectPool pools}).
56   * </p>
57   * <p>
58   * See {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool
59   * GenericKeyedObjectPool} for an implementation.
60   * </p>
61   *
62   * @param <K> The type of keys maintained by this pool.
63   * @param <V> Type of element pooled in this pool.
64   *
65   *
66   * @see KeyedPooledObjectFactory
67   * @see ObjectPool
68   * @see org.apache.commons.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool
69   * @since 2.0
70   */
71  public interface KeyedObjectPool<K, V> extends Closeable {
72  
73      /**
74       * Creates an object using the {@link KeyedPooledObjectFactory factory} or
75       * other implementation dependent mechanism, passivate it, and then place it
76       * in the idle object pool. {@code addObject} is useful for
77       * "pre-loading" a pool with idle objects (Optional operation).
78       *
79       * @param key the key a new instance should be added to
80       * @throws Exception
81       *              when {@link KeyedPooledObjectFactory#makeObject} fails.
82       * @throws IllegalStateException
83       *              after {@link #close} has been called on this pool.
84       * @throws UnsupportedOperationException
85       *              when this pool cannot add new idle objects.
86       */
87      void addObject(K key) throws Exception;
88  
89      /**
90       * Calls {@link KeyedObjectPool#addObject(Object)} with each
91       * key in {@code keys} for {@code count} number of times. This has
92       * the same effect as calling {@link #addObjects(Object, int)}
93       * for each key in the {@code keys} collection.
94       *
95       * @param keys
96       *            {@link Collection} of keys to add objects for.
97       * @param count
98       *            the number of idle objects to add for each {@code key}.
99       * @throws Exception
100      *             when {@link KeyedObjectPool#addObject(Object)} fails.
101      * @throws IllegalArgumentException
102      *             when {@code keyedPool}, {@code keys}, or any value
103      *             in {@code keys} is {@code null}.
104      * @see #addObjects(Object, int)
105      */
106     default void addObjects(final Collection<K> keys, final int count) throws Exception {
107         if (keys == null) {
108             throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEYS);
109         }
110         for (final K key : keys) {
111             addObjects(key, count);
112         }
113     }
114 
115     /**
116      * Calls {@link KeyedObjectPool#addObject(Object)}
117      * {@code key} {@code count} number of times.
118      *
119      * @param key
120      *            the key to add objects for.
121      * @param count
122      *            the number of idle objects to add for {@code key}.
123      * @throws Exception
124      *             when {@link KeyedObjectPool#addObject(Object)} fails.
125      * @throws IllegalArgumentException
126      *             when {@code key} is {@code null}.
127      * @since 2.8.0
128      */
129     default void addObjects(final K key, final int count) throws Exception {
130         if (key == null) {
131             throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEY);
132         }
133         for (int i = 0; i < count; i++) {
134             addObject(key);
135         }
136     }
137 
138     /**
139      * Borrows an instance from this pool for the specified {@code key}.
140      * <p>
141      * Instances returned from this method will have been either newly created
142      * with {@link KeyedPooledObjectFactory#makeObject makeObject} or will be
143      * a previously idle object and have been activated with
144      * {@link KeyedPooledObjectFactory#activateObject activateObject} and then
145      * (optionally) validated with
146      * {@link KeyedPooledObjectFactory#validateObject validateObject}.
147      * </p>
148      * <p>
149      * By contract, clients <strong>must</strong> return the borrowed object
150      * using {@link #returnObject returnObject},
151      * {@link #invalidateObject invalidateObject}, or a related method as
152      * defined in an implementation or sub-interface, using a {@code key}
153      * that is {@link Object#equals equivalent} to the one used to borrow the
154      * instance in the first place.
155      * </p>
156      * <p>
157      * The behavior of this method when the pool has been exhausted is not
158      * strictly specified (although it may be specified by implementations).
159      * </p>
160      *
161      * @param key the key used to obtain the object
162      * @return an instance from this pool.
163      * @throws IllegalStateException
164      *              after {@link #close close} has been called on this pool
165      * @throws Exception
166      *              when {@link KeyedPooledObjectFactory#makeObject
167      *              makeObject} throws an exception
168      * @throws NoSuchElementException
169      *              when the pool is exhausted and cannot or will not return
170      *              another instance
171      */
172     V borrowObject(K key) throws Exception;
173 
174     /**
175      * Clears the pool, removing all pooled instances (optional operation).
176      *
177      * @throws UnsupportedOperationException when this implementation doesn't
178      *                                       support the operation
179      *
180      * @throws Exception if the pool cannot be cleared
181      */
182     void clear() throws Exception;
183 
184     /**
185      * Clears the specified pool, removing all pooled instances corresponding to
186      * the given {@code key} (optional operation).
187      *
188      * @param key the key to clear
189      * @throws UnsupportedOperationException when this implementation doesn't
190      *                                       support the operation
191      *
192      * @throws Exception if the key cannot be cleared
193      */
194     void clear(K key) throws Exception;
195 
196     /**
197      * Closes this pool, and free any resources associated with it.
198      * <p>
199      * Calling {@link #addObject addObject} or
200      * {@link #borrowObject borrowObject} after invoking this method on a pool
201      * will cause them to throw an {@link IllegalStateException}.
202      * </p>
203      * <p>
204      * Implementations should silently fail if not all resources can be freed.
205      * </p>
206      */
207     @Override
208     void close();
209 
210     /**
211      * Gets a copy of the pool key list.
212      * <p>
213      * Note: The default implementation returns an empty list.
214      * Implementations should override this method.
215      * </p>
216      *
217      * @return a copy of the pool key list.
218      * @since 2.12.0
219      */
220     default List<K> getKeys() {
221         return Collections.emptyList();
222     }
223 
224     /**
225      * Gets the total number of instances currently borrowed from this pool but
226      * not yet returned. Returns a negative value if this information is not
227      * available.
228      * @return the total number of instances currently borrowed from this pool but
229      * not yet returned.
230      */
231     int getNumActive();
232 
233     /**
234      * Gets the number of instances currently borrowed from but not yet
235      * returned to the pool corresponding to the given {@code key}.
236      * Returns a negative value if this information is not available.
237      *
238      * @param key the key to query
239      * @return the number of instances currently borrowed from but not yet
240      * returned to the pool corresponding to the given {@code key}.
241      */
242     int getNumActive(K key);
243 
244     /**
245      * Gets the total number of instances currently idle in this pool.
246      * Returns a negative value if this information is not available.
247      * @return the total number of instances currently idle in this pool.
248      */
249     int getNumIdle();
250 
251     /**
252      * Gets the number of instances corresponding to the given
253      * {@code key} currently idle in this pool. Returns a negative value if
254      * this information is not available.
255      *
256      * @param key the key to query
257      * @return the number of instances corresponding to the given
258      * {@code key} currently idle in this pool.
259      */
260     int getNumIdle(K key);
261 
262     /**
263      * Invalidates an object from the pool.
264      * <p>
265      * By contract, {@code obj} <strong>must</strong> have been obtained
266      * using {@link #borrowObject borrowObject} or a related method as defined
267      * in an implementation or sub-interface using a {@code key} that is
268      * equivalent to the one used to borrow the {@code Object} in the first
269      * place.
270      * </p>
271      * <p>
272      * This method should be used when an object that has been borrowed is
273      * determined (due to an exception or other problem) to be invalid.
274      * </p>
275      *
276      * @param key the key used to obtain the object
277      * @param obj a {@link #borrowObject borrowed} instance to be returned.
278      * @throws Exception if the instance cannot be invalidated
279      */
280     void invalidateObject(K key, V obj) throws Exception;
281 
282     /**
283      * Invalidates an object from the pool, using the provided
284      * {@link DestroyMode}.
285      * <p>
286      * By contract, {@code obj} <strong>must</strong> have been obtained
287      * using {@link #borrowObject borrowObject} or a related method as defined
288      * in an implementation or sub-interface using a {@code key} that is
289      * equivalent to the one used to borrow the {@code Object} in the first
290      * place.
291      * </p>
292      * <p>
293      * This method should be used when an object that has been borrowed is
294      * determined (due to an exception or other problem) to be invalid.
295      * </p>
296      *
297      * @param key the key used to obtain the object
298      * @param obj a {@link #borrowObject borrowed} instance to be returned.
299      * @param destroyMode destroy activation context provided to the factory
300      * @throws Exception if the instance cannot be invalidated
301      * @since 2.9.0
302      */
303     default void invalidateObject(final K key, final V obj, final DestroyMode destroyMode) throws Exception {
304         invalidateObject(key, obj);
305     }
306 
307     /**
308      * Return an instance to the pool. By contract, {@code obj}
309      * <strong>must</strong> have been obtained using
310      * {@link #borrowObject borrowObject} or a related method as defined in an
311      * implementation or sub-interface using a {@code key} that is
312      * equivalent to the one used to borrow the instance in the first place.
313      *
314      * @param key the key used to obtain the object
315      * @param obj a {@link #borrowObject borrowed} instance to be returned.
316      * @throws IllegalStateException
317      *              if an attempt is made to return an object to the pool that
318      *              is in any state other than allocated (i.e. borrowed).
319      *              Attempting to return an object more than once or attempting
320      *              to return an object that was never borrowed from the pool
321      *              will trigger this exception.
322      *
323      * @throws Exception if an instance cannot be returned to the pool
324      */
325     void returnObject(K key, V obj) throws Exception;
326 }