uk.ac.sanger.cgp.dbcon.core.AbstractDbConDataSource.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.sanger.cgp.dbcon.core.AbstractDbConDataSource.java

Source

/*
##########################################################################
#                          COPYRIGHT NOTICE                              #
##########################################################################
#                                                                        #
# Copyright (c) 2006 Genome Research Ltd.                                #
# Author: The Cancer Genome Project IT group cancerit@sanger.ac.uk       #
#                                                                        #
# THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       #
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     #
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. #
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   #
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   #
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      #
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 #
#                                                                        #
# This code is free software; you can redistribute it and/or modify it   #
# under the terms of the BSD License.                                    #
#                                                                        #
# Any redistribution or derivation in whole or in part including any     #
# substantial portion of this code must include this copyright and       #
# permission notice.                                                     #
#                                                                        #
##########################################################################
*/

package uk.ac.sanger.cgp.dbcon.core;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import uk.ac.sanger.cgp.dbcon.exceptions.DbConException;
import uk.ac.sanger.cgp.dbcon.pooling.Pool;
import uk.ac.sanger.cgp.dbcon.pooling.PooledDataSource;
import uk.ac.sanger.cgp.dbcon.util.DatabaseUtils;

/**
 * <p>
 * Used as a default implementation of the data source object which uses the
 * AbstractPools objects to retrieve pools and their connections from the given
 * synonym specified through construction.
 *
 * <p>
 * This is a thin wrapper around the DBCP DataSource object which is linked to
 * the shared connection pool. Be aware that <strong>ALL</strong> Connections
 * retrived from this object <strong>MUST</strong> be closed otherwise you will
 * have impacts on other systems with locking out connections and causing the pool
 * to be filled.
 *
 * @author andrewyates
 * @author $Author$
 * @version $Revision$
 * @see <a href="http://jakarta.apache.org/commons/dbcp/apidocs/org/apache/commons/dbcp/package-summary.html">DBCP DataSources</a>
 */
public abstract class AbstractDbConDataSource implements DataSource {

    private Log log = LogFactory.getLog(this.getClass());

    private final String name;

    /**
     * Creates a new instance of PooledDataSource
     */
    public AbstractDbConDataSource(String name) {
        super();
        this.name = name;
    }

    protected Log getLog() {
        return log;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) {
        return getClass().isAssignableFrom(iface);
    }

    @Override
    public <T> T unwrap(Class<T> iface) {
        return (T) this;
    }

    /**
     * Throws UnsupportedOperationException.
     */
    public void setLoginTimeout(int seconds) throws SQLException {
        getDataSource().setLoginTimeout(seconds);
    }

    /**
     * Wrapper around the underlying DataSource's method
     */
    public void setLogWriter(PrintWriter out) throws SQLException {
        getDataSource().setLogWriter(out);
    }

    /**
     * Runs a basic toString
     */
    public String toString() {
        String retValue;
        retValue = super.toString();
        retValue = retValue + "DB Name: " + getName();
        return retValue;
    }

    /**
     * Throws UnsupportedOperationException.
     */
    public int getLoginTimeout() throws SQLException {
        return getDataSource().getLoginTimeout();
    }

    /**
     * Wrapper around the underlying DataSource's method
     */
    public PrintWriter getLogWriter() throws SQLException {
        return getDataSource().getLogWriter();
    }

    /**
     * Gets a connection from the underling DataSource, using a given username and
     * password. Applies the settings specified by
     * {@link DatabaseUtils#connectionSettings(Connection)} Throws
     * UnsupportedOperationException.
     */
    public Connection getConnection(String username, String password) throws SQLException {
        Connection conn = getDataSource().getConnection(username, password);
        DatabaseUtils.connectionSettings(conn);
        return conn;
    }

    /**
     * Gets a connection from the underling DataSource using the username and
     * password specified at creation. Applies the settings specified by
     * {@link DatabaseUtils#connectionSettings(Connection)}
     */
    public Connection getConnection() throws SQLException {
        Connection conn = getDataSource().getConnection();
        DatabaseUtils.connectionSettings(conn);
        return conn;
    }

    /**
     * Returns true if the synonym/name used to create this class with has
     * resulted in a Pool being created.
     */
    public boolean isSynonymFound() throws SQLException {
        return getBackingAbstractPoolsInstance().isSynonymKnown(name);
    }

    /**
     * Wrapper to extract the DataSource for the specified named pool. This
     * happens every single time to maintain updates with the potentially ever
     * changing
     *
     */
    protected DataSource getDataSource() throws SQLException {
        return getUnderlyingPool().getDataSource();
    }

    /**
     * Used to provide the backing instance method which links pooling provided by
     * the AbstractPools classes to this datasource
     */
    protected abstract AbstractPools getBackingAbstractPoolsInstance();

    /**
     * Finds the pool which is represented by the synonym given by this Object
     *
     * @throws SQLException
     *           If any DbConException is detected. This is logged here and
     *           re-thrown with information but no nesting since SQLException does
     *           not support this
     */
    protected Pool getUnderlyingPool() throws SQLException {
        try {
            return getBackingAbstractPoolsInstance().getPool(getName());
        } catch (DbConException e) {
            if (getLog().isErrorEnabled()) {
                getLog().error("Could not get pool for " + getName(), e);
            }
            throw new SQLException(
                    "Detected DbCon exception whilst " + "trying to retriving underlying pool for " + getName());
        }
    }

    /**
     * Indicates the synonym used to connect to the specified pool
     */
    public String getName() {
        return name;
    }

    /**
     * Tests if the submitted DataSource is a PooledDataSource and if it is backed
     * by the same Pool. This is enough to test equality as we hold only one
     * instance underlying the pools here so two hashcodes from the same synonym
     * should be equal.
     */
    public boolean equals(Object obj) {
        boolean equality = false;

        if (this.getClass().isInstance(obj)) {
            PooledDataSource pds = (PooledDataSource) obj;
            try {
                equality = pds.getUnderlyingPool().equals(this.getUnderlyingPool());
            } catch (SQLException e) {
                if (getLog().isErrorEnabled())
                    getLog().error("Could not compare pools together. Equality is false", e);
            }
        }

        return equality;
    }

    /**
     * This is taken as being the underlying Pool's hashcode. This is enough to
     * get the hashcode as we hold only one instance underlying the pools here so
     * two hashcodes from the same synonym should be equal.
     */
    public int hashCode() {

        int hashCodeReturn = 0;

        try {
            hashCodeReturn = this.getUnderlyingPool().hashCode();
        } catch (SQLException e) {
            if (getLog().isErrorEnabled())
                getLog().error("Could not retrieve underlying pool for hashcode. Hashcode is 0", e);
        }

        return hashCodeReturn;
    }

}