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}