/*
 * $Source: /home/cvs/commons/pool1.1/ja/src/org/apache/commons/pool/impl/GenericObjectPool.java,v $
 * $Revision: 1.1 $
 * $Date: 2004/02/22 11:58:26 $
 *
 * ====================================================================
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowledgement:
 *       "This product includes software developed by the
 *        Apache Software Foundation - http://www.apache.org/"
 *    Alternately, this acknowledgement may appear in the software itself,
 *    if and wherever such third-party acknowledgements normally appear.
 *
 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * http://www.apache.org/
 *
 */

package org.apache.commons.pool.impl;

import java.util.Iterator;
import java.util.NoSuchElementException;

import org.apache.commons.collections.CursorableLinkedList;
import org.apache.commons.pool.BaseObjectPool;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;

/**
 * 詳細な設定の可能な {@link ObjectPool} の実装です。
 * {@primary A configurable {@link ObjectPool} implementation.}
 * <p>
 * 適切な {@link PoolableObjectFactory} と対となって動作することにより
 * <tt>GenericObjectPool</tt> は強固な任意のオブジェクトのプーリングの機能を提供します。
 * {@primary When coupled with the appropriate {@link PoolableObjectFactory},
 * <tt>GenericObjectPool</tt> provides robust pooling functionality for
 * arbitrary objects.}
 * <p>
 * <tt>GenericObjectPool</tt> は多くの設定可能なパラメータを提供します。
 * {@primary A <tt>GenericObjectPool</tt> provides a number of configurable parameters:}
 * <ul>
 *  <li>
 *    {@link #setMaxActive <i>maxActive</i>} は同時にプールから取り出すことのできるオブジェクトの最大数を制御します。
 *    マイナスの値が設定された場合には同時にプールから取り出すことのできるオブジェクトの制限を行いません。
 *    {@link #setMaxActive <i>maxActive</i>} を超えた場合、プールは使い尽されていることになります。
 *    {@primary {@link #setMaxActive <i>maxActive</i>} controls the maximum number of objects that can
 *    be borrowed from the pool at one time.  When negative, there
 *    is no limit to the number of objects that may be active at one time.
 *    When {@link #setMaxActive <i>maxActive</i>} is exceeded, the pool is said to be exhausted.}
 *  </li>
 *  <li>
 *    {@link #setMaxIdle <i>maxIdle</i>} はプール内に保持できる未使用のオブジェクトの最大数を制御します。
 *    マイナスの値が設定された場合には同時にプール内に保持できるオブジェクトの制限を行いません。
 *    {@primary {@link #setMaxIdle <i>maxIdle</i>} controls the maximum number of objects that can
 *    sit idle in the pool at any time.  When non-positive, there
 *    is no limit to the number of objects that may be idle at one time.}
 *  </li>
 *  <li>
 *    {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} 
 *    はプールが使い尽されている場合の {@link #borrowObject} メソッドの振る舞いを指定します:
 *    {@primary {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} specifies the
 *    behaviour of the {@link #borrowObject} method when the pool is exhausted:}
 *    <ul>
 *    <li>
 *      {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} が
 *      {@link #WHEN_EXHAUSTED_FAIL}の場合、
 *      {@link #borrowObject} は {@link NoSuchElementException} を投げます。
 *      {@primary When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
 *      {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject} will throw
 *      a {@link NoSuchElementException}}
 *    </li>
 *    <li>
 *      {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} が
 *      {@link #WHEN_EXHAUSTED_GROW} の場合、
 *      {@link #borrowObject} は新たなオブジェクトを生成し、返します
 *      (実質、{@link #setMaxActive <i>maxActive</i>} は意味をなしません)。
 *      {@primary When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
 *      {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject} will create a new
 *      object and return it(essentially making {@link #setMaxActive <i>maxActive</i>}
 *      meaningless.)}
 *    </li>
 *    <li>
 *      {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} が
 *      {@link #WHEN_EXHAUSTED_BLOCK} の場合、
 *      {@link #borrowObject} は新たなもしくは未使用のオブジェクトが利用できるまで({@link Object#wait} を呼んで)待機します。
 *      有効な {@link #setMaxWait <i>maxWait</i>} が設定されている場合、
 *      {@link #borrowObject} は設定されたミリセカンド待機した後に {@link NoSuchElementException} を投げます。
 *      {@link #setMaxWait <i>maxWait</i>} がマイナスの値だった場合
 *      {@link #borrowObject} は無期限に待機します。
 *      {@primary When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>}
 *      is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject} will block
 *      (invoke {@link Object#wait} until a new or idle object is available.
 *      If a positive {@link #setMaxWait <i>maxWait</i>}
 *      value is supplied, the {@link #borrowObject} will block for at
 *      most that many milliseconds, after which a {@link NoSuchElementException}
 *      will be thrown.  If {@link #setMaxWait <i>maxWait</i>} is non-positive,
 *      the {@link #borrowObject} method will block indefinitely.}
 *    </li>
 *    </ul>
 *  </li>
 *  <li>
 *    {@link #setTestOnBorrow <i>testOnBorrow</i>} が設定されている場合、プールは
 *    {@link #borrowObject} メソッドにて取り出される前に
 *    (提供されたファクトリの {@link PoolableObjectFactory#validateObject} メソッドを使用して)
 *    オブジェクトが有効かどうかの確認を試みます。
 *    有効でないと判断されたオブジェクトはプールから破棄され、他のオブジェクトが取り出されます。
 *    {@primary When {@link #setTestOnBorrow <i>testOnBorrow</i>} is set, the pool will
 *    attempt to validate each object before it is returned from the
 *    {@link #borrowObject} method. (Using the provided factory's
 *    {@link PoolableObjectFactory#validateObject} method.)  Objects that fail
 *    to validate will be dropped from the pool, and a different object will
 *    be borrowed.}
 *  </li>
 *  <li>
 *    When {@link #setTestOnReturn <i>testOnReturn</i>} が設定されている場合、プールは
 *    {@link #returnObject} メソッドにて戻される前に
 *    (提供されたファクトリの {@link PoolableObjectFactory#validateObject} メソッドを使用して)
 *    オブジェクトが有効かどうかの確認を試みます。
 *    有効でないと判断されたオブジェクトはプールから破棄されます。
 *    {@primary When {@link #setTestOnReturn <i>testOnReturn</i>} is set, the pool will
 *    attempt to validate each object before it is returned to the pool in the
 *    {@link #returnObject} method. (Using the provided factory's
 *    {@link PoolableObjectFactory#validateObject}
 *    method.)  Objects that fail to validate will be dropped from the pool.}
 *  </li>
 * </ul>
 * <p>
 * オプションとして、プール内を走査して不正な状態でプール内に居続けるオブジェクトを排除する設定をすることができます。
 * これは非同期な "未使用オブジェクト排除" スレッドで行われます。
 * "未使用オブジェクト排除" スレッドの挙動は以下の属性で設定されます:
 * {@primary Optionally, one may configure the pool to examine and possibly evict objects as they
 * sit idle in the pool.  This is performed by an "idle object eviction" thread, which
 * runs asychronously.  The idle object eviction thread may be configured using the
 * following attributes:}
 * <ul>
 *  <li>
 *   {@link #setTimeBetweenEvictionRunsMillis <i>timeBetweenEvictionRunsMillis</i>} 
 *   は排除スレッドがオブジェクト排除処理を実行する前にどのくらいの間スリープするかを示します。
 *   マイナスの値が設定された場合、排除スレッドは起動しません。
 *   {@primary {@link #setTimeBetweenEvictionRunsMillis <i>timeBetweenEvictionRunsMillis</i>}
 *   indicates how long the eviction thread should sleep before "runs" of examining
 *   idle objects.  When non-positive, no eviction thread will be launched.}
 *  </li>
 *  <li>
 *   {@link #setMinEvictableIdleTimeMillis <i>minEvictableIdleTimeMillis</i>}
 *   はオブジェクトがプール内に未使用状態でいられる時間の最小値を指定します。
 *   未使用状態でいる時間がこの値に達すると排除処理の対象となります。
 *   マイナスの値が設定された場合、未使用状態でいる時間が原因ではオブジェクトの削除は行われません。
 *   {@primary {@link #setMinEvictableIdleTimeMillis <i>minEvictableIdleTimeMillis</i>}
 *   specifies the minimum amount of time that an object may sit idle in the pool
 *   before it is eligable for eviction due to idle time.  When non-positive, no object
 *   will be dropped from the pool due to idle time alone.}
 *  </li>
 *  <li>
 *   {@link #setTestWhileIdle <i>testWhileIdle</i>} 
 *   は未使用状態のオブジェクトに対してファクトリの
 *   {@link PoolableObjectFactory#validateObject} メソッドを使ってチェックを行うかどうかを示します。
 *   有効でないと判断されたオブジェクトはプールから破棄されます。
 *   {@primary {@link #setTestWhileIdle <i>testWhileIdle</i>} indicates whether or not idle
 *   objects should be validated using the factory's
 *   {@link PoolableObjectFactory#validateObject} method.  Objects
 *   that fail to validate will be dropped from the pool.}
 *  </li>
 * </ul>
 * <p>
 * {@link PoolableObjectFactory} を使用しない場合、GenericObjectPool は有用ではありません。
 * コンストラクタの引数または、{@link #setFactory} メソッドをコールすることによって
 * <code>null</code> ではないファクトリを提供する必要があります。
 * {@primary GenericObjectPool is not usable without a {@link PoolableObjectFactory}.  A
 * non-<code>null</code> factory must be provided either as a constructor argument
 * or via a call to {@link #setFactory} before the pool is used.}
 *
 * @see GenericKeyedObjectPool
 * @author Rodney Waldhoff
 * @author Dirk Verbeeck
 * @version $Revision: 1.1 $ $Date: 2004/02/22 11:58:26 $
 *
 * @translator 日置 聡
 * @status firstdraft
 * @update 2004/02/21
 */
public class GenericObjectPool extends BaseObjectPool implements ObjectPool {

    //--- public constants -------------------------------------------

    /**
     * "使い尽された時の処理"のタイプ、
     * プールが尽されている場合 (同時にプールから取り出すことのできるオブジェクトの最大数に達した場合)
     * の処理を示し、{@link #borrowObject} メソッドは失敗し、{@link NoSuchElementException} を投げます。
     * {@primary A "when exhausted action" type indicating that when the pool is
     * exhausted (i.e., the maximum number of active objects has
     * been reached), the {@link #borrowObject}
     * method should fail, throwing a {@link NoSuchElementException}.}
     * @see #WHEN_EXHAUSTED_BLOCK
     * @see #WHEN_EXHAUSTED_GROW
     * @see #setWhenExhaustedAction
     */
    public static final byte WHEN_EXHAUSTED_FAIL   = 0;

    /**
     * "使い尽された時の処理"のタイプ、
     * プールが尽されている場合 (同時にプールから取り出すことのできるオブジェクトの最大数に達した場合)
     * の処理を示し、{@link #borrowObject} メソッドは新たなオブジェクトが利用できるまでまたは
     * {@link #getMaxWait 最大待機時間} に達するまで待機します。
     * {@primary A "when exhausted action" type indicating that when the pool
     * is exhausted (i.e., the maximum number
     * of active objects has been reached), the {@link #borrowObject}
     * method should block until a new object is available, or the
     * {@link #getMaxWait maximum wait time} has been reached.}
     * @see #WHEN_EXHAUSTED_FAIL
     * @see #WHEN_EXHAUSTED_GROW
     * @see #setMaxWait
     * @see #getMaxWait
     * @see #setWhenExhaustedAction
     */
    public static final byte WHEN_EXHAUSTED_BLOCK  = 1;

    /**
     * "使い尽された時の処理"のタイプ、
     * プールが尽されている場合 (同時にプールから取り出すことのできるオブジェクトの最大数に達した場合)
     * の処理を示し、{@link #borrowObject} メソッドは単純にとにかく新たなオブジェクトを生成します。
     * {@primary A "when exhausted action" type indicating that when the pool is
     * exhausted (i.e., the maximum number
     * of active objects has been reached), the {@link #borrowObject}
     * method should simply create a new object anyway.}
     * @see #WHEN_EXHAUSTED_FAIL
     * @see #WHEN_EXHAUSTED_GROW
     * @see #setWhenExhaustedAction
     */
    public static final byte WHEN_EXHAUSTED_GROW   = 2;

    /**
     * プール内に保持できる未使用インスタンスの最大数のデフォルト値です。
     * {@primary The default cap on the number of "sleeping" instances in the pool.}
     * @see #getMaxIdle
     * @see #setMaxIdle
     */
    public static final int DEFAULT_MAX_IDLE  = 8;

    /**
     * プール内に保持される未使用インスタンスの最少数のデフォルト値です。
     * {@primary The default minimum number of "sleeping" instances in the pool
     * before before the evictor thread (if active) spawns new objects.}
     * @see #getMinIdle
     * @see #setMinIdle
     */
    public static final int DEFAULT_MIN_IDLE = 0;

    /**
     * 同時にプールから取り出すことのできるインスタンスの最大数のデフォルト値です。
     * {@primary The default cap on the total number of active instances from the pool.}
     * @see #getMaxActive
     */
    public static final int DEFAULT_MAX_ACTIVE  = 8;

    /**
     * "使い尽された時の処理"のタイプのデフォルト値です。
     * {@primary The default "when exhausted action" for the pool.}
     * @see #WHEN_EXHAUSTED_BLOCK
     * @see #WHEN_EXHAUSTED_FAIL
     * @see #WHEN_EXHAUSTED_GROW
     * @see #setWhenExhaustedAction
     */
    public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK;

    /**
     * プールが使い尽されていて {@link #getWhenExhaustedAction "使い尽された時の処理"} に
     * {@link #WHEN_EXHAUSTED_BLOCK} が設定されている場合の
     * {@link #borrowObject} メソッドが例外を投げるまでの最長待機時間(ミリセカンド)のデフォルト値です。
     * {@primary The default maximum amount of time (in millis) the
     * {@link #borrowObject} method should block before throwing
     * an exception when the pool is exhausted and the
     * {@link #getWhenExhaustedAction "when exhausted" action} is
     * {@link #WHEN_EXHAUSTED_BLOCK}.}
     * @see #getMaxWait
     * @see #setMaxWait
     */
    public static final long DEFAULT_MAX_WAIT = -1L;

    /**
     * オブジェクトの状態を "取り出し時に確認" するかどうかのデフォルトの値です。
     * {@primary The default "test on borrow" value.}
     * @see #getTestOnBorrow
     * @see #setTestOnBorrow
     */
    public static final boolean DEFAULT_TEST_ON_BORROW = false;

    /**
     * オブジェクトの状態を "戻される時に確認" するかどうかのデフォルトの値です。
     * {@primary The default "test on return" value.}
     * @see #getTestOnReturn
     * @see #setTestOnReturn
     */
    public static final boolean DEFAULT_TEST_ON_RETURN = false;

    /**
     * オブジェクトの状態を "未使用の間に確認" するかどうかのデフォルトの値です。
     * {@primary The default "test while idle" value.}
     * @see #getTestWhileIdle
     * @see #setTestWhileIdle
     * @see #getTimeBetweenEvictionRunsMillis
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public static final boolean DEFAULT_TEST_WHILE_IDLE = false;

    /**
     * "オブジェクト排除処理の実行間隔" のデフォルトの値です。
     * {@primary The default "time between eviction runs" value.}
     * @see #getTimeBetweenEvictionRunsMillis
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;

    /**
     * 1度のオブジェクト排除処理でチェックされるオブジェクトの数のデフォルト値です。
     * {@primary The default number of objects to examine per run in the
     * idle object evictor.}
     * @see #getNumTestsPerEvictionRun
     * @see #setNumTestsPerEvictionRun
     * @see #getTimeBetweenEvictionRunsMillis
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;

    /**
     * {@link #getMinEvictableIdleTimeMillis} のデフォルト値です。
     * {@primary The default value for {@link #getMinEvictableIdleTimeMillis}.}
     * @see #getMinEvictableIdleTimeMillis
     * @see #setMinEvictableIdleTimeMillis
     */
    public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;

    //--- constructors -----------------------------------------------

    /**
     * 新たな <tt>GenericObjectPool</tt> を生成します。
     * {@primary Create a new <tt>GenericObjectPool</tt>.}
     */
    public GenericObjectPool() {
        this(null,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
    }

    /**
     * 指定された値を使用して新たな <tt>GenericObjectPool</tt> を生成します。
     * {@primary Create a new <tt>GenericObjectPool</tt> using the specified values.}
     * @param factory オブジェクトの生成、確認、破棄を行う際に使用される PoolableObjectFactory( <tt>null</tt> を許容します)
     * {@primary the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects}
     */
    public GenericObjectPool(PoolableObjectFactory factory) {
        this(factory,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
    }

    /**
     * 指定された値を使用して新たな <tt>GenericObjectPool</tt> を生成します。
     * {@primary Create a new <tt>GenericObjectPool</tt> using the specified values.}
     * @param factory オブジェクトの生成、確認、破棄を行う際に使用される PoolableObjectFactory( <tt>null</tt> を許容します)
     * {@primary the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects}
     * @param config 設定情報を定義する {@link GenericObjectPool.Config} ( <tt>null</tt> を許容しません)
     * {@primary a non-<tt>null</tt> {@link GenericObjectPool.Config} describing my configuration}
     */
    public GenericObjectPool(PoolableObjectFactory factory, GenericObjectPool.Config config) {
        this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.minIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle);
    }

    /**
     * 指定された値を使用して新たな <tt>GenericObjectPool</tt> を生成します。
     * {@primary Create a new <tt>GenericObjectPool</tt> using the specified values.}
     * @param factory オブジェクトの生成、確認、破棄を行う際に使用される PoolableObjectFactory( <tt>null</tt> を許容します)
     * {@primary the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects}
     * @param maxActive 同時にプールから取り出すことのできるオブジェクトの最大数({@link #setMaxActive} を参照)
     * {@primary the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})}
     */
    public GenericObjectPool(PoolableObjectFactory factory, int maxActive) {
        this(factory,maxActive,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
    }

    /**
     * 指定された値を使用して新たな <tt>GenericObjectPool</tt> を生成します。
     * {@primary Create a new <tt>GenericObjectPool</tt> using the specified values.}
     * @param factory オブジェクトの生成、確認、破棄を行う際に使用される PoolableObjectFactory( <tt>null</tt> を許容します)
     * {@primary the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects}
     * @param maxActive 同時にプールから取り出すことのできるオブジェクトの最大数({@link #setMaxActive} を参照)
     * {@primary the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})}
     * @param whenExhaustedAction プールが使い尽されている場合の処理 ({@link #getWhenExhaustedAction} を参照)
     * {@primary the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})}
     * @param maxWait プールが使い尽されていて <i>whenExhaustedAction</i> が {@link #WHEN_EXHAUSTED_BLOCK} の場合(それ以外の場合、無視されます)の最長待機時間 ({@link #getMaxWait} を参照)
     * {@primary the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})}
     */
    public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
        this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,DEFAULT_MIN_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
    }

    /**
     * 指定された値を使用して新たな <tt>GenericObjectPool</tt> を生成します。
     * {@primary Create a new <tt>GenericObjectPool</tt> using the specified values.}
     * @param factory オブジェクトの生成、確認、破棄を行う際に使用される PoolableObjectFactory( <tt>null</tt> を許容します)
     * {@primary the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects}
     * @param maxActive 同時にプールから取り出すことのできるオブジェクトの最大数 ({@link #setMaxActive} を参照)
     * {@primary the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})}
     * @param whenExhaustedAction プールが使い尽されている場合の処理 ({@link #getWhenExhaustedAction} を参照)
     * {@primary the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})}
     * @param maxWait プールが使い尽されていて <i>whenExhaustedAction</i> が {@link #WHEN_EXHAUSTED_BLOCK} の場合(それ以外の場合、無視されます)の最長待機時間 ({@link #getMaxWait} を参照)
     * {@primary the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})}
     * @param testOnBorrow オブジェクトの状態を {@link #borrowObject} メソッドを使って取り出す前に確認するかどうか ({@link #getTestOnBorrow} を参照)
     * {@primary whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow})}
     * @param testOnReturn オブジェクトの状態を {@link #returnObject} メソッドを使って戻した後に確認するかどうか ({@link #getTestOnReturn} を参照)
     * {@primary whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn})}
     */
    public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
        this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,DEFAULT_MIN_IDLE,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
    }

    /**
     * 指定された値を使用して新たな <tt>GenericObjectPool</tt> を生成します。
     * {@primary Create a new <tt>GenericObjectPool</tt> using the specified values.}
     * @param factory オブジェクトの生成、確認、破棄を行う際に使用される PoolableObjectFactory( <tt>null</tt> を許容します)
     * {@primary the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects}
     * @param maxActive 同時にプールから取り出すことのできるオブジェクトの最大数({@link #setMaxActive} を参照)
     * {@primary the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})}
     * @param whenExhaustedAction プールが使い尽されている場合の処理 ({@link #getWhenExhaustedAction} を参照)
     * {@primary the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})}
     * @param maxWait プールが使い尽されていて <i>whenExhaustedAction</i> が {@link #WHEN_EXHAUSTED_BLOCK} の場合(それ以外の場合、無視されます)の最長待機時間 ({@link #getMaxWait} を参照)
     * {@primary the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})}
     * @param maxIdle プール内に保持できる未使用のオブジェクトの最大数 ({@link #getMaxIdle} を参照)
     * {@primary the maximum number of idle objects in my pool (see {@link #getMaxIdle})}
     */
    public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
        this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,DEFAULT_MIN_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
    }

    /**
     * 指定された値を使用して新たな <tt>GenericObjectPool</tt> を生成します。
     * {@primary Create a new <tt>GenericObjectPool</tt> using the specified values.}
     * @param factory オブジェクトの生成、確認、破棄を行う際に使用される PoolableObjectFactory( <tt>null</tt> を許容します)
     * {@primary the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects}
     * @param maxActive 同時にプールから取り出すことのできるオブジェクトの最大数({@link #setMaxActive} を参照)
     * {@primary the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})}
     * @param whenExhaustedAction プールが使い尽されている場合の処理 ({@link #getWhenExhaustedAction} を参照)
     * {@primary the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})}
     * @param maxWait プールが使い尽されていて <i>whenExhaustedAction</i> が {@link #WHEN_EXHAUSTED_BLOCK} の場合(それ以外の場合、無視されます)の最長待機時間 ({@link #getMaxWait} を参照)
     * {@primary the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})}
     * @param maxIdle プール内に保持できる未使用のオブジェクトの最大数 ({@link #getMaxIdle} を参照)
     * {@primary the maximum number of idle objects in my pool (see {@link #getMaxIdle})}
     * @param testOnBorrow オブジェクトの状態を {@link #borrowObject} メソッドを使って取り出す前に確認するかどうか ({@link #getTestOnBorrow} を参照)
     * {@primary whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow})}
     * @param testOnReturn オブジェクトの状態を {@link #returnObject} メソッドを使って戻した後に確認するかどうか ({@link #getTestOnReturn} を参照)
     * {@primary whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn})}
     */
    public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
        this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,DEFAULT_MIN_IDLE,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
    }

    /**
     * 指定された値を使用して新たな <tt>GenericObjectPool</tt> を生成します。
     * {@primary Create a new <tt>GenericObjectPool</tt> using the specified values.}
     * @param factory オブジェクトの生成、確認、破棄を行う際に使用される PoolableObjectFactory( <tt>null</tt> を許容します)
     * {@primary the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects}
     * @param maxActive 同時にプールから取り出すことのできるオブジェクトの最大数({@link #setMaxActive} を参照)
     * {@primary the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})}
     * @param whenExhaustedAction プールが使い尽されている場合の処理 ({@link #getWhenExhaustedAction} を参照)
     * {@primary the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})}
     * @param maxWait プールが使い尽されていて <i>whenExhaustedAction</i> が {@link #WHEN_EXHAUSTED_BLOCK} の場合(それ以外の場合、無視されます)の最長待機時間 ({@link #getMaxWait} を参照)
     * {@primary the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})}
     * @param maxIdle プール内に保持できる未使用のオブジェクトの最大数 ({@link #getMaxIdle} を参照)
     * {@primary the maximum number of idle objects in my pool (see {@link #getMaxIdle})}
     * @param testOnBorrow オブジェクトの状態を {@link #borrowObject} メソッドを使って取り出す前に確認するかどうか ({@link #getTestOnBorrow} を参照)
     * {@primary whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow})}
     * @param testOnReturn オブジェクトの状態を {@link #returnObject} メソッドを使って戻した後に確認するかどうか ({@link #getTestOnReturn} を参照)
     * {@primary whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn})}
     * @param timeBetweenEvictionRunsMillis 未使用オブジェクト排除処理が次の実行までの間スリープする時間(ミリセカンド) ({@link #setTimeBetweenEvictionRunsMillis} を参照)
     * {@primary the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})}
     * @param numTestsPerEvictionRun 1度のオブジェクト排除処理でチェックされるオブジェクトの数 ({@link #setNumTestsPerEvictionRun} を参照)
     * {@primary the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})}
     * @param minEvictableIdleTimeMillis オブジェクトがプール内に未使用状態でいられる時間の最小値(ミリセカンド) ({@link #setMinEvictableIdleTimeMillis} を参照)
     * {@primary the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})}
     * @param testWhileIdle 未使用状態のオブジェクトを未使用オブジェクト排除スレッドでチェックするかどうか ({@link #setTestWhileIdle} を参照)
     * {@primary whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})}
     */
    public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
        this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
    }

    /**
     * 指定された値を使用して新たな <tt>GenericObjectPool</tt> を生成します。
     * {@primary Create a new <tt>GenericObjectPool</tt> using the specified values.}
     * @param factory オブジェクトの生成、確認、破棄を行う際に使用される PoolableObjectFactory( <tt>null</tt> を許容します)
     * {@primary the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects}
     * @param maxActive 同時にプールから取り出すことのできるオブジェクトの最大数({@link #setMaxActive} を参照)
     * {@primary the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})}
     * @param whenExhaustedAction プールが使い尽されている場合の処理 ({@link #getWhenExhaustedAction} を参照)
     * {@primary the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})}
     * @param maxWait プールが使い尽されていて <i>whenExhaustedAction</i> が {@link #WHEN_EXHAUSTED_BLOCK} の場合(それ以外の場合、無視されます)の最長待機時間 ({@link #getMaxWait} を参照)
     * {@primary the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})}
     * @param maxIdle プール内に保持できる未使用のオブジェクトの最大数 ({@link #getMaxIdle} を参照)
     * {@primary the maximum number of idle objects in my pool (see {@link #getMaxIdle})}
     * @param minIdle プール内に保持される未使用のオブジェクトの最少数 ({@link #setMinIdle} を参照)
     * {@primary the minimum number of idle objects in my pool (see {@link #setMinIdle})}
     * @param testOnBorrow オブジェクトの状態を {@link #borrowObject} メソッドを使って取り出す前に確認するかどうか ({@link #getTestOnBorrow} を参照)
     * {@primary whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow})}
     * @param testOnReturn オブジェクトの状態を {@link #returnObject} メソッドを使って戻した後に確認するかどうか ({@link #getTestOnReturn} を参照)
     * {@primary whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn})}
     * @param timeBetweenEvictionRunsMillis 未使用オブジェクト排除処理が次の実行までの間スリープする時間(ミリセカンド) ({@link #setTimeBetweenEvictionRunsMillis} を参照)
     * {@primary the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})}
     * @param numTestsPerEvictionRun 1度のオブジェクト排除処理でチェックされるオブジェクトの数 ({@link #setNumTestsPerEvictionRun} を参照)
     * {@primary the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})}
     * @param minEvictableIdleTimeMillis オブジェクトがプール内に未使用状態でいられる時間の最小値(ミリセカンド) ({@link #setMinEvictableIdleTimeMillis} を参照)
     * {@primary the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})}
     * @param testWhileIdle 未使用状態のオブジェクトを未使用オブジェクト排除スレッドでチェックするかどうか ({@link #setTestWhileIdle} を参照)
     * {@primary whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})}
     */
    public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
        _factory = factory;
        _maxActive = maxActive;
        switch(whenExhaustedAction) {
            case WHEN_EXHAUSTED_BLOCK:
            case WHEN_EXHAUSTED_FAIL:
            case WHEN_EXHAUSTED_GROW:
                _whenExhaustedAction = whenExhaustedAction;
                break;
            default:
                throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
        }
        _maxWait = maxWait;
        _maxIdle = maxIdle;
        _minIdle = minIdle;
        _testOnBorrow = testOnBorrow;
        _testOnReturn = testOnReturn;
        _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
        _numTestsPerEvictionRun = numTestsPerEvictionRun;
        _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
        _testWhileIdle = testWhileIdle;

        _pool = new CursorableLinkedList();
        startEvictor(_timeBetweenEvictionRunsMillis);
    }

    //--- public methods ---------------------------------------------

    //--- configuration methods --------------------------------------

    /**
     * 同時にプールから取り出すことのできるオブジェクトの最大数を返します。
     * {@primary Returns the cap on the total number of active instances from my pool.}
     * @return 取り出すことのできるオブジェクトの最大数
     * {@primary the cap on the total number of active instances from my pool.}
     * @see #setMaxActive
     */
    public synchronized int getMaxActive() {
        return _maxActive;
    }

    /**
     * 同時にプールから取り出すことのできるオブジェクトの最大数を設定します。
     * {@primary Sets the cap on the total number of active instances from my pool.}
     * @param maxActive 取り出すことのできるオブジェクトの最大数、
     *                  インスタンスの数を制限しない場合にはマイナスの値を設定します
     * {@primary The cap on the total number of active instances from my pool.
     *           Use a negative value for an infinite number of instances.}
     * @see #getMaxActive
     */
    public synchronized void setMaxActive(int maxActive) {
        _maxActive = maxActive;
        notifyAll();
    }

    /**
     * プールが使い尽されている場合(取り出すことのできるオブジェクトが最大数に達した場合)に
     * {@link #borrowObject} メソッドが行う処理の種別を返します。
     * {@primary Returns the action to take when the {@link #borrowObject} method
     * is invoked when the pool is exhausted (the maximum number
     * of "active" objects has been reached).}
     *
     * @return {@link #WHEN_EXHAUSTED_BLOCK}、{@link #WHEN_EXHAUSTED_FAIL}、{@link #WHEN_EXHAUSTED_GROW} のうちののどれか
     * {@primary one of {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW}}
     * @see #setWhenExhaustedAction
     */
    public synchronized byte getWhenExhaustedAction() {
        return _whenExhaustedAction;
    }

    /**
     * プールが使い尽されている場合(取り出すことのできるオブジェクトが最大数に達した場合)に
     * {@link #borrowObject} メソッドが行う処理の種別を設定します。
     * {@primary Sets the action to take when the {@link #borrowObject} method
     * is invoked when the pool is exhausted (the maximum number
     * of "active" objects has been reached).}
     *
     * @param whenExhaustedAction 処理の種別、
     *        {@link #WHEN_EXHAUSTED_BLOCK}、{@link #WHEN_EXHAUSTED_FAIL}、
     *        {@link #WHEN_EXHAUSTED_GROW} のうちののどれかである必要があります
     * {@primary the action code, which must be one of
     *           {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL},
     *            or {@link #WHEN_EXHAUSTED_GROW}}
     * @see #getWhenExhaustedAction
     */
    public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) {
        switch(whenExhaustedAction) {
            case WHEN_EXHAUSTED_BLOCK:
            case WHEN_EXHAUSTED_FAIL:
            case WHEN_EXHAUSTED_GROW:
                _whenExhaustedAction = whenExhaustedAction;
                notifyAll();
                break;
            default:
                throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
        }
    }


    /**
     * プールが使い尽されていて {@link #getWhenExhaustedAction "使い尽された時の処理"} に
     * {@link #WHEN_EXHAUSTED_BLOCK} が設定されている場合の
     * {@link #borrowObject} メソッドが例外を投げるまでの最長待機時間(ミリセカンド)を返します。
     * 0より小さな値が設定された場合、{@link #borrowObject}
     * メソッドは無期限に待機します。
     * {@primary Returns the maximum amount of time (in milliseconds) the
     * {@link #borrowObject} method should block before throwing
     * an exception when the pool is exhausted and the
     * {@link #setWhenExhaustedAction "when exhausted" action} is
     * {@link #WHEN_EXHAUSTED_BLOCK}.}
     * 
     * When less than 0, the {@link #borrowObject} method
     * may block indefinitely.}
     *
     * @see #setMaxWait
     * @see #setWhenExhaustedAction
     * @see #WHEN_EXHAUSTED_BLOCK
     */
    public synchronized long getMaxWait() {
        return _maxWait;
    }

    /**
     * プールが使い尽されていて {@link #getWhenExhaustedAction "使い尽された時の処理"} に
     * {@link #WHEN_EXHAUSTED_BLOCK} が設定されている場合の
     * {@link #borrowObject} メソッドが例外を投げるまでの最長待機時間(ミリセカンド)を設定します。
     * 0より小さな値が設定された場合、{@link #borrowObject}
     * メソッドは無期限に待機します。
     * {@primary Sets the maximum amount of time (in milliseconds) the
     * {@link #borrowObject} method should block before throwing
     * an exception when the pool is exhausted and the
     * {@link #setWhenExhaustedAction "when exhausted" action} is
     * {@link #WHEN_EXHAUSTED_BLOCK}.}
     * 
     * When less than 0, the {@link #borrowObject} method
     * may block indefinitely.}
     *
     * @see #getMaxWait
     * @see #setWhenExhaustedAction
     * @see #WHEN_EXHAUSTED_BLOCK
     */
    public synchronized void setMaxWait(long maxWait) {
        _maxWait = maxWait;
        notifyAll();
    }

    /**
     * プール内に保持できる未使用のオブジェクトの最大数を返します。
     * {@primary Returns the cap on the number of "idle" instances in the pool.}
     * @return プール内に保持できる未使用のオブジェクトの最大数
     * {@primary the cap on the number of "idle" instances in the pool.}
     * @see #setMaxIdle
     */
    public synchronized int getMaxIdle() {
        return _maxIdle;
    }

    /**
     * プール内に保持できる未使用のオブジェクトの最大数を設定します。
     * {@primary Sets the cap on the number of "idle" instances in the pool.}
     * @param maxIdle プール内に保持できる未使用のオブジェクトの最大数
     *                マイナスの値が設定された場合には同時にプール内に保持できるオブジェクトを制限しません
     * {@primary The cap on the number of "idle" instances in the pool.
     *           Use a negative value to indicate an unlimited number
     *           of idle instances.}
     * @see #getMaxIdle
     */
    public synchronized void setMaxIdle(int maxIdle) {
        _maxIdle = maxIdle;
        notifyAll();
    }

    /**
     * プール内に保持される未使用のオブジェクトの最小数を設定します。
     * この値に達しない場合には排除処理スレッドにて新たなオブジェクトの生成を行います。
     * (注：numActive + numIdle >= maxActive となる場合にはオブジェクトの生成は行われません)
     * {@primary Sets the minimum number of objects allowed in the pool
     * before the evictor thread (if active) spawns new objects.
     * (Note no objects are created when: numActive + numIdle >= maxActive)}
     * 
     * @param minIdle オブジェクトの最小数
     * {@primary The minimum number of objects. }
     * @see #getMinIdle
     */
    public synchronized void setMinIdle(int minIdle) {
        _minIdle = minIdle;
        notifyAll();
    }

    /**
     * プール内に保持される未使用のオブジェクトの最小数を返します。
     * この値に達しない場合には排除処理スレッドにて新たなオブジェクトの生成を行います。
     * (Note no objects are created when: numActive + numIdle >= maxActive)
     * {@primary Returns the minimum number of objects allowed in the pool
     * before the evictor thread (if active) spawns new objects.
     * (Note no objects are created when: numActive + numIdle >= maxActive)}
     *
     * @return オブジェクトの最小数
     * {@primary The minimum number of objects.}
     * @see #setMinIdle
     */
    public synchronized int getMinIdle() {
        return _minIdle;
    }

    /**
     * この値が <tt>true</tt> の場合
     * インスタンスが {@link #borrowObject} メソッドにて取り出される前に
     * {@link PoolableObjectFactory#validateObject 有効かどうかの確認} を行います。
     * 有効でないと判断された場合、オブジェクトはプールから破棄され、他のオブジェクトが取り出されます。
     * {@primary When <tt>true</tt>, objects will be
     * {@link PoolableObjectFactory#validateObject validated}
     * before being returned by the {@link #borrowObject}
     * method.  If the object fails to validate,
     * it will be dropped from the pool, and we will attempt
     * to borrow another.}
     *
     * @see #setTestOnBorrow
     */
    public synchronized boolean getTestOnBorrow() {
        return _testOnBorrow;
    }

    /**
     * この値が <tt>true</tt> の場合
     * オブジェクトが {@link #borrowObject} メソッドにて取り出される前に
     * {@link PoolableObjectFactory#validateObject 有効かどうかの確認} を行います。
     * 有効でないと判断された場合、オブジェクトはプールから破棄され、他のオブジェクトが取り出されます。
     * {@primary When <tt>true</tt>, objects will be
     * {@link PoolableObjectFactory#validateObject validated}
     * before being returned by the {@link #borrowObject}
     * method.  If the object fails to validate,
     * it will be dropped from the pool, and we will attempt
     * to borrow another.}
     *
     * @see #getTestOnBorrow
     */
    public synchronized void setTestOnBorrow(boolean testOnBorrow) {
        _testOnBorrow = testOnBorrow;
    }

    /**
     * この値が <tt>true</tt> の場合
     * オブジェクトが {@link #returnObject} メソッドにて戻される前に
     * {@link PoolableObjectFactory#validateObject 有効かどうかの確認} を行います。
     * {@primary When <tt>true</tt>, objects will be
     * {@link PoolableObjectFactory#validateObject validated}
     * before being returned to the pool within the
     * {@link #returnObject}.}
     *
     * @see #setTestOnReturn
     */
    public synchronized boolean getTestOnReturn() {
        return _testOnReturn;
    }

    /**
     * この値が <tt>true</tt> の場合
     * オブジェクトが {@link #returnObject} メソッドにて戻される前に
     * {@link PoolableObjectFactory#validateObject 有効かどうかの確認} を行います。
     * {@primary When <tt>true</tt>, objects will be
     * {@link PoolableObjectFactory#validateObject validated}
     * before being returned to the pool within the
     * {@link #returnObject}.}
     *
     * @see #getTestOnReturn
     */
    public synchronized void setTestOnReturn(boolean testOnReturn) {
        _testOnReturn = testOnReturn;
    }

    /**
     * 未使用オブジェクト排除処理が次の実行までの間スリープする時間(ミリセカンド)を返します。
     * マイナスの値が設定された場合、排除スレッドは起動しません。
     * {@primary Returns the number of milliseconds to sleep between runs of the
     * idle object evictor thread.
     * When non-positive, no idle object evictor thread will be
     * run.}
     *
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public synchronized long getTimeBetweenEvictionRunsMillis() {
        return _timeBetweenEvictionRunsMillis;
    }

    /**
     * 未使用オブジェクト排除処理が次の実行までの間スリープする時間(ミリセカンド)を設定します。
     * マイナスの値が設定された場合、排除スレッドは起動しません。
     * {@primary Sets the number of milliseconds to sleep between runs of the
     * idle object evictor thread.
     * When non-positive, no idle object evictor thread will be
     * run.}
     *
     * @see #getTimeBetweenEvictionRunsMillis
     */
    public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
        _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
        startEvictor(_timeBetweenEvictionRunsMillis);
    }

    /**
     * 1度のオブジェクト排除処理で排除スレッドにチェックされるオブジェクトの数を返します。
     * {@primary Returns the number of objects to examine during each run of the
     * idle object evictor thread (if any).}
     *
     * @see #setNumTestsPerEvictionRun
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public synchronized int getNumTestsPerEvictionRun() {
        return _numTestsPerEvictionRun;
    }

    /**
     * 1度のオブジェクト排除処理で排除スレッドにチェックされるオブジェクトの数を返します。
     * {@primary Sets the number of objects to examine during each run of the
     * idle object evictor thread (if any).}
     * <p>
     * マイナスの値が設定された場合、<tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
     * 回のチェックを実施します。  例えば <i>-n</i> が設定された場合には、1/<i>n</i>
     * の未使用オブジェクトが1度のオブジェクト排除処理でチェックされます。
     * {@primary When a negative value is supplied, <tt>ceil({@link #numIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
     * tests will be run.  I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
     * idle objects will be tested per run.}
     *
     * @see #getNumTestsPerEvictionRun
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
        _numTestsPerEvictionRun = numTestsPerEvictionRun;
    }

    /**
     * オブジェクトがプール内に未使用状態でいられる時間の最小値を返します。
     * 未使用状態でいる時間がこの値に達すると排除処理の対象となります。
     * {@primary Returns the minimum amount of time an object may sit idle in the pool
     * before it is eligable for eviction by the idle object evictor
     * (if any).}
     *
     * @see #setMinEvictableIdleTimeMillis
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public synchronized long getMinEvictableIdleTimeMillis() {
        return _minEvictableIdleTimeMillis;
    }

    /**
     * オブジェクトがプール内に未使用状態でいられる時間の最小値を設定します。
     * 未使用状態でいる時間がこの値に達すると排除処理の対象となります。
     * マイナスの値が設定された場合、未使用状態でいる時間が原因ではオブジェクトの削除は行われません。
     * {@primary Sets the minimum amount of time an object may sit idle in the pool
     * before it is eligable for eviction by the idle object evictor
     * (if any).
     * When non-positive, no objects will be evicted from the pool
     * due to idle time alone.}
     *
     * @see #getMinEvictableIdleTimeMillis
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
        _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
    }

    /**
     * この値が <tt>true</tt> の場合
     * オブジェクト排除処理によってオブジェクトに対する
     * {@link PoolableObjectFactory#validateObject 有効かどうかの確認} が実施されます。
     * 有効でないと判断されたオブジェクトはプールから破棄されます。
     * {@primary When <tt>true</tt>, objects will be
     * {@link PoolableObjectFactory#validateObject validated}
     * by the idle object evictor (if any).  If an object
     * fails to validate, it will be dropped from the pool.}
     *
     * @see #setTestWhileIdle
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public synchronized boolean getTestWhileIdle() {
        return _testWhileIdle;
    }

    /**
     * この値が <tt>true</tt> の場合
     * オブジェクト排除処理によってオブジェクトに対する
     * {@link PoolableObjectFactory#validateObject 有効かどうかの確認} が実施されます。
     * 有効でないと判断されたオブジェクトはプールから破棄されます。
     * {@primary When <tt>true</tt>, objects will be
     * {@link PoolableObjectFactory#validateObject validated}
     * by the idle object evictor (if any).  If an object
     * fails to validate, it will be dropped from the pool.}
     *
     * @see #getTestWhileIdle
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public synchronized void setTestWhileIdle(boolean testWhileIdle) {
        _testWhileIdle = testWhileIdle;
    }

    /**
     * 設定情報を登録します。
     * {@primary Sets my configuration.}
     * @see GenericObjectPool.Config
     */
    public synchronized void setConfig(GenericObjectPool.Config conf) {
        setMaxIdle(conf.maxIdle);
        setMinIdle(conf.minIdle);
        setMaxActive(conf.maxActive);
        setMaxWait(conf.maxWait);
        setWhenExhaustedAction(conf.whenExhaustedAction);
        setTestOnBorrow(conf.testOnBorrow);
        setTestOnReturn(conf.testOnReturn);
        setTestWhileIdle(conf.testWhileIdle);
        setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
        setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
        setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
        notifyAll();
    }

    //-- ObjectPool methods ------------------------------------------

    public Object borrowObject() throws Exception {
        long starttime = System.currentTimeMillis();
        boolean newlyCreated = false;
        for(;;) {
            ObjectTimestampPair pair = null;

            synchronized(this) {
                assertOpen();

                // if there are any sleeping, just grab one of those
                try {
                    pair = (ObjectTimestampPair)(_pool.removeFirst());
                } catch(NoSuchElementException e) {
                    ; /* ignored */
                }

                // otherwise
                if(null == pair) {
                    // check if we can create one
                    // (note we know that the num sleeping is 0, else we wouldn't be here)
                    if(_maxActive <= 0 || _numActive < _maxActive) {
                        // allow new object to be created
                    } else {
                        // the pool is exhausted
                        switch(_whenExhaustedAction) {
                            case WHEN_EXHAUSTED_GROW:
                                // allow new object to be created
                                break;
                            case WHEN_EXHAUSTED_FAIL:
                                throw new NoSuchElementException();
                            case WHEN_EXHAUSTED_BLOCK:
                                    try {
                                        if(_maxWait <= 0) {
                                            wait();
                                        } else {
                                            wait(_maxWait);
                                        }
                                    } catch(InterruptedException e) {
                                        // ignored
                                    }
                                    if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
                                        throw new NoSuchElementException("Timeout waiting for idle object");
                                    } else {
                                        continue; // keep looping
                                    }
                            default:
                                throw new IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not recognized.");
                        }
                    }
                }
                _numActive++;
            } // end synchronized
            
            // create new object when needed
            if(null == pair) {
                try {
                    Object obj = _factory.makeObject();
                    pair = new ObjectTimestampPair(obj);
                    newlyCreated = true;
                }
                catch (Exception e) {
                    // object cannot be created
                    synchronized(this) {
                        _numActive--;
                        notifyAll();
                    }
                    throw e;
                }
            }

            // activate & validate the object
            try {
                _factory.activateObject(pair.value);
                if(_testOnBorrow && !_factory.validateObject(pair.value)) {
                    throw new Exception("validateObject failed");
                }                
                return pair.value;
            } 
            catch (Exception e) {
                // object cannot be activated or is invalid
                synchronized(this) {
                    _numActive--;
                    notifyAll();
                }
                try {
                    _factory.destroyObject(pair.value);
                } 
                catch (Exception e2) {
                    // cannot destroy broken object 
                }
                if(newlyCreated) {
                    throw new NoSuchElementException("Could not create a validated object");
                } 
                else {
                    continue; // keep looping
                }
            }
        }
    }

    public void invalidateObject(Object obj) throws Exception {
        assertOpen();
        try {
            _factory.destroyObject(obj);
        }
        finally {
            synchronized(this) {
                _numActive--;
                notifyAll(); // _numActive has changed
            }
        }
    }

    public synchronized void clear() {
        assertOpen();
        for(Iterator it = _pool.iterator(); it.hasNext(); ) {
            try {
                _factory.destroyObject(((ObjectTimestampPair)(it.next())).value);
            } catch(Exception e) {
                // ignore error, keep destroying the rest
            }
            it.remove();
        }
        _pool.clear();
        notifyAll(); // num sleeping has changed
    }

    public synchronized int getNumActive() {
        assertOpen();
        return _numActive;
    }

    public synchronized int getNumIdle() {
        assertOpen();
        return _pool.size();
    }

    public void returnObject(Object obj) throws Exception {
        assertOpen();
        boolean success = true;
        if(_testOnReturn && !(_factory.validateObject(obj))) {
            success = false;
        } else {
            try {
                _factory.passivateObject(obj);
            } catch(Exception e) {
                success = false;
            }
        }

        boolean shouldDestroy = !success;

        synchronized(this) {
            _numActive--;
            if((_maxIdle >= 0) && (_pool.size() >= _maxIdle)) {
                shouldDestroy = true;
            } else if(success) {
                _pool.addFirst(new ObjectTimestampPair(obj));
            }
            notifyAll(); // _numActive has changed
        }

        if(shouldDestroy) {
            try {
                _factory.destroyObject(obj);
            } catch(Exception e) {
                // ignored
            }
        }
    }

    public synchronized void close() throws Exception {
        clear();
        _pool = null;
        _factory = null;
        if(null != _evictionCursor) {
            _evictionCursor.close();
            _evictionCursor = null;
        }
        startEvictor(-1L);
        super.close();
    }

    public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
        assertOpen();
        if(0 < getNumActive()) {
            throw new IllegalStateException("Objects are already active");
        } else {
            clear();
            _factory = factory;
        }
    }

    public synchronized void evict() throws Exception {
        assertOpen();
        if(!_pool.isEmpty()) {
            if(null == _evictionCursor) {
                _evictionCursor = (_pool.cursor(_pool.size()));
            } else if(!_evictionCursor.hasPrevious()) {
                _evictionCursor.close();
                _evictionCursor = (_pool.cursor(_pool.size()));
            }
            for(int i=0,m=getNumTests();i<m;i++) {
                if(!_evictionCursor.hasPrevious()) {
                    _evictionCursor.close();
                    _evictionCursor = (_pool.cursor(_pool.size()));
                } else {
                    boolean removeObject = false;
                    ObjectTimestampPair pair = (ObjectTimestampPair)(_evictionCursor.previous());
                    if(_minEvictableIdleTimeMillis > 0 &&
                       System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) {
                       removeObject = true;
                    } else if(_testWhileIdle) {
                        boolean active = false;
                        try {
                            _factory.activateObject(pair.value);
                            active = true;
                        } catch(Exception e) {
                            removeObject=true;
                        }
                        if(active) {
                            if(!_factory.validateObject(pair.value)) {
                                removeObject=true;
                            } else {
                                try {
                                    _factory.passivateObject(pair.value);
                                } catch(Exception e) {
                                    removeObject=true;
                                }
                            }
                        }
                    }
                    if(removeObject) {
                        try {
                            _evictionCursor.remove();
                            _factory.destroyObject(pair.value);
                        } catch(Exception e) {
                            ; // ignored
                        }
                    }
                }
            }
        } // if !empty
    }
    
    /**
     * Check to see if we are below our minimum number of objects
     * if so enough to bring us back to our minimum.
     */
    private void ensureMinIdle() throws Exception {
        // this method isn't synchronized so the
        // calculateDeficit is done at the beginning
        // as a loop limit and a second time inside the loop
        // to stop when another thread already returned the
        // needed objects
        int objectDeficit = calculateDeficit();
        for ( int j = 0 ; j < objectDeficit && calculateDeficit() > 0 ; j++ ) {
            addObject();
        }
    }

    private synchronized int calculateDeficit() {
        int objectDeficit = getMinIdle() - getNumIdle();
        if (_maxActive > 0) {
            int growLimit = Math.max(0, getMaxActive() - getNumActive() - getNumIdle());
            objectDeficit = Math.min(objectDeficit, growLimit);
        }
        return objectDeficit;
    } 

    /**
     * Create an object, and place it into the pool.
     * addObject() is useful for "pre-loading" a pool with idle objects.
     */
    public void addObject() throws Exception {
        Object obj = _factory.makeObject();
        synchronized(this) {
            _numActive++;   // A little slimy - must do this because returnObject decrements it.
            this.returnObject(obj);
        }
    }
    
    //--- non-public methods ----------------------------------------

    /**
     * Start the eviction thread or service, or when
     * <i>delay</i> is non-positive, stop it
     * if it is already running.
     */
    protected synchronized void startEvictor(long delay) {
        if(null != _evictor) {
            _evictor.cancel();
            _evictor = null;
        }
        if(delay > 0) {
            _evictor = new Evictor(delay);
            Thread t = new Thread(_evictor);
            t.setDaemon(true);
            t.start();
        }
    }

    synchronized String debugInfo() {
        StringBuffer buf = new StringBuffer();
        buf.append("Active: ").append(getNumActive()).append("\n");
        buf.append("Idle: ").append(getNumIdle()).append("\n");
        buf.append("Idle Objects:\n");
        Iterator it = _pool.iterator();
        long time = System.currentTimeMillis();
        while(it.hasNext()) {
            ObjectTimestampPair pair = (ObjectTimestampPair)(it.next());
            buf.append("\t").append(pair.value).append("\t").append(time - pair.tstamp).append("\n");
        }
        return buf.toString();
    }

    private int getNumTests() {
        if(_numTestsPerEvictionRun >= 0) {
            return _numTestsPerEvictionRun;
        } else {
            return(int)(Math.ceil((double)_pool.size()/Math.abs((double)_numTestsPerEvictionRun)));
        }
    }

    //--- inner classes ----------------------------------------------

    /**
     * A simple "struct" encapsulating an object instance and a timestamp.
     */
    class ObjectTimestampPair {
        Object value;
        long tstamp;

        ObjectTimestampPair(Object val) {
            this(val,System.currentTimeMillis());
        }

        ObjectTimestampPair(Object val, long time) {
            value = val;
            tstamp = time;
        }
    }

    /**
     * The idle object evictor thread.
     * @see #setTimeBetweenEvictionRunsMillis
     */
    class Evictor implements Runnable {
        private boolean _cancelled = false;
        private long _delay = 0L;

        public Evictor(long delay) {
            _delay = delay;
        }

        void cancel() {
            _cancelled = true;
        }

        public void run() {
            while(!_cancelled) {
                try {
                    Thread.sleep(_delay);
                } catch(Exception e) {
                    // ignored
                }
                try {
                    evict();
                } catch(Exception e) {
                    // ignored
                }
                try {
                    ensureMinIdle();
                } catch(Exception e) {
                    // ignored
                }
            }
            synchronized(GenericObjectPool.this) {
                if(null != _evictionCursor) {
                    _evictionCursor.close();
                    _evictionCursor = null;
                }
            }
        }

    }

    /**
     * {@link GenericObjectPool} のための設定情報を格納したシンプルな "構造体(のようなもの)" です。
     * {@primary A simple "struct" encapsulating the
     * configuration information for a {@link GenericObjectPool}.}
     * @see GenericObjectPool#GenericObjectPool(org.apache.commons.pool.PoolableObjectFactory,org.apache.commons.pool.impl.GenericObjectPool.Config)
     * @see GenericObjectPool#setConfig
     */
    public static class Config {
        public int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
        public int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;
        public int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
        public long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
        public byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
        public boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;
        public boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;
        public boolean testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;
        public long timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
        public int numTestsPerEvictionRun =  GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
        public long minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
    }

    //--- private attributes ---------------------------------------

    /**
     * The cap on the number of idle instances in the pool.
     * @see #setMaxIdle
     * @see #getMaxIdle
     */
    private int _maxIdle = DEFAULT_MAX_IDLE;

    /**
    * The cap on the minimum number of idle instances in the pool.
    * @see #setMinIdle
    * @see #getMinIdle
    */
   private int _minIdle = DEFAULT_MIN_IDLE;

    /**
     * The cap on the total number of active instances from the pool.
     * @see #setMaxActive
     * @see #getMaxActive
     */
    private int _maxActive = DEFAULT_MAX_ACTIVE;

    /**
     * The maximum amount of time (in millis) the
     * {@link #borrowObject} method should block before throwing
     * an exception when the pool is exhausted and the
     * {@link #getWhenExhaustedAction "when exhausted" action} is
     * {@link #WHEN_EXHAUSTED_BLOCK}.
     *
     * When less than 0, the {@link #borrowObject} method
     * may block indefinitely.
     *
     * @see #setMaxWait
     * @see #getMaxWait
     * @see #WHEN_EXHAUSTED_BLOCK
     * @see #setWhenExhaustedAction
     * @see #getWhenExhaustedAction
     */
    private long _maxWait = DEFAULT_MAX_WAIT;

    /**
     * The action to take when the {@link #borrowObject} method
     * is invoked when the pool is exhausted (the maximum number
     * of "active" objects has been reached).
     *
     * @see #WHEN_EXHAUSTED_BLOCK
     * @see #WHEN_EXHAUSTED_FAIL
     * @see #WHEN_EXHAUSTED_GROW
     * @see #DEFAULT_WHEN_EXHAUSTED_ACTION
     * @see #setWhenExhaustedAction
     * @see #getWhenExhaustedAction
     */
    private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION;

    /**
     * When <tt>true</tt>, objects will be
     * {@link PoolableObjectFactory#validateObject validated}
     * before being returned by the {@link #borrowObject}
     * method.  If the object fails to validate,
     * it will be dropped from the pool, and we will attempt
     * to borrow another.
     *
     * @see #setTestOnBorrow
     * @see #getTestOnBorrow
     */
    private boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW;

    /**
     * When <tt>true</tt>, objects will be
     * {@link PoolableObjectFactory#validateObject validated}
     * before being returned to the pool within the
     * {@link #returnObject}.
     *
     * @see #getTestOnReturn
     * @see #setTestOnReturn
     */
    private boolean _testOnReturn = DEFAULT_TEST_ON_RETURN;

    /**
     * When <tt>true</tt>, objects will be
     * {@link PoolableObjectFactory#validateObject validated}
     * by the idle object evictor (if any).  If an object
     * fails to validate, it will be dropped from the pool.
     *
     * @see #setTestWhileIdle
     * @see #getTestWhileIdle
     * @see #getTimeBetweenEvictionRunsMillis
     * @see #setTimeBetweenEvictionRunsMillis
     */
    private boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE;

    /**
     * The number of milliseconds to sleep between runs of the
     * idle object evictor thread.
     * When non-positive, no idle object evictor thread will be
     * run.
     *
     * @see #setTimeBetweenEvictionRunsMillis
     * @see #getTimeBetweenEvictionRunsMillis
     */
    private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;

    /**
     * The number of objects to examine during each run of the
     * idle object evictor thread (if any).
     * <p>
     * When a negative value is supplied, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
     * tests will be run.  I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
     * idle objects will be tested per run.
     *
     * @see #setNumTestsPerEvictionRun
     * @see #getNumTestsPerEvictionRun
     * @see #getTimeBetweenEvictionRunsMillis
     * @see #setTimeBetweenEvictionRunsMillis
     */
    private int _numTestsPerEvictionRun =  DEFAULT_NUM_TESTS_PER_EVICTION_RUN;

    /**
     * The minimum amount of time an object may sit idle in the pool
     * before it is eligable for eviction by the idle object evictor
     * (if any).
     * When non-positive, no objects will be evicted from the pool
     * due to idle time alone.
     *
     * @see #setMinEvictableIdleTimeMillis
     * @see #getMinEvictableIdleTimeMillis
     * @see #getTimeBetweenEvictionRunsMillis
     * @see #setTimeBetweenEvictionRunsMillis
     */
    private long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;

    /** My pool. */
    private CursorableLinkedList _pool = null;

    /** My {@link PoolableObjectFactory}. */
    private PoolableObjectFactory _factory = null;

    /**
     * The number of objects {@link #borrowObject} borrowed
     * from the pool, but not yet returned.
     */
    private int _numActive = 0;

    /**
     * My idle object eviction thread, if any.
     */
    private Evictor _evictor = null;

    private CursorableLinkedList.Cursor _evictionCursor = null;
}

