    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}