org.seasar.dbflute.helper.jdbc.connection.DfDataSourceHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.seasar.dbflute.helper.jdbc.connection.DfDataSourceHandler.java

Source

/*
 * Copyright 2004-2011 the Seasar Foundation and the Others.
 *
 * Licensed 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.seasar.dbflute.helper.jdbc.connection;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.seasar.dbflute.exception.DfJDBCException;
import org.seasar.dbflute.helper.jdbc.context.DfDataSourceContext;

public class DfDataSourceHandler implements DfConnectionProvider {

    // ===================================================================================
    //                                                                          Definition
    //                                                                          ==========
    /** Log instance. */
    private static Log _log = LogFactory.getLog(DfDataSourceHandler.class);

    // ===================================================================================
    //                                                                           Attribute
    //                                                                           =========
    /** DB driver. */
    protected String _driver;

    /** DB URL. */
    protected String _url;

    /** User name. */
    protected String _user;

    /** Password */
    protected String _password;

    /** Connection properties. */
    protected Properties _connectionProperties;

    /** Is the mode auto commit? */
    protected boolean _autoCommit;

    /** Cached connection object. */
    protected Connection _cachedConnection;

    /** The meta information of connected database. (lazy load) */
    protected DfConnectionMetaInfo _connectionMetaInfo;

    /** Has a connection meta already been set up? (related to connectionMetaInfo) */
    protected boolean _alreadySetupMeta;

    // ===================================================================================
    //                                                                              Create
    //                                                                              ======
    public void create() throws SQLException {
        if (!DfDataSourceContext.isExistDataSource()) {
            _log.info("...Creating data source:");
            _log.info("  driver = " + _driver);
            _log.info("  url    = " + _url);
            _log.info("  user   = " + _user);
            DfDataSourceContext.setDataSource(new DfSimpleDataSource(this));
        }
    }

    public void commit() throws SQLException {
        Connection conn = null;
        try {
            conn = getCachedConnection();
            if (conn == null) {
                return; // if no cache, do nothing
            }
            if (!conn.getAutoCommit()) {
                _log.info("...commit()");
                conn.commit();
            }
        } catch (SQLException e) {
            String msg = "Failed to commit the conection: conn=" + conn;
            throw new DfJDBCException(msg, e);
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException ignored) {
                }
            }
        }
    }

    public void destroy() throws SQLException {
        try {
            final Connection conn = getCachedConnection();
            if (conn == null) {
                return; // if no cache, do nothing
            }
            if (!conn.getAutoCommit()) {
                _log.info("...rollback()");
                conn.rollback();
            }
            if (conn instanceof DfSimpleConnection) {
                _log.info("...closeReally()");
                ((DfSimpleConnection) conn).closeReally();
            } else {
                _log.info("...close()");
                conn.close();
            }
        } catch (SQLException ignored) {
        } finally {
            if (DfDataSourceContext.isExistDataSource()) {
                DfDataSourceContext.clearDataSource();
            }
        }
    }

    // ===================================================================================
    //                                                             Provider Implementation
    //                                                             =======================
    public Connection getConnection() throws SQLException {
        return processCachedConnection();
    }

    public Connection getCachedConnection() {
        return _cachedConnection;
    }

    protected Connection processCachedConnection() throws SQLException {
        if (_cachedConnection != null) {
            return _cachedConnection;
        }
        final Connection conn = createConnection();
        _cachedConnection = new DfSimpleConnection(conn);
        processConnectionMetaInfo(conn);
        return _cachedConnection;
    }

    protected Connection createConnection() throws SQLException {
        Connection conn = null;
        final Driver driverInstance = newDriver();
        final Properties info = new Properties();
        if (_connectionProperties != null && !_connectionProperties.isEmpty()) {
            info.putAll(_connectionProperties);
        }
        if (_user == null) {
            String msg = "The database user should not be null.";
            throw new IllegalStateException(msg);
        }
        info.put("user", _user);
        if (_password == null) {
            String msg = "The database password should not be null (but empty allowed).";
            throw new IllegalStateException(msg);
        }
        info.put("password", _password);

        try {
            _log.info("...Connecting to the database:");
            conn = driverInstance.connect(_url, info);
        } catch (SQLException e) {
            String msg = "Failed to connect:";
            msg = msg + " url=" + _url + " user=" + _user;
            throw new DfJDBCException(msg, e);
        }
        if (conn == null) {
            String msg = "The driver didn't understand the URL: " + _url;
            throw new DfJDBCException(msg);
        }
        try {
            conn.setAutoCommit(_autoCommit);
        } catch (SQLException e) {
            String msg = "Failed to set auto commit:";
            msg = msg + " autocommit=" + _autoCommit;
            throw new DfJDBCException(msg, e);
        }
        return conn;
    }

    protected Driver newDriver() {
        final String driver = _driver;
        final Driver driverInstance;
        try {
            final Class<?> dc = Class.forName(driver);
            driverInstance = (Driver) dc.newInstance();
        } catch (ClassNotFoundException e) {
            String msg = "Class Not Found: JDBC driver " + driver + " could not be loaded.";
            throw new IllegalStateException(msg, e);
        } catch (IllegalAccessException e) {
            String msg = "Illegal Access: JDBC driver " + driver + " could not be loaded.";
            throw new IllegalStateException(msg, e);
        } catch (InstantiationException e) {
            String msg = "Instantiation Exception: JDBC driver " + driver + " could not be loaded.";
            throw new IllegalStateException(msg, e);
        }
        return driverInstance;
    }

    protected void processConnectionMetaInfo(Connection conn) throws SQLException {
        if (_alreadySetupMeta) {
            return;
        }
        try {
            final DfConnectionMetaInfo metaInfo = new DfConnectionMetaInfo();
            final DatabaseMetaData metaData = conn.getMetaData();
            metaInfo.setProductName(metaData.getDatabaseProductName());
            metaInfo.setProductVersion(metaData.getDatabaseProductVersion());
            metaInfo.setDriverName(metaData.getDriverName());
            metaInfo.setDriverVersion(metaData.getDriverVersion());
            final int majorVersion = metaData.getJDBCMajorVersion();
            final int minorVersion = metaData.getJDBCMinorVersion();
            metaInfo.setJdbcVersion(majorVersion + "." + minorVersion);
            _log.info("  product = " + metaInfo.getProductDisp());
            _log.info("  driver  = " + metaInfo.getDriverDisp());
            _connectionMetaInfo = metaInfo;
        } catch (SQLException continued) {
            _log.info("*Failed to get connection meta: " + continued.getMessage());
            _connectionMetaInfo = null;
        }
        _alreadySetupMeta = true;
    }

    // ===================================================================================
    //                                                                      Basic Override
    //                                                                      ==============
    @Override
    public String toString() {
        return "{url=" + _url + ", user=" + _user + ", prop=" + _connectionProperties + "}";
    }

    // ===================================================================================
    //                                                                            Accessor
    //                                                                            ========
    /**
     * Set the JDBC driver to be used.
     * @param driver driver class name
     */
    public void setDriver(String driver) {
        this._driver = driver;
    }

    /**
     * Set the DB connection URL.
     * @param url connection URL
     */
    public void setUrl(String url) {
        this._url = url;
    }

    /**
     * Set the user name for the DB connection.
     * @param user database user
     */
    public void setUser(String user) {
        this._user = user;
    }

    /**
     * Set the password for the DB connection.
     * @param password database password
     */
    public void setPassword(String password) {
        this._password = password;
    }

    /**
     * Set the connection properties for the DB connection.
     * @param connectionProperties The connection properties.
     */
    public void setConnectionProperties(Properties connectionProperties) {
        this._connectionProperties = connectionProperties;
    }

    /**
     * Set the autoCommit for the DB connection.
     * @param autoCommit Is auto commit?
     */
    public void setAutoCommit(boolean autoCommit) {
        this._autoCommit = autoCommit;
    }

    /**
     * Get the meta information of connected database.
     * @return The instance of meta information. (NullAllowed)
     */
    public DfConnectionMetaInfo getConnectionMetaInfo() {
        return _connectionMetaInfo;
    }
}