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 */
017
018package org.apache.commons.pool.impl;
019
020import java.util.Iterator;
021import java.util.NoSuchElementException;
022import java.util.Stack;
023
024import org.apache.commons.pool.BaseObjectPool;
025import org.apache.commons.pool.ObjectPool;
026import org.apache.commons.pool.PoolUtils;
027import org.apache.commons.pool.PoolableObjectFactory;
028
029/**
030 * A simple, {@link java.util.Stack Stack}-based {@link ObjectPool} implementation.
031 * <p>
032 * Given a {@link PoolableObjectFactory}, this class will maintain
033 * a simple pool of instances.  A finite number of "sleeping"
034 * or idle instances is enforced, but when the pool is
035 * empty, new instances are created to support the new load.
036 * Hence this class places no limit on the number of "active"
037 * instances created by the pool, but is quite useful for
038 * re-using <tt>Object</tt>s without introducing
039 * artificial limits.
040 *
041 * @param <T> the type of objects held in this pool
042 * 
043 * @author Rodney Waldhoff
044 * @author Dirk Verbeeck
045 * @author Sandy McArthur
046 * @version $Revision: 892236 $ $Date: 2013-12-31 04:43:12 +0000 (Tue, 31 Dec 2013) $
047 * @since Pool 1.0
048 */
049public class StackObjectPool<T> extends BaseObjectPool<T> implements ObjectPool<T> {
050    /**
051     * Create a new pool using no factory. Clients must first 
052     * {@link #setFactory(PoolableObjectFactory) set the factory} or
053     * else this pool will not behave correctly. Clients may first populate the pool
054     * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed}
055     * but this usage is <strong>discouraged</strong>.
056     *
057     * @see #StackObjectPool(PoolableObjectFactory)
058     * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory)}
059     */
060    @Deprecated
061    public StackObjectPool() {
062        this(null,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY);
063    }
064
065    /**
066     * Create a new pool using no factory.
067     * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory} or
068     * else this pool will not behave correctly. Clients may first populate the pool
069     * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed}
070     * but this usage is <strong>discouraged</strong>.
071     *
072     * @param maxIdle cap on the number of "sleeping" instances in the pool
073     * @see #StackObjectPool(PoolableObjectFactory, int)
074     * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory, int)}
075     */
076    @Deprecated
077    public StackObjectPool(int maxIdle) {
078        this(null,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY);
079    }
080
081    /**
082     * Create a new pool using no factory.
083     * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory} or
084     * else this pool will not behave correctly. Clients may first populate the pool
085     * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed}
086     * but this usage is <strong>discouraged</strong>.
087     *
088     * @param maxIdle cap on the number of "sleeping" instances in the pool
089     * @param initIdleCapacity initial size of the pool (this specifies the size of the container,
090     *             it does not cause the pool to be pre-populated.)
091     * @see #StackObjectPool(PoolableObjectFactory, int, int)
092     * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory, int, int)}
093     */
094    @Deprecated
095    public StackObjectPool(int maxIdle, int initIdleCapacity) {
096        this(null,maxIdle,initIdleCapacity);
097    }
098
099    /**
100     * Create a new <tt>StackObjectPool</tt> using the specified <i>factory</i> to create new instances.
101     *
102     * @param factory the {@link PoolableObjectFactory} used to populate the pool
103     */
104    public StackObjectPool(PoolableObjectFactory<T> factory) {
105        this(factory,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY);
106    }
107
108    /**
109     * Create a new <tt>SimpleObjectPool</tt> using the specified <i>factory</i> to create new instances,
110     * capping the number of "sleeping" instances to <i>maxIdle</i>.
111     *
112     * @param factory the {@link PoolableObjectFactory} used to populate the pool
113     * @param maxIdle cap on the number of "sleeping" instances in the pool
114     */
115    public StackObjectPool(PoolableObjectFactory<T> factory, int maxIdle) {
116        this(factory,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY);
117    }
118
119    /**
120     * <p>Create a new <tt>StackObjectPool</tt> using the specified <code>factory</code> to create new instances,
121     * capping the number of "sleeping" instances to <code>maxIdle</code>, and initially allocating a container
122     * capable of containing at least <code>initIdleCapacity</code> instances.  The pool is not pre-populated.
123     * The <code>initIdleCapacity</code> parameter just determines the initial size of the underlying
124     * container, which can increase beyond this value if <code>maxIdle &gt; initIdleCapacity.</code></p>
125     * 
126     * <p>Negative values of <code>maxIdle</code> are ignored (i.e., the pool is created using
127     * {@link #DEFAULT_MAX_SLEEPING}) as are non-positive values for <code>initIdleCapacity.</code>
128     *
129     * @param factory the {@link PoolableObjectFactory} used to populate the pool
130     * @param maxIdle cap on the number of "sleeping" instances in the pool
131     * @param initIdleCapacity initial size of the pool (this specifies the size of the container,
132     *             it does not cause the pool to be pre-populated.)
133     */
134    public StackObjectPool(PoolableObjectFactory<T> factory, int maxIdle, int initIdleCapacity) {
135        _factory = factory;
136        _maxSleeping = (maxIdle < 0 ? DEFAULT_MAX_SLEEPING : maxIdle);
137        int initcapacity = (initIdleCapacity < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : initIdleCapacity);
138        _pool = new Stack<T>();
139        _pool.ensureCapacity( initcapacity > _maxSleeping ? _maxSleeping : initcapacity);
140    }
141
142    /**
143     * <p>Borrows an object from the pool.  If there are idle instances available on the stack,
144     * the top element of the stack is popped to activate, validate and return to the client.  If there
145     * are no idle instances available, the {@link PoolableObjectFactory#makeObject() makeObject} 
146     * method of the pool's {@link PoolableObjectFactory} is invoked to create a new instance.</p>
147     * 
148     * <p>All instances are {@link PoolableObjectFactory#activateObject(Object) activated} and
149     * {@link PoolableObjectFactory#validateObject(Object) validated} before being returned to the
150     * client.  If validation fails or an exception occurs activating or validating an instance 
151     * popped from the idle instance stack, the failing instance is 
152     * {@link PoolableObjectFactory#destroyObject(Object) destroyed} and the next instance on
153     * the stack is popped, validated and activated.  This process continues until either the
154     * stack is empty or an instance passes validation.  If the stack is empty on activation or
155     * it does not contain any valid instances, the factory's <code>makeObject</code> method is used
156     * to create a new instance.  If a null instance is returned by the factory or the created
157     * instance either raises an exception on activation or fails validation, <code>NoSuchElementException</code>
158     * is thrown. Exceptions thrown by <code>MakeObject</code> are propagated to the caller; but 
159     * other than <code>ThreadDeath</code> or <code>VirtualMachineError</code>, exceptions generated by
160     * activation, validation or destroy methods are swallowed silently.</p>
161     * 
162     * @return an instance from the pool
163     */
164    @Override
165    public synchronized T borrowObject() throws Exception {
166        assertOpen();
167        T obj = null;
168        boolean newlyCreated = false;
169        while (null == obj) {
170            if (!_pool.empty()) {
171                obj = _pool.pop();
172            } else {
173                if(null == _factory) {
174                    throw new NoSuchElementException();
175                } else {
176                    obj = _factory.makeObject();
177                    newlyCreated = true;
178                  if (obj == null) {
179                    throw new NoSuchElementException("PoolableObjectFactory.makeObject() returned null.");
180                  }
181                }
182            }
183            if (null != _factory && null != obj) {
184                try {
185                    _factory.activateObject(obj);
186                    if (!_factory.validateObject(obj)) {
187                        throw new Exception("ValidateObject failed");
188                    }
189                } catch (Throwable t) {
190                    PoolUtils.checkRethrow(t);
191                    try {
192                        _factory.destroyObject(obj);
193                    } catch (Throwable t2) {
194                        PoolUtils.checkRethrow(t2);
195                        // swallowed
196                    } finally {
197                        obj = null;
198                    }
199                    if (newlyCreated) {
200                        throw new NoSuchElementException(
201                            "Could not create a validated object, cause: " +
202                            t.getMessage());
203                    }
204                }
205            }
206        }
207        _numActive++;
208        return obj;
209    }
210
211    /**
212     * <p>Returns an instance to the pool, pushing it on top of the idle instance stack after successful
213     * validation and passivation. The returning instance is destroyed if any of the following are true:<ul>
214     *   <li>the pool is closed</li>
215     *   <li>{@link PoolableObjectFactory#validateObject(Object) validation} fails</li>
216     *   <li>{@link PoolableObjectFactory#passivateObject(Object) passivation} throws an exception</li>
217     * </ul>
218     * If adding a validated, passivated returning instance to the stack would cause
219     * {@link #getMaxSleeping() maxSleeping} to be exceeded, the oldest (bottom) instance on the stack
220     * is destroyed to make room for the returning instance, which is pushed on top of the stack.</p>
221     * 
222     * <p>Exceptions passivating or destroying instances are silently swallowed.  Exceptions validating
223     * instances are propagated to the client.</p>
224     * 
225     * @param obj instance to return to the pool
226     */
227    @Override
228    public synchronized void returnObject(T obj) throws Exception {
229        boolean success = !isClosed();
230        if(null != _factory) {
231            if(!_factory.validateObject(obj)) {
232                success = false;
233            } else {
234                try {
235                    _factory.passivateObject(obj);
236                } catch(Exception e) {
237                    success = false;
238                }
239            }
240        }
241
242        boolean shouldDestroy = !success;
243
244        _numActive--;
245        if (success) {
246            T toBeDestroyed = null;
247            if(_pool.size() >= _maxSleeping) {
248                shouldDestroy = true;
249                toBeDestroyed = _pool.remove(0); // remove the stalest object
250            }
251            _pool.push(obj);
252            obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed
253        }
254        notifyAll(); // _numActive has changed
255
256        if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null
257            try {
258                _factory.destroyObject(obj);
259            } catch(Exception e) {
260                // ignored
261            }
262        }
263    }
264
265    /**
266     * {@inheritDoc}
267     */
268    @Override
269    public synchronized void invalidateObject(T obj) throws Exception {
270        _numActive--;
271        if (null != _factory) {
272            _factory.destroyObject(obj);
273        }
274        notifyAll(); // _numActive has changed
275    }
276
277    /**
278     * Return the number of instances
279     * currently idle in this pool.
280     *
281     * @return the number of instances currently idle in this pool
282     */
283    @Override
284    public synchronized int getNumIdle() {
285        return _pool.size();
286    }
287
288    /**
289     * Return the number of instances currently borrowed from this pool.
290     *
291     * @return the number of instances currently borrowed from this pool
292     */
293    @Override
294    public synchronized int getNumActive() {
295        return _numActive;
296    }
297
298    /**
299     * Clears any objects sitting idle in the pool. Silently swallows any
300     * exceptions thrown by {@link PoolableObjectFactory#destroyObject(Object)}.
301     */
302    @Override
303    public synchronized void clear() {
304        if(null != _factory) {
305            Iterator<T> it = _pool.iterator();
306            while(it.hasNext()) {
307                try {
308                    _factory.destroyObject(it.next());
309                } catch(Exception e) {
310                    // ignore error, keep destroying the rest
311                }
312            }
313        }
314        _pool.clear();
315    }
316
317    /**
318     * <p>Close this pool, and free any resources associated with it. Invokes
319     * {@link #clear()} to destroy and remove instances in the pool.</p>
320     * 
321     * <p>Calling {@link #addObject} or {@link #borrowObject} after invoking
322     * this method on a pool will cause them to throw an
323     * {@link IllegalStateException}.</p>
324     *
325     * @throws Exception never - exceptions clearing the pool are swallowed
326     */
327    @Override
328    public void close() throws Exception {
329        super.close();
330        clear();
331    }
332
333    /**
334     * <p>Create an object, and place it on top of the stack.
335     * This method is useful for "pre-loading" a pool with idle objects.</p>
336     * 
337     * <p>Before being added to the pool, the newly created instance is
338     * {@link PoolableObjectFactory#validateObject(Object) validated} and 
339     * {@link PoolableObjectFactory#passivateObject(Object) passivated}.  If validation
340     * fails, the new instance is {@link PoolableObjectFactory#destroyObject(Object) destroyed}.
341     * Exceptions generated by the factory <code>makeObject</code> or <code>passivate</code> are
342     * propagated to the caller. Exceptions destroying instances are silently swallowed.</p>
343     * 
344     * <p>If a new instance is created and successfully validated and passivated and adding this
345     * instance to the pool causes {@link #getMaxSleeping() maxSleeping} to be exceeded, the oldest
346     * (bottom) instance in the pool is destroyed to make room for the newly created instance, which
347     * is pushed on top of the stack.
348     * 
349     * @throws Exception when the {@link #getFactory() factory} has a problem creating or passivating an object.
350     */
351    @Override
352    public synchronized void addObject() throws Exception {
353        assertOpen();
354        if (_factory == null) {
355            throw new IllegalStateException("Cannot add objects without a factory.");
356        }
357        T obj = _factory.makeObject();
358
359        boolean success = true;
360        if(!_factory.validateObject(obj)) {
361            success = false;
362        } else {
363            _factory.passivateObject(obj);
364        }
365
366        boolean shouldDestroy = !success;
367
368        if (success) {
369            T toBeDestroyed = null;
370            if(_pool.size() >= _maxSleeping) {
371                shouldDestroy = true;
372                toBeDestroyed = _pool.remove(0); // remove the stalest object
373            }
374            _pool.push(obj);
375            obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed
376        }
377        notifyAll(); // _numIdle has changed
378
379        if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null
380            try {
381                _factory.destroyObject(obj);
382            } catch(Exception e) {
383                // ignored
384            }
385        }
386    }
387
388    /**
389     * Sets the {@link PoolableObjectFactory factory} this pool uses
390     * to create new instances. Trying to change
391     * the <code>factory</code> while there are borrowed objects will
392     * throw an {@link IllegalStateException}.
393     *
394     * @param factory the {@link PoolableObjectFactory} used to create new instances.
395     * @throws IllegalStateException when the factory cannot be set at this time
396     * @deprecated to be removed in pool 2.0
397     */
398    @Deprecated
399    @Override
400    public synchronized void setFactory(PoolableObjectFactory<T> factory) throws IllegalStateException {
401        assertOpen();
402        if(0 < getNumActive()) {
403            throw new IllegalStateException("Objects are already active");
404        } else {
405            clear();
406            _factory = factory;
407        }
408    }
409
410    /**
411     * The cap on the number of "sleeping" instances in the pool.
412     */
413    protected static final int DEFAULT_MAX_SLEEPING  = 8;
414
415    /**
416     * The default initial size of the pool
417     * (this specifies the size of the container, it does not
418     * cause the pool to be pre-populated.)
419     */
420    protected static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4;
421
422    /** 
423     * My pool.
424     * @deprecated to be made private in pool 2.0 
425     */
426    @Deprecated
427    protected Stack<T> _pool = null;
428
429    /** 
430     * My {@link PoolableObjectFactory}.
431     * @deprecated to be made private in pool 2.0 - use {@link #getFactory()}
432     */
433    @Deprecated
434    protected PoolableObjectFactory<T> _factory = null;
435
436    /** 
437     * The cap on the number of "sleeping" instances in the pool. 
438     * @deprecated to be made private in pool 2.0 - use {@link #getMaxSleeping()}
439     */
440    @Deprecated
441    protected int _maxSleeping = DEFAULT_MAX_SLEEPING;
442    
443    /**
444     * Number of objects borrowed but not yet returned to the pool.
445     * @deprecated to be made private in pool 2.0 - use {@link #getNumActive()}
446     */
447    @Deprecated
448    protected int _numActive = 0;
449
450    /**
451     * Returns the {@link PoolableObjectFactory} used by this pool to create and manage object instances.
452     * 
453     * @return the factory
454     * @since 1.5.5
455     */
456    public synchronized PoolableObjectFactory<T> getFactory() {
457        return _factory;
458    }
459
460    /**
461     * Returns the maximum number of idle instances in the pool.
462     * 
463     * @return maxSleeping
464     * @since 1.5.5
465     */
466    public int getMaxSleeping() {
467        return _maxSleeping;
468    }
469
470   
471}