    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 *      https://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 <em>may</em> 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 * @since 2.0
    070 */
    071public interface KeyedObjectPool<K, V> extends Closeable {
    072
    073    /**
    074     * Creates an object using the {@link KeyedPooledObjectFactory factory} or
    075     * other implementation dependent mechanism, passivate it, and then place it
    076     * in the idle object pool. {@code addObject} is useful for
    077     * "pre-loading" a pool with idle objects (Optional operation).
    078     *
    079     * @param key the key a new instance should be added to
    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;
    088
    089    /**
    090     * Calls {@link KeyedObjectPool#addObject(Object)} with each
    091     * key in {@code keys} for {@code count} number of times. This has
    092     * the same effect as calling {@link #addObjects(Object, int)}
    093     * for each key in the {@code keys} collection.
    094     *
    095     * @param keys
    096     *            {@link Collection} of keys to add objects for.
    097     * @param count
    098     *            the number of idle objects to add for each {@code key}.
    099     * @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}