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