1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.pool2; 18 19 import java.io.Closeable; 20 import java.util.Collection; 21 import java.util.Collections; 22 import java.util.List; 23 import java.util.NoSuchElementException; 24 25 /** 26 * A "keyed" pooling interface. 27 * <p> 28 * A keyed pool maintains a pool of instances for each key value. 29 * </p> 30 * <p> 31 * Example of use: 32 * </p> 33 * <pre style="border:solid thin; padding: 1ex;" 34 * > Object obj = <code style="color:#00C">null</code>; 35 * Object key = <code style="color:#C00">"Key"</code>; 36 * 37 * <code style="color:#00C">try</code> { 38 * obj = pool.borrowObject(key); 39 * <code style="color:#0C0">//...use the object...</code> 40 * } <code style="color:#00C">catch</code> (Exception e) { 41 * <code style="color:#0C0">// invalidate the object</code> 42 * pool.invalidateObject(key, obj); 43 * <code style="color:#0C0">// do not return the object to the pool twice</code> 44 * obj = <code style="color:#00C">null</code>; 45 * } <code style="color:#00C">finally</code> { 46 * <code style="color:#0C0">// make sure the object is returned to the pool</code> 47 * <code style="color:#00C">if</code> (<code style="color:#00C">null</code> != obj) { 48 * pool.returnObject(key, obj); 49 * } 50 * }</pre> 51 * <p> 52 * {@link KeyedObjectPool} implementations <i>may</i> choose to store at most 53 * one instance per key value, or may choose to maintain a pool of instances 54 * for each key (essentially creating a {@link java.util.Map Map} of 55 * {@link ObjectPool pools}). 56 * </p> 57 * <p> 58 * See {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool 59 * GenericKeyedObjectPool} for an implementation. 60 * </p> 61 * 62 * @param <K> The type of keys maintained by this pool. 63 * @param <V> Type of element pooled in this pool. 64 * 65 * 66 * @see KeyedPooledObjectFactory 67 * @see ObjectPool 68 * @see org.apache.commons.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool 69 * 70 * @since 2.0 71 */ 72 public interface KeyedObjectPool<K, V> extends Closeable { 73 74 /** 75 * Creates an object using the {@link KeyedPooledObjectFactory factory} or 76 * other implementation dependent mechanism, passivate it, and then place it 77 * in the idle object pool. {@code addObject} is useful for 78 * "pre-loading" a pool with idle objects (Optional operation). 79 * 80 * @param key the key a new instance should be added to 81 * 82 * @throws Exception 83 * when {@link KeyedPooledObjectFactory#makeObject} fails. 84 * @throws IllegalStateException 85 * after {@link #close} has been called on this pool. 86 * @throws UnsupportedOperationException 87 * when this pool cannot add new idle objects. 88 */ 89 void addObject(K key) throws Exception; 90 91 /** 92 * Calls {@link KeyedObjectPool#addObject(Object)} with each 93 * key in {@code keys} for {@code count} number of times. This has 94 * the same effect as calling {@link #addObjects(Object, int)} 95 * for each key in the {@code keys} collection. 96 * 97 * @param keys 98 * {@link Collection} of keys to add objects for. 99 * @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 }