001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.pool2;
018
019import java.io.Closeable;
020import java.util.Collection;
021import java.util.Collections;
022import java.util.List;
023import java.util.NoSuchElementException;
024
025/**
026 * A "keyed" pooling interface.
027 * <p>
028 * A keyed pool maintains a pool of instances for each key value.
029 * </p>
030 * <p>
031 * Example of use:
032 * </p>
033 * <pre style="border:solid thin; padding: 1ex;"
034 * > Object obj = <code style="color:#00C">null</code>;
035 * Object key = <code style="color:#C00">"Key"</code>;
036 *
037 * <code style="color:#00C">try</code> {
038 *     obj = pool.borrowObject(key);
039 *     <code style="color:#0C0">//...use the object...</code>
040 * } <code style="color:#00C">catch</code> (Exception e) {
041 *     <code style="color:#0C0">// invalidate the object</code>
042 *     pool.invalidateObject(key, obj);
043 *     <code style="color:#0C0">// do not return the object to the pool twice</code>
044 *     obj = <code style="color:#00C">null</code>;
045 * } <code style="color:#00C">finally</code> {
046 *     <code style="color:#0C0">// make sure the object is returned to the pool</code>
047 *     <code style="color:#00C">if</code> (<code style="color:#00C">null</code> != obj) {
048 *         pool.returnObject(key, obj);
049 *     }
050 * }</pre>
051 * <p>
052 * {@link KeyedObjectPool} implementations <i>may</i> choose to store at most
053 * one instance per key value, or may choose to maintain a pool of instances
054 * for each key (essentially creating a {@link java.util.Map Map} of
055 * {@link ObjectPool pools}).
056 * </p>
057 * <p>
058 * See {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool
059 * GenericKeyedObjectPool} for an implementation.
060 * </p>
061 *
062 * @param <K> The type of keys maintained by this pool.
063 * @param <V> Type of element pooled in this pool.
064 * 
065 *
066 * @see KeyedPooledObjectFactory
067 * @see ObjectPool
068 * @see org.apache.commons.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool
069 *
070 * @since 2.0
071 */
072public interface KeyedObjectPool<K, V> extends Closeable {
073
074    /**
075     * Creates an object using the {@link KeyedPooledObjectFactory factory} or
076     * other implementation dependent mechanism, passivate it, and then place it
077     * in the idle object pool. {@code addObject} is useful for
078     * "pre-loading" a pool with idle objects (Optional operation).
079     *
080     * @param key the key a new instance should be added to
081     *
082     * @throws Exception
083     *              when {@link KeyedPooledObjectFactory#makeObject} fails.
084     * @throws IllegalStateException
085     *              after {@link #close} has been called on this pool.
086     * @throws UnsupportedOperationException
087     *              when this pool cannot add new idle objects.
088     */
089    void addObject(K key) throws Exception;
090
091    /**
092     * Calls {@link KeyedObjectPool#addObject(Object)} with each
093     * key in {@code keys} for {@code count} number of times. This has
094     * the same effect as calling {@link #addObjects(Object, int)}
095     * for each key in the {@code keys} collection.
096     *
097     * @param keys
098     *            {@link Collection} of keys to add objects for.
099     * @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}