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 <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}