Package org.apache.commons.dbcp

Source Code of org.apache.commons.dbcp.BasicDataSource

/** $Header: /home/cvspublic/jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/BasicDataSource.java,v 1.11 2002/07/21 00:38:35 craigmcc Exp $
* $Revision: 1.11 $
* $Date: 2002/07/21 00:38:35 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 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 acknowlegement:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowlegement may appear in the software itself,
*    if and wherever such third-party acknowlegements 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 Group.
*
* 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.dbcp;

import java.io.PrintWriter;
import java.util.Properties;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.DriverConnectionFactory;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;


/**
* <p>Basic implementation of <code>javax.sql.DataSource</code> that is
* configured via JavaBeans properties.  This is not the only way to
* combine the <em>commons-dbcp</em> and <em>commons-pool</em> packages,
* but provides a "one stop shopping" solution for basic requirements.</p>
*
* @author Glenn L. Nielsen
* @author Craig R. McClanahan
* @version $Revision: 1.11 $ $Date: 2002/07/21 00:38:35 $
*/

public class BasicDataSource implements DataSource {


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


    /**
     * The default auto-commit state of connections created by this pool.
     */
    protected boolean defaultAutoCommit = true;

    public boolean getDefaultAutoCommit() {
        return (this.defaultAutoCommit);
    }

    public void setDefaultAutoCommit(boolean defaultAutoCommit) {
        this.defaultAutoCommit = defaultAutoCommit;
    }


    /**
     * The default read-only state of connections created by this pool.
     */
    protected boolean defaultReadOnly = false;

    public boolean getDefaultReadOnly() {
        return (this.defaultReadOnly);
    }

    public void setDefaultReadOnly(boolean defaultReadOnly) {
        this.defaultReadOnly = defaultReadOnly;
    }


    /**
     * The fully qualified Java class name of the JDBC driver to be used.
     */
    protected String driverClassName = null;

    public String getDriverClassName() {
        return (this.driverClassName);
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }


    /**
     * The maximum number of active connections that can be allocated from
     * this pool at the same time, or zero for no limit.
     */
    protected int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;

    public int getMaxActive() {
        return (this.maxActive);
    }

    public void setMaxActive(int maxActive) {
        this.maxActive = maxActive;
    }


    /**
     * The maximum number of active connections that can remain idle in the
     * pool, without extra ones being released, or zero for no limit.
     */
    protected int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;;

    public int getMaxIdle() {
        return (this.maxIdle);
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }


    /**
     * The maximum number of milliseconds that the pool will wait (when there
     * are no available connections) for a connection to be returned before
     * throwing an exception, or -1 to wait indefinitely.
     */
    protected long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;

    public long getMaxWait() {
        return (this.maxWait);
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }



    /**
     * [Read Only] The current number of active connections that have been
     * allocated from this data source.
     */
    public int getNumActive() {
        if (connectionPool != null) {
            return (connectionPool.getNumActive());
        } else {
            return (0);
        }
    }


    /**
     * [Read Only] The current number of idle connections that are waiting
     * to be allocated from this data source.
     */
    public int getNumIdle() {
        if (connectionPool != null) {
            return (connectionPool.getNumIdle());
        } else {
            return (0);
        }
    }


    /**
     * The connection password to be passed to our JDBC driver to establish
     * a connection.
     */
    protected String password = null;

    public String getPassword() {
        return (this.password);
    }

    public void setPassword(String password) {
        this.password = password;
    }


    /**
     * The connection URL to be passed to our JDBC driver to establish
     * a connection.
     */
    protected String url = null;

    public String getUrl() {
        return (this.url);
    }

    public void setUrl(String url) {
        this.url = url;
    }


    /**
     * The connection username to be passed to our JDBC driver to
     * establish a connection.
     */
    protected String username = null;

    public String getUsername() {
        return (this.username);
    }

    public void setUsername(String username) {
        this.username = username;
    }


    /**
     * 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.
     */
    protected String validationQuery = null;

    public String getValidationQuery() {
        return (this.validationQuery);
    }

    public void setValidationQuery(String validationQuery) {
        this.validationQuery = validationQuery;
    }


    // ----------------------------------------------------- Instance Variables


    /**
     * The object pool that internally manages our connections.
     */
    protected GenericObjectPool connectionPool = null;


    /**
     * The connection properties that will be sent to our JDBC driver when
     * establishing new connections.  <strong>NOTE</strong> - The "user" and
     * "password" properties will be passed explicitly, so they do not need
     * to be included here.
     */
    protected Properties connectionProperties = new Properties();


    /**
     * The data source we will use to manage connections.  This object should
     * be acquired <strong>ONLY</strong> by calls to the
     * <code>createDataSource()</code> method.
     */
    protected DataSource dataSource = null;


    /**
     * The PrintWriter to which log messages should be directed.
     */
    protected PrintWriter logWriter = new PrintWriter(System.out);


    // ----------------------------------------------------- DataSource Methods


    /**
     * Create (if necessary) and return a connection to the database.
     *
     * @exception SQLException if a database access error occurs
     */
    public Connection getConnection() throws SQLException {

        return (createDataSource().getConnection());

    }


    /**
     * Create (if necessary) and return a connection to the database.
     *
     * @param username Database user on whose behalf the Connection
     *   is being made
     * @param password The database user's password
     *
     * @exception SQLException if a database access error occurs
     */
    public Connection getConnection(String username, String password)
        throws SQLException {

        return (createDataSource().getConnection(username, password));

    }


    /**
     * Return the login timeout (in seconds) for connecting to the database.
     *
     * @exception SQLException if a database access error occurs
     */
    public int getLoginTimeout() throws SQLException {

        return (createDataSource().getLoginTimeout());

    }


    /**
     * Return the log writer being used by this data source.
     *
     * @exception SQLException if a database access error occurs
     */
    public PrintWriter getLogWriter() throws SQLException {

        return (createDataSource().getLogWriter());

    }


    /**
     * Set the login timeout (in seconds) for connecting to the database.
     *
     * @param loginTimeout The new login timeout, or zero for no timeout
     *
     * @exception SQLException if a database access error occurs
     */
    public void setLoginTimeout(int loginTimeout) throws SQLException {

        createDataSource().setLoginTimeout(loginTimeout);

    }


    /**
     * Set the log writer being used by this data source.
     *
     * @param logWriter The new log writer
     *
     * @exception SQLException if a database access error occurs
     */
    public void setLogWriter(PrintWriter logWriter) throws SQLException {

        createDataSource().setLogWriter(logWriter);
        this.logWriter = logWriter;

    }

    private AbandonedConfig abandonedConfig;

    /**                      
     * Flag to remove abandoned connections if they exceed the
     * removeAbandonedTimout.
     *
     * Set to true or false, default false.
     * If set to true a connection is considered abandoned and eligible
     * for removal if it has been idle longer than the removeAbandonedTimeout.
     * Setting this to true can recover db connections from poorly written   
     * applications which fail to close a connection.                        
     */                                                                  
    public boolean getRemoveAbandoned() {  
        if (abandonedConfig != null) {
            return abandonedConfig.getRemoveAbandoned();
        }
        return false;
    }                                   
                                     
    public void setRemoveAbandoned(boolean removeAbandoned) {
        if (abandonedConfig == null) {
            abandonedConfig = new AbandonedConfig();
        }
        abandonedConfig.setRemoveAbandoned(removeAbandoned);
    }                                                       
                                              
    /**
     * Timeout in seconds before an abandoned connection can be removed.
     *
     * Defaults to 300 seconds.                                        
     */                                                                
    public int getRemoveAbandonedTimeout() {
        if (abandonedConfig != null) {
            return abandonedConfig.getRemoveAbandonedTimeout();
        }
        return 300;
    }                                       
                                            
    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
        if (abandonedConfig == null) {
            abandonedConfig = new AbandonedConfig();
        }
        abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout);
    }                                                                 
                                                            
    /**
     * Flag to log stack traces for application code which abandoned
     * a Statement or Connection.
     *
     * Defaults to false.               
     *                                                             
     * Logging of abandoned Statements and Connections adds overhead
     * for every Connection open or new Statement because a stack  
     * trace has to be generated.                                  
     */                                                         
    public boolean getLogAbandoned() {  
        if (abandonedConfig != null) {
            return abandonedConfig.getLogAbandoned();
        }
        return false;
    }                                
                                  
    public void setLogAbandoned(boolean logAbandoned) {
        if (abandonedConfig == null) {
            abandonedConfig = new AbandonedConfig();
        }
        abandonedConfig.setLogAbandoned(logAbandoned);
    }


    // --------------------------------------------------------- Public Methods


    /**
     * Add a custom connection property to the set that will be passed to our
     * JDBC driver.    This <strong>MUST</strong> be called before the first
     * connection is retrieved (along with all the other configuration
     * property setters).
     *
     * @param name Name of the custom connection property
     * @param value Value of the custom connection property
     */
    public void addConnectionProperty(String name, String value) {

        connectionProperties.put(name, value);

    }


    /**
     * Close and release all connections that are currently stored in the
     * connection pool associated with our data source.
     *
     * @exception SQLException if a database error occurs
     */
    public void close() throws SQLException {
        GenericObjectPool oldpool = connectionPool;
        connectionPool = null;
        dataSource = null;
        try {
            oldpool.close();
        } catch(SQLException e) {
            throw e;
        } catch(RuntimeException e) {
            throw e;
        } catch(Exception e) {
            throw new SQLException(e.toString());
        }
    }


    // ------------------------------------------------------ Protected Methods


    /**
     * <p>Create (if necessary) and return the internal data source we are
     * using to manage our connections.</p>
     *
     * <p><strong>IMPLEMENTATION NOTE</strong> - It is tempting to use the
     * "double checked locking" idiom in an attempt to avoid synchronizing
     * on every single call to this method.  However, this idiom fails to
     * work correctly in the face of some optimizations that are legal for
     * a JVM to perform.</p>
     *
     * @exception SQLException if the object pool cannot be created.
     */
    protected synchronized DataSource createDataSource()
        throws SQLException {

        // Return the pool if we have already created it
        if (dataSource != null) {
            return (dataSource);
        }

        // Load the JDBC driver class
        Class driverClass = null;
        try {
            driverClass = Class.forName(driverClassName);
        } catch (Throwable t) {
            String message = "Cannot load JDBC driver class '" +
                driverClassName + "'";
            logWriter.println(message);
            t.printStackTrace(logWriter);
            throw new SQLException(message);
        }

        // Create a JDBC driver instance
        Driver driver = null;
        try {
            driver = DriverManager.getDriver(url);
        } catch (Throwable t) {
            String message = "Cannot create JDBC driver of class '" +
                driverClassName + "' for connect URL '" + url + "'";
            logWriter.println(message);
            t.printStackTrace(logWriter);
            throw new SQLException(message);
        }

        // Create an object pool to contain our active connections
        connectionPool = new AbandonedObjectPool(null,abandonedConfig);
        connectionPool.setMaxActive(maxActive);
        connectionPool.setMaxIdle(maxIdle);
        connectionPool.setMaxWait(maxWait);
        if (validationQuery != null) {
            connectionPool.setTestOnBorrow(true);
        }

        // Set up the driver connection factory we will use
        if (username != null) {
            connectionProperties.put("user", username);
        } else {
            System.out.println(
                "DBCP DataSource configured without a 'username'");
        }
        if (password != null) {
            connectionProperties.put("password", password);
        } else {
            System.out.println(
                "DBCP DataSource configured without a 'password'");
        }
        DriverConnectionFactory driverConnectionFactory =
            new DriverConnectionFactory(driver, url, connectionProperties);

        // Set up the poolable connection factory we will use
        PoolableConnectionFactory connectionFactory = null;
        try {
            connectionFactory =
                new PoolableConnectionFactory(driverConnectionFactory,
                                              connectionPool,
                                              null, // FIXME - stmtPoolFactory?
                                              validationQuery,
                                              defaultReadOnly,
                                              defaultAutoCommit,
                                              abandonedConfig);
        } catch(RuntimeException e) {
            throw e;
        } catch(Exception e) {
            throw new SQLException(e.toString());
        }

        // Create and return the pooling data source to manage the connections
        dataSource = new PoolingDataSource(connectionPool);
        dataSource.setLogWriter(logWriter);
        return (dataSource);

    }


}
TOP

Related Classes of org.apache.commons.dbcp.BasicDataSource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.