/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.dbcp.datasources;

import java.io.Serializable;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.NoSuchElementException;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.naming.Referenceable;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import javax.sql.PooledConnection;

import org.apache.commons.dbcp.SQLNestedException;
import org.apache.commons.pool.impl.GenericObjectPool;

/**
 * <p>The base class for <code>SharedPoolDataSource</code> and 
 * <code>PerUserPoolDataSource</code>.  Many of the configuration properties
 * are shared and defined here.  This class is declared public in order
 * to allow particular usage with commons-beanutils; do not make direct
 * use of it outside of commons-dbcp.
 * </p>
 *
 * <p>
 * A J2EE container will normally provide some method of initializing the
 * <code>DataSource</code> whose attributes are presented
 * as bean getters/setters and then deploying it via JNDI.  It is then
 * available to an application as a source of pooled logical connections to 
 * the database.  The pool needs a source of physical connections.  This
 * source is in the form of a <code>ConnectionPoolDataSource</code> that
 * can be specified via the {@link #setDataSourceName(String)} used to
 * lookup the source via JNDI.
 * </p>
 *
 * <p>
 * Although normally used within a JNDI environment, A DataSource
 * can be instantiated and initialized as any bean.  In this case the 
 * <code>ConnectionPoolDataSource</code> will likely be instantiated in
 * a similar manner.  This class allows the physical source of connections
 * to be attached directly to this pool using the 
 * {@link #setConnectionPoolDataSource(ConnectionPoolDataSource)} method.
 * </p>
 *
 * <p>
 * The dbcp package contains an adapter, 
 * {@link org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS},
 * that can be used to allow the use of <code>DataSource</code>'s based on this
 * class with jdbc driver implementations that do not supply a 
 * <code>ConnectionPoolDataSource</code>, but still
 * provide a {@link java.sql.Driver} implementation.
 * </p>
 *
 * <p>
 * The <a href="package-summary.html">package documentation</a> contains an 
 * example using catalina and JNDI and it also contains a non-JNDI example. 
 * </p>
 *
 * @author John D. McNally
 * @version $Revision$ $Date$
 */
public abstract class InstanceKeyDataSource
        implements DataSource, Referenceable, Serializable {
    private static final long serialVersionUID = -4243533936955098795L;
    private static final String GET_CONNECTION_CALLED 
            = "A Connection was already requested from this source, " 
            + "further initialization is not allowed.";
    private static final String BAD_TRANSACTION_ISOLATION
        = "The requested TransactionIsolation level is invalid.";
    /**
    * Internal constant to indicate the level is not set. 
    */
    protected static final int UNKNOWN_TRANSACTIONISOLATION = -1;

    private boolean getConnectionCalled = false;

    private ConnectionPoolDataSource cpds = null;
    /** DataSource Name used to find the ConnectionPoolDataSource */
    private String dataSourceName = null;
    private boolean defaultAutoCommit = false;
    private int defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION;
//    private int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
//    private int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
//    private int maxWait = (int)Math.min(Integer.MAX_VALUE,
//        GenericObjectPool.DEFAULT_MAX_WAIT);
    private boolean defaultReadOnly = false;
    /** Description */
    private String description = null;
    /** Environment that may be used to set up a jndi initial context. */
    Properties jndiEnvironment = null;
    /** Login TimeOut in seconds */
    private int loginTimeout = 0;
    /** Log stream */
    private PrintWriter logWriter = null;
    private boolean _testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;
    private boolean _testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;
    private int _timeBetweenEvictionRunsMillis = (int)
        Math.min(Integer.MAX_VALUE,
                 GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
    private int _numTestsPerEvictionRun = 
        GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
    private int _minEvictableIdleTimeMillis = (int)
    Math.min(Integer.MAX_VALUE,
             GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
    private boolean _testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;
    private String validationQuery = null;
    private boolean rollbackAfterValidation = false;
    private boolean testPositionSet = false;

    protected String instanceKey = null;

    /**
     * Default no-arg constructor for Serialization
     */
    public InstanceKeyDataSource() {
        defaultAutoCommit = true;
    }

    /**
     * Throws an IllegalStateException, if a PooledConnection has already
     * been requested.
     */
    protected void assertInitializationAllowed()
        throws IllegalStateException {
        if (getConnectionCalled) {
            throw new IllegalStateException(GET_CONNECTION_CALLED);
        }
    }

    /**
     * Close pool being maintained by this datasource.
     */
    public abstract void close() throws Exception;

    /*
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    public <T> T unwrap(Class<T> iface) throws SQLException {
        throw new SQLException("InstanceKeyDataSource is not a wrapper.");
    }
    */

    // -------------------------------------------------------------------
    // Properties

    /**
     * Get the value of connectionPoolDataSource.  This method will return
     * null, if the backing datasource is being accessed via jndi.
     *
     * @return value of connectionPoolDataSource.
     */
    public ConnectionPoolDataSource getConnectionPoolDataSource() {
        return cpds;
    }
    
    /**
     * Set the backend ConnectionPoolDataSource.  This property should not be
     * set if using jndi to access the datasource.
     *
     * @param v  Value to assign to connectionPoolDataSource.
     */
    public void setConnectionPoolDataSource(ConnectionPoolDataSource v) {
        assertInitializationAllowed();
        if (dataSourceName != null) {
            throw new IllegalStateException(
                "Cannot set the DataSource, if JNDI is used.");
        }
        if (cpds != null) 
        {
            throw new IllegalStateException(
                "The CPDS has already been set. It cannot be altered.");
        }
        cpds = v;
        instanceKey = InstanceKeyObjectFactory.registerNewInstance(this);
    }

    /**
     * Get the name of the ConnectionPoolDataSource which backs this pool.
     * This name is used to look up the datasource from a jndi service 
     * provider.
     *
     * @return value of dataSourceName.
     */
    public String getDataSourceName() {
        return dataSourceName;
    }
    
    /**
     * Set the name of the ConnectionPoolDataSource which backs this pool.
     * This name is used to look up the datasource from a jndi service 
     * provider.
     *
     * @param v  Value to assign to dataSourceName.
     */
    public void setDataSourceName(String v) {
        assertInitializationAllowed();
        if (cpds != null) {
            throw new IllegalStateException(
                "Cannot set the JNDI name for the DataSource, if already " +
                "set using setConnectionPoolDataSource.");
        }
        if (dataSourceName != null) 
        {
            throw new IllegalStateException(
                "The DataSourceName has already been set. " + 
                "It cannot be altered.");
        }
        this.dataSourceName = v;
        instanceKey = InstanceKeyObjectFactory.registerNewInstance(this);
    }

    /** 
     * Get the value of defaultAutoCommit, which defines the state of 
     * connections handed out from this pool.  The value can be changed
     * on the Connection using Connection.setAutoCommit(boolean).
     * The default is true.
     *
     * @return value of defaultAutoCommit.
     */
    public boolean isDefaultAutoCommit() {
        return defaultAutoCommit;
    }
    
    /**
     * Set the value of defaultAutoCommit, which defines the state of 
     * connections handed out from this pool.  The value can be changed
     * on the Connection using Connection.setAutoCommit(boolean).
     * The default is true.
     *
     * @param v  Value to assign to defaultAutoCommit.
     */
    public void setDefaultAutoCommit(boolean v) {
        assertInitializationAllowed();
        this.defaultAutoCommit = v;
    }

    /**
     * Get the value of defaultReadOnly, which defines the state of 
     * connections handed out from this pool.  The value can be changed
     * on the Connection using Connection.setReadOnly(boolean).
     * The default is false.
     *
     * @return value of defaultReadOnly.
     */
    public boolean isDefaultReadOnly() {
        return defaultReadOnly;
    }
    
    /**
     * Set the value of defaultReadOnly, which defines the state of 
     * connections handed out from this pool.  The value can be changed
     * on the Connection using Connection.setReadOnly(boolean).
     * The default is false.
     *
     * @param v  Value to assign to defaultReadOnly.
     */
    public void setDefaultReadOnly(boolean v) {
        assertInitializationAllowed();
        this.defaultReadOnly = v;
    }

    /**
     * Get the value of defaultTransactionIsolation, which defines the state of
     * connections handed out from this pool.  The value can be changed
     * on the Connection using Connection.setTransactionIsolation(int).
     * If this method returns -1, the default is JDBC driver dependent.
     * 
     * @return value of defaultTransactionIsolation.
     */
    public int getDefaultTransactionIsolation() {
            return defaultTransactionIsolation;
    }

    /**
     * Set the value of defaultTransactionIsolation, which defines the state of
     * connections handed out from this pool.  The value can be changed
     * on the Connection using Connection.setTransactionIsolation(int).
     * The default is JDBC driver dependent.
     * 
     * @param v  Value to assign to defaultTransactionIsolation
     */
    public void setDefaultTransactionIsolation(int v) {
        assertInitializationAllowed();
        switch (v) {
        case Connection.TRANSACTION_NONE:
        case Connection.TRANSACTION_READ_COMMITTED:
        case Connection.TRANSACTION_READ_UNCOMMITTED:
        case Connection.TRANSACTION_REPEATABLE_READ:
        case Connection.TRANSACTION_SERIALIZABLE:
            break;
        default:
            throw new IllegalArgumentException(BAD_TRANSACTION_ISOLATION);
        }
        this.defaultTransactionIsolation = v;
    }
    
    /**
     * Get the description.  This property is defined by jdbc as for use with
     * GUI (or other) tools that might deploy the datasource.  It serves no
     * internal purpose.
     *
     * @return value of description.
     */
    public String getDescription() {
        return description;
    }
    
    /**
     * Set the description.  This property is defined by jdbc as for use with
     * GUI (or other) tools that might deploy the datasource.  It serves no
     * internal purpose.
     * 
     * @param v  Value to assign to description.
     */
    public void setDescription(String v) {
        this.description = v;
    }
        
    /**
     * Get the value of jndiEnvironment which is used when instantiating
     * a jndi InitialContext.  This InitialContext is used to locate the
     * backend ConnectionPoolDataSource.
     *
     * @return value of jndiEnvironment.
     */
    public String getJndiEnvironment(String key) {
        String value = null;
        if (jndiEnvironment != null) {
            value = jndiEnvironment.getProperty(key);
        }
        return value;
    }
    
    /**
     * Sets the value of the given JNDI environment property to be used when
     * instantiating a JNDI InitialContext. This InitialContext is used to
     * locate the backend ConnectionPoolDataSource.
     * 
     * @param key the JNDI environment property to set.
     * @param value the value assigned to specified JNDI environment property.
     */
    public void setJndiEnvironment(String key, String value) {
        if (jndiEnvironment == null) {
            jndiEnvironment = new Properties();
        }
        jndiEnvironment.setProperty(key, value);
    }
    
    /**
     * Get the value of loginTimeout.
     * @return value of loginTimeout.
     */
    public int getLoginTimeout() {
        return loginTimeout;
    }
    
    /**
     * Set the value of loginTimeout.
     * @param v  Value to assign to loginTimeout.
     */
    public void setLoginTimeout(int v) {
        this.loginTimeout = v;
    }
        
    /**
     * Get the value of logWriter.
     * @return value of logWriter.
     */
    public PrintWriter getLogWriter() {
        if (logWriter == null) {
            logWriter = new PrintWriter(System.out);
        }        
        return logWriter;
    }
    
    /**
     * Set the value of logWriter.
     * @param v  Value to assign to logWriter.
     */
    public void setLogWriter(PrintWriter v) {
        this.logWriter = v;
    }
    
    /**
     * @see #getTestOnBorrow
     */
    public final boolean isTestOnBorrow() {
        return getTestOnBorrow();
    }
    
    /**
     * 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 boolean getTestOnBorrow() {
        return _testOnBorrow;
    }

    /**
     * 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. For a <code>true</code> value to have any effect,
     * the <code>validationQuery</code> property must be set to a non-null
     * string.
     *
     * @see #getTestOnBorrow
     */
    public void setTestOnBorrow(boolean testOnBorrow) {
        assertInitializationAllowed();
        _testOnBorrow = testOnBorrow;
        testPositionSet = true;
    }

    /**
     * @see #getTestOnReturn
     */
    public final boolean isTestOnReturn() {
        return getTestOnReturn();
    }
    
    /**
     * When <tt>true</tt>, objects will be
     * {*link PoolableObjectFactory#validateObject validated}
     * before being returned to the pool within the
     * {*link #returnObject}.
     *
     * @see #setTestOnReturn
     */
    public boolean getTestOnReturn() {
        return _testOnReturn;
    }

    /**
     * When <tt>true</tt>, objects will be
     * {*link PoolableObjectFactory#validateObject validated}
     * before being returned to the pool within the
     * {*link #returnObject}. For a <code>true</code> value to have any effect,
     * the <code>validationQuery</code> property must be set to a non-null
     * string.
     *
     * @see #getTestOnReturn
     */
    public void setTestOnReturn(boolean testOnReturn) {
        assertInitializationAllowed();
        _testOnReturn = testOnReturn;
        testPositionSet = true;
    }

    /**
     * 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 int getTimeBetweenEvictionRunsMillis() {
        return _timeBetweenEvictionRunsMillis;
    }

    /**
     * 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 void 
        setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
        assertInitializationAllowed();
            _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
    }

    /**
     * Returns the number of objects to examine during each run of the
     * idle object evictor thread (if any).
     *
     * @see #setNumTestsPerEvictionRun
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public int getNumTestsPerEvictionRun() {
        return _numTestsPerEvictionRun;
    }

    /**
     * Sets 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 #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 void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
        assertInitializationAllowed();
        _numTestsPerEvictionRun = numTestsPerEvictionRun;
    }

    /**
     * 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 int getMinEvictableIdleTimeMillis() {
        return _minEvictableIdleTimeMillis;
    }

    /**
     * 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 void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
        assertInitializationAllowed();
        _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
    }

    /**
     * @see #getTestWhileIdle
     */
    public final boolean isTestWhileIdle() {
        return getTestWhileIdle();
    }
    
    /**
     * 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 boolean getTestWhileIdle() {
        return _testWhileIdle;
    }

    /**
     * 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. For a
     * <code>true</code> value to have any effect,
     * the <code>validationQuery</code> property must be set to a non-null
     * string.
     *
     * @see #getTestWhileIdle
     * @see #setTimeBetweenEvictionRunsMillis
     */
    public void setTestWhileIdle(boolean testWhileIdle) {
        assertInitializationAllowed();
        _testWhileIdle = testWhileIdle;
        testPositionSet = true;
    }

    /**
     * The SQL query that will be used to validate connections from this pool
     * before returning them to the caller.  If specified, this query
     * <strong>MUST</strong> be an SQL SELECT statement that returns at least
     * one row.
     */
    public String getValidationQuery() {
        return (this.validationQuery);
    }

    /**
     * The SQL query that will be used to validate connections from this pool
     * before returning them to the caller.  If specified, this query
     * <strong>MUST</strong> be an SQL SELECT statement that returns at least
     * one row.  Default behavior is to test the connection when it is
     * borrowed.
     */
    public void setValidationQuery(String validationQuery) {
        assertInitializationAllowed();
        this.validationQuery = validationQuery;
        if (!testPositionSet) {
            setTestOnBorrow(true);
        }
    }

    /**
     * Whether a rollback will be issued after executing the SQL query 
     * that will be used to validate connections from this pool
     * before returning them to the caller.
     * 
     * @return true if a rollback will be issued after executing the
     * validation query
     * @since 1.2.2
     */
    public boolean isRollbackAfterValidation() {
        return (this.rollbackAfterValidation);
    }

    /**
     * Whether a rollback will be issued after executing the SQL query 
     * that will be used to validate connections from this pool
     * before returning them to the caller. Default behavior is NOT
     * to issue a rollback. The setting will only have an effect
     * if a validation query is set
     * 
     * @param rollbackAfterValidation new property value
     * @since 1.2.2
     */
    public void setRollbackAfterValidation(boolean rollbackAfterValidation) {
        assertInitializationAllowed();
        this.rollbackAfterValidation = rollbackAfterValidation;
    }

    // ----------------------------------------------------------------------
    // Instrumentation Methods

    // ----------------------------------------------------------------------
    // DataSource implementation 

    /**
     * Attempt to establish a database connection.
     */
    public Connection getConnection() throws SQLException {
        return getConnection(null, null);
    }

    /**
     * Attempt to establish a database connection.
     */
    public Connection getConnection(String username, String password)
            throws SQLException {        
        if (instanceKey == null) {
            throw new SQLException("Must set the ConnectionPoolDataSource " 
                    + "through setDataSourceName or setConnectionPoolDataSource"
                    + " before calling getConnection.");
        }
        getConnectionCalled = true;
        PooledConnectionAndInfo info = null;
        try {
            info = getPooledConnectionAndInfo(username, password);
        } catch (NoSuchElementException e) {
            closeDueToException(info);
            throw new SQLNestedException("Cannot borrow connection from pool", e);
        } catch (RuntimeException e) {
            closeDueToException(info);
            throw e;
        } catch (SQLException e) {            
            closeDueToException(info);
            throw e;
        } catch (Exception e) {
            closeDueToException(info);
            throw new SQLNestedException("Cannot borrow connection from pool", e);
        }
        
        if (!(null == password ? null == info.getPassword() 
                : password.equals(info.getPassword()))) {
            closeDueToException(info);
            throw new SQLException("Given password did not match password used"
                                   + " to create the PooledConnection.");
        }

        Connection con = info.getPooledConnection().getConnection();
        try { 
            setupDefaults(con, username);
            con.clearWarnings();
            return con;
        } catch (SQLException ex) {  
            try {
                con.close();
            } catch (Exception exc) { 
                getLogWriter().println(
                     "ignoring exception during close: " + exc);
            }
            throw ex;
        }
    }

    protected abstract PooledConnectionAndInfo 
        getPooledConnectionAndInfo(String username, String password)
        throws SQLException;

    protected abstract void setupDefaults(Connection con, String username) 
        throws SQLException;

        
    private void closeDueToException(PooledConnectionAndInfo info) {
        if (info != null) {
            try {
                info.getPooledConnection().getConnection().close();
            } catch (Exception e) {
                // do not throw this exception because we are in the middle
                // of handling another exception.  But record it because
                // it potentially leaks connections from the pool.
                getLogWriter().println("[ERROR] Could not return connection to "
                    + "pool during exception handling. " + e.getMessage());   
            }
        }
    }

    protected ConnectionPoolDataSource 
        testCPDS(String username, String password)
        throws javax.naming.NamingException, SQLException {
        // The source of physical db connections
        ConnectionPoolDataSource cpds = this.cpds;
        if (cpds == null) {            
            Context ctx = null;
            if (jndiEnvironment == null) {
                ctx = new InitialContext();                
            } else {
                ctx = new InitialContext(jndiEnvironment);
            }
            Object ds = ctx.lookup(dataSourceName);
            if (ds instanceof ConnectionPoolDataSource) {
                cpds = (ConnectionPoolDataSource) ds;
            } else {
                throw new SQLException("Illegal configuration: "
                    + "DataSource " + dataSourceName
                    + " (" + ds.getClass().getName() + ")"
                    + " doesn't implement javax.sql.ConnectionPoolDataSource");
            }
        }
        
        // try to get a connection with the supplied username/password
        PooledConnection conn = null;
        try {
            if (username != null) {
                conn = cpds.getPooledConnection(username, password);
            }
            else {
                conn = cpds.getPooledConnection();
            }
            if (conn == null) {
                throw new SQLException(
                    "Cannot connect using the supplied username/password");
            }
        }
        finally {
            if (conn != null) {
                try {
                    conn.close();
                }
                catch (SQLException e) {
                    // at least we could connect
                }
            }
        }
        return cpds;
    }

    protected byte whenExhaustedAction(int maxActive, int maxWait) {
        byte whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;
        if (maxActive <= 0) {
            whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_GROW;
        } else if (maxWait == 0) {
            whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_FAIL;
        }
        return whenExhausted;
    }    

    // ----------------------------------------------------------------------
    // Referenceable implementation 

    /**
     * Retrieves the Reference of this object.
     * <strong>Note:</strong> <code>InstanceKeyDataSource</code> subclasses
     * should override this method. The implementaion included below
     * is not robust and will be removed at the next major version DBCP
     * release.
     *
     * @return The non-null Reference of this object.
     * @exception NamingException If a naming exception was encountered
     *      while retrieving the reference.
     */
    // TODO: Remove the implementation of this method at next major
    // version release.
    
    public Reference getReference() throws NamingException {
        final String className = getClass().getName();
        final String factoryName = className + "Factory"; // XXX: not robust 
        Reference ref = new Reference(className, factoryName, null);
        ref.add(new StringRefAddr("instanceKey", instanceKey));
        return ref;
    }
}
