    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.Iterator;
    022import java.util.NoSuchElementException;
    023
    024/**
    025 * A "keyed" pooling interface.
    026 * <p>
    027 * A keyed pool maintains a pool of instances for each key value.
    028 * </p>
    029 * <p>
    030 * Example of use:
    031 * </p>
    032 * <pre style="border:solid thin; padding: 1ex;"
    033 * > Object obj = <code style="color:#00C">null</code>;
    034 * Object key = <code style="color:#C00">"Key"</code>;
    035 *
    036 * <code style="color:#00C">try</code> {
    037 *     obj = pool.borrowObject(key);
    038 *     <code style="color:#0C0">//...use the object...</code>
    039 * } <code style="color:#00C">catch</code>(Exception e) {
    040 *     <code style="color:#0C0">// invalidate the object</code>
    041 *     pool.invalidateObject(key, obj);
    042 *     <code style="color:#0C0">// do not return the object to the pool twice</code>
    043 *     obj = <code style="color:#00C">null</code>;
    044 * } <code style="color:#00C">finally</code> {
    045 *     <code style="color:#0C0">// make sure the object is returned to the pool</code>
    046 *     <code style="color:#00C">if</code>(<code style="color:#00C">null</code> != obj) {
    047 *         pool.returnObject(key, obj);
    048 *     }
    049 * }</pre>
    050 * <p>
    051 * {@link KeyedObjectPool} implementations <i>may</i> choose to store at most
    052 * one instance per key value, or may choose to maintain a pool of instances
    053 * for each key (essentially creating a {@link java.util.Map Map} of
    054 * {@link ObjectPool pools}).
    055 * </p>
    056 * <p>
    057 * See {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool
    058 * GenericKeyedObjectPool} for an implementation.
    059 * </p>
    060 *
    061 * @param <K> The type of keys maintained by this pool.
    062 * @param <V> Type of element pooled in this pool.
    063 *
    064 * @see KeyedPooledObjectFactory
    065 * @see ObjectPool
    066 * @see org.apache.commons.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool
    067 *
    068 * @since 2.0
    069 */
    070public interface KeyedObjectPool<K, V> extends Closeable {
    071
    072    /**
    073     * Create an object using the {@link KeyedPooledObjectFactory factory} or
    074     * other implementation dependent mechanism, passivate it, and then place it
    075     * in the idle object pool. {@code addObject} is useful for
    076     * "pre-loading" a pool with idle objects (Optional operation).
    077     *
    078     * @param key the key a new instance should be added to
    079     *
    080     * @throws Exception
    081     *              when {@link KeyedPooledObjectFactory#makeObject} fails.
    082     * @throws IllegalStateException
    083     *              after {@link #close} has been called on this pool.
    084     * @throws UnsupportedOperationException
    085     *              when this pool cannot add new idle objects.
    086     */
    087    void addObject(K key) throws Exception, IllegalStateException,
    088            UnsupportedOperationException;
    089
    090    /**
    091     * Calls {@link KeyedObjectPool#addObject(Object)} with each
    092     * key in {@code keys} for {@code count} number of times. This has
    093     * the same effect as calling {@link #addObjects(Object, int)}
    094     * for each key in the {@code keys} collection.
    095     *
    096     * @param keys
    097     *            {@link Collection} of keys to add objects for.
    098     * @param count
    099     *            the number of idle objects to add for each {@code key}.
    100     * @throws Exception
    101     *             when {@link KeyedObjectPool#addObject(Object)} fails.
    102     * @throws IllegalArgumentException
    103     *             when {@code keyedPool}, {@code keys}, or any value
    104     *             in {@code keys} is {@code null}.
    105     * @see #addObjects(Object, int)
    106     */
    107    default void addObjects(final Collection<K> keys, final int count) throws Exception, IllegalArgumentException {
    108        if (keys == null) {
    109            throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEYS);
    110        }
    111        final Iterator<K> iter = keys.iterator();
    112        while (iter.hasNext()) {
    113            addObjects(iter.next(), 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, IllegalArgumentException {
    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     * Obtains 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, NoSuchElementException, IllegalStateException;
    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, UnsupportedOperationException;
    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, UnsupportedOperationException;
    200
    201    /**
    202     * Close 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     * Returns the total number of instances currently borrowed from this pool but
    217     * not yet returned. Returns a negative value if this information is not
    218     * available.
    219     * @return the total number of instances currently borrowed from this pool but
    220     * not yet returned.
    221     */
    222    int getNumActive();
    223
    224    /**
    225     * Returns the number of instances currently borrowed from but not yet
    226     * returned to the pool corresponding to the given {@code key}.
    227     * Returns a negative value if this information is not available.
    228     *
    229     * @param key the key to query
    230     * @return the number of instances currently borrowed from but not yet
    231     * returned to the pool corresponding to the given {@code key}.
    232     */
    233    int getNumActive(K key);
    234
    235    /**
    236     * Returns the total number of instances currently idle in this pool.
    237     * Returns a negative value if this information is not available.
    238     * @return the total number of instances currently idle in this pool.
    239     */
    240    int getNumIdle();
    241
    242    /**
    243     * Returns the number of instances corresponding to the given
    244     * {@code key} currently idle in this pool. Returns a negative value if
    245     * this information is not available.
    246     *
    247     * @param key the key to query
    248     * @return the number of instances corresponding to the given
    249     * {@code key} currently idle in this pool.
    250     */
    251    int getNumIdle(K key);
    252
    253    /**
    254     * Invalidates an object from the pool.
    255     * <p>
    256     * By contract, {@code obj} <strong>must</strong> have been obtained
    257     * using {@link #borrowObject borrowObject} or a related method as defined
    258     * in an implementation or sub-interface using a {@code key} that is
    259     * equivalent to the one used to borrow the {@code Object} in the first
    260     * place.
    261     * </p>
    262     * <p>
    263     * This method should be used when an object that has been borrowed is
    264     * determined (due to an exception or other problem) to be invalid.
    265     * </p>
    266     *
    267     * @param key the key used to obtain the object
    268     * @param obj a {@link #borrowObject borrowed} instance to be returned.
    269     *
    270     * @throws Exception if the instance cannot be invalidated
    271     */
    272    void invalidateObject(K key, V obj) throws Exception;
    273
    274
    275    /**
    276     * Invalidates an object from the pool, using the provided
    277     * {@link DestroyMode}.
    278     * <p>
    279     * By contract, {@code obj} <strong>must</strong> have been obtained
    280     * using {@link #borrowObject borrowObject} or a related method as defined
    281     * in an implementation or sub-interface using a {@code key} that is
    282     * equivalent to the one used to borrow the {@code Object} in the first
    283     * place.
    284     * </p>
    285     * <p>
    286     * This method should be used when an object that has been borrowed is
    287     * determined (due to an exception or other problem) to be invalid.
    288     * </p>
    289     *
    290     * @param key the key used to obtain the object
    291     * @param obj a {@link #borrowObject borrowed} instance to be returned.
    292     * @param mode destroy activation context provided to the factory
    293     *
    294     * @throws Exception if the instance cannot be invalidated
    295     * @since 2.9.0
    296     */
    297    default void invalidateObject(final K key, final V obj, final DestroyMode mode) throws Exception {
    298        invalidateObject(key, obj);
    299    }
    300
    301    /**
    302     * Return an instance to the pool. By contract, {@code obj}
    303     * <strong>must</strong> have been obtained using
    304     * {@link #borrowObject borrowObject} or a related method as defined in an
    305     * implementation or sub-interface using a {@code key} that is
    306     * equivalent to the one used to borrow the instance in the first place.
    307     *
    308     * @param key the key used to obtain the object
    309     * @param obj a {@link #borrowObject borrowed} instance to be returned.
    310     *
    311     * @throws IllegalStateException
    312     *              if an attempt is made to return an object to the pool that
    313     *              is in any state other than allocated (i.e. borrowed).
    314     *              Attempting to return an object more than once or attempting
    315     *              to return an object that was never borrowed from the pool
    316     *              will trigger this exception.
    317     *
    318     * @throws Exception if an instance cannot be returned to the pool
    319     */
    320    void returnObject(K key, V obj) throws Exception;
    321}