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 <i>may</i> 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   *
70   * @since 2.0
71   */
72  public interface KeyedObjectPool<K, V> extends Closeable {
73  
74      /**
75       * Creates an object using the {@link KeyedPooledObjectFactory factory} or
76       * other implementation dependent mechanism, passivate it, and then place it
77       * in the idle object pool. {@code addObject} is useful for
78       * "pre-loading" a pool with idle objects (Optional operation).
79       *
80       * @param key the key a new instance should be added to
81       *
82       * @throws Exception
83       *              when {@link KeyedPooledObjectFactory#makeObject} fails.
84       * @throws IllegalStateException
85       *              after {@link #close} has been called on this pool.
86       * @throws UnsupportedOperationException
87       *              when this pool cannot add new idle objects.
88       */
89      void addObject(K key) throws Exception;
90  
91      /**
92       * Calls {@link KeyedObjectPool#addObject(Object)} with each
93       * key in {@code keys} for {@code count} number of times. This has
94       * the same effect as calling {@link #addObjects(Object, int)}
95       * for each key in the {@code keys} collection.
96       *
97       * @param keys
98       *            {@link Collection} of keys to add objects for.
99       * @param count
100      *            the number of idle objects to add for each {@code key}.
101      * @throws Exception
102      *             when {@link KeyedObjectPool#addObject(Object)} fails.
103      * @throws IllegalArgumentException
104      *             when {@code keyedPool}, {@code keys}, or any value
105      *             in {@code keys} is {@code null}.
106      * @see #addObjects(Object, int)
107      */
108     default void addObjects(final Collection<K> keys, final int count) throws Exception {
109         if (keys == null) {
110             throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEYS);
111         }
112         for (final K key : keys) {
113             addObjects(key, count);
114         }
115     }
116 
117     /**
118      * Calls {@link KeyedObjectPool#addObject(Object)}
119      * {@code key} {@code count} number of times.
120      *
121      * @param key
122      *            the key to add objects for.
123      * @param count
124      *            the number of idle objects to add for {@code key}.
125      * @throws Exception
126      *             when {@link KeyedObjectPool#addObject(Object)} fails.
127      * @throws IllegalArgumentException
128      *             when {@code key} is {@code null}.
129      * @since 2.8.0
130      */
131     default void addObjects(final K key, final int count) throws Exception {
132         if (key == null) {
133             throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEY);
134         }
135         for (int i = 0; i < count; i++) {
136             addObject(key);
137         }
138     }
139 
140     /**
141      * Borrows an instance from this pool for the specified {@code key}.
142      * <p>
143      * Instances returned from this method will have been either newly created
144      * with {@link KeyedPooledObjectFactory#makeObject makeObject} or will be
145      * a previously idle object and have been activated with
146      * {@link KeyedPooledObjectFactory#activateObject activateObject} and then
147      * (optionally) validated with
148      * {@link KeyedPooledObjectFactory#validateObject validateObject}.
149      * </p>
150      * <p>
151      * By contract, clients <strong>must</strong> return the borrowed object
152      * using {@link #returnObject returnObject},
153      * {@link #invalidateObject invalidateObject}, or a related method as
154      * defined in an implementation or sub-interface, using a {@code key}
155      * that is {@link Object#equals equivalent} to the one used to borrow the
156      * instance in the first place.
157      * </p>
158      * <p>
159      * The behavior of this method when the pool has been exhausted is not
160      * strictly specified (although it may be specified by implementations).
161      * </p>
162      *
163      * @param key the key used to obtain the object
164      *
165      * @return an instance from this pool.
166      *
167      * @throws IllegalStateException
168      *              after {@link #close close} has been called on this pool
169      * @throws Exception
170      *              when {@link KeyedPooledObjectFactory#makeObject
171      *              makeObject} throws an exception
172      * @throws NoSuchElementException
173      *              when the pool is exhausted and cannot or will not return
174      *              another instance
175      */
176     V borrowObject(K key) throws Exception;
177 
178     /**
179      * Clears the pool, removing all pooled instances (optional operation).
180      *
181      * @throws UnsupportedOperationException when this implementation doesn't
182      *                                       support the operation
183      *
184      * @throws Exception if the pool cannot be cleared
185      */
186     void clear() throws Exception;
187 
188     /**
189      * Clears the specified pool, removing all pooled instances corresponding to
190      * the given {@code key} (optional operation).
191      *
192      * @param key the key to clear
193      *
194      * @throws UnsupportedOperationException when this implementation doesn't
195      *                                       support the operation
196      *
197      * @throws Exception if the key cannot be cleared
198      */
199     void clear(K key) throws Exception;
200 
201     /**
202      * Closes this pool, and free any resources associated with it.
203      * <p>
204      * Calling {@link #addObject addObject} or
205      * {@link #borrowObject borrowObject} after invoking this method on a pool
206      * will cause them to throw an {@link IllegalStateException}.
207      * </p>
208      * <p>
209      * Implementations should silently fail if not all resources can be freed.
210      * </p>
211      */
212     @Override
213     void close();
214 
215     /**
216      * Gets a copy of the pool key list.
217      * <p>
218      * Note: The default implementation returns an empty list.
219      * Implementations should override this method.
220      * </p>
221      *
222      * @return a copy of the pool key list.
223      * @since 2.12.0
224      */
225     default List<K> getKeys() {
226         return Collections.emptyList();
227     }
228 
229     /**
230      * Gets the total number of instances currently borrowed from this pool but
231      * not yet returned. Returns a negative value if this information is not
232      * available.
233      * @return the total number of instances currently borrowed from this pool but
234      * not yet returned.
235      */
236     int getNumActive();
237 
238     /**
239      * Gets the number of instances currently borrowed from but not yet
240      * returned to the pool corresponding to the given {@code key}.
241      * Returns a negative value if this information is not available.
242      *
243      * @param key the key to query
244      * @return the number of instances currently borrowed from but not yet
245      * returned to the pool corresponding to the given {@code key}.
246      */
247     int getNumActive(K key);
248 
249     /**
250      * Gets the total number of instances currently idle in this pool.
251      * Returns a negative value if this information is not available.
252      * @return the total number of instances currently idle in this pool.
253      */
254     int getNumIdle();
255 
256     /**
257      * Gets the number of instances corresponding to the given
258      * {@code key} currently idle in this pool. Returns a negative value if
259      * this information is not available.
260      *
261      * @param key the key to query
262      * @return the number of instances corresponding to the given
263      * {@code key} currently idle in this pool.
264      */
265     int getNumIdle(K key);
266 
267     /**
268      * Invalidates an object from the pool.
269      * <p>
270      * By contract, {@code obj} <strong>must</strong> have been obtained
271      * using {@link #borrowObject borrowObject} or a related method as defined
272      * in an implementation or sub-interface using a {@code key} that is
273      * equivalent to the one used to borrow the {@code Object} in the first
274      * place.
275      * </p>
276      * <p>
277      * This method should be used when an object that has been borrowed is
278      * determined (due to an exception or other problem) to be invalid.
279      * </p>
280      *
281      * @param key the key used to obtain the object
282      * @param obj a {@link #borrowObject borrowed} instance to be returned.
283      *
284      * @throws Exception if the instance cannot be invalidated
285      */
286     void invalidateObject(K key, V obj) throws Exception;
287 
288     /**
289      * Invalidates an object from the pool, using the provided
290      * {@link DestroyMode}.
291      * <p>
292      * By contract, {@code obj} <strong>must</strong> have been obtained
293      * using {@link #borrowObject borrowObject} or a related method as defined
294      * in an implementation or sub-interface using a {@code key} that is
295      * equivalent to the one used to borrow the {@code Object} in the first
296      * place.
297      * </p>
298      * <p>
299      * This method should be used when an object that has been borrowed is
300      * determined (due to an exception or other problem) to be invalid.
301      * </p>
302      *
303      * @param key the key used to obtain the object
304      * @param obj a {@link #borrowObject borrowed} instance to be returned.
305      * @param destroyMode destroy activation context provided to the factory
306      *
307      * @throws Exception if the instance cannot be invalidated
308      * @since 2.9.0
309      */
310     default void invalidateObject(final K key, final V obj, final DestroyMode destroyMode) throws Exception {
311         invalidateObject(key, obj);
312     }
313 
314     /**
315      * Return an instance to the pool. By contract, {@code obj}
316      * <strong>must</strong> have been obtained using
317      * {@link #borrowObject borrowObject} or a related method as defined in an
318      * implementation or sub-interface using a {@code key} that is
319      * equivalent to the one used to borrow the instance in the first place.
320      *
321      * @param key the key used to obtain the object
322      * @param obj a {@link #borrowObject borrowed} instance to be returned.
323      *
324      * @throws IllegalStateException
325      *              if an attempt is made to return an object to the pool that
326      *              is in any state other than allocated (i.e. borrowed).
327      *              Attempting to return an object more than once or attempting
328      *              to return an object that was never borrowed from the pool
329      *              will trigger this exception.
330      *
331      * @throws Exception if an instance cannot be returned to the pool
332      */
333     void returnObject(K key, V obj) throws Exception;
334 }