com.jolbox.bonecp.provider.BoneCPConnectionProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.jolbox.bonecp.provider.BoneCPConnectionProvider.java

Source

/**
 *  Copyright 2010 Wallace Wadge
 *
 *    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 com.jolbox.bonecp.provider;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.UnknownUnwrapTypeException;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.Stoppable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jolbox.bonecp.BoneCP;
import com.jolbox.bonecp.BoneCPConfig;
import com.jolbox.bonecp.hooks.ConnectionHook;

/**
 * Hibernate Connection Provider.
 *
 * @author wallacew
 */
public class BoneCPConnectionProvider implements ConnectionProvider, Configurable, Stoppable {
    /**
     * uid
     */
    private static final long serialVersionUID = -5236029951415598543L;
    /** Config key. */
    protected static final String CONFIG_CONNECTION_DRIVER_CLASS = "hibernate.connection.driver_class";
    /** Config key. */
    protected static final String CONFIG_CONNECTION_PASSWORD = "hibernate.connection.password";
    /** Config key. */
    protected static final String CONFIG_CONNECTION_USERNAME = "hibernate.connection.username";
    /** Config key. */
    protected static final String CONFIG_CONNECTION_URL = "hibernate.connection.url";
    /** Config key. */
    protected static final String CONFIG_CONNECTION_DRIVER_CLASS_ALTERNATE = "javax.persistence.jdbc.driver";
    /** Config key. */
    protected static final String CONFIG_CONNECTION_PASSWORD_ALTERNATE = "javax.persistence.jdbc.password";
    /** Config key. */
    protected static final String CONFIG_CONNECTION_USERNAME_ALTERNATE = "javax.persistence.jdbc.user";
    /** Config key. */
    protected static final String CONFIG_CONNECTION_URL_ALTERNATE = "javax.persistence.jdbc.url";
    /** Connection pool handle. */
    private BoneCP pool;
    /** Isolation level. */
    private Integer isolation;
    /** Autocommit option. */
    private boolean autocommit;
    /** Classloader to use to load the jdbc driver. */
    private ClassLoader classLoader;
    /** Configuration handle. */
    private BoneCPConfig config;
    /** Class logger. */
    private static final Logger logger = LoggerFactory.getLogger(BoneCPConnectionProvider.class);

    /**
     * {@inheritDoc}
     *
     * @see org.hibernate.service.jdbc.connections.spi.ConnectionProvider#closeConnection(java.sql.Connection)
     */
    public void closeConnection(Connection conn) throws SQLException {
        conn.close();
    }

    /**
     * Pool configuration.
     * @param props
     * @throws HibernateException
     */
    public void configure(Properties props) throws HibernateException {
        try {
            this.config = new BoneCPConfig(props);

            // old hibernate config
            String url = props.getProperty(CONFIG_CONNECTION_URL);
            String username = props.getProperty(CONFIG_CONNECTION_USERNAME);
            String password = props.getProperty(CONFIG_CONNECTION_PASSWORD);
            String driver = props.getProperty(CONFIG_CONNECTION_DRIVER_CLASS);
            if (url == null) {
                url = props.getProperty(CONFIG_CONNECTION_URL_ALTERNATE);
            }
            if (username == null) {
                username = props.getProperty(CONFIG_CONNECTION_USERNAME_ALTERNATE);
            }
            if (password == null) {
                password = props.getProperty(CONFIG_CONNECTION_PASSWORD_ALTERNATE);
            }
            if (driver == null) {
                driver = props.getProperty(CONFIG_CONNECTION_DRIVER_CLASS_ALTERNATE);
            }

            if (url != null) {
                this.config.setJdbcUrl(url);
            }
            if (username != null) {
                this.config.setUsername(username);
            }
            if (password != null) {
                this.config.setPassword(password);
            }

            // Remember Isolation level
            this.isolation = ConfigurationHelper.getInteger(AvailableSettings.ISOLATION, props);
            this.autocommit = ConfigurationHelper.getBoolean(AvailableSettings.AUTOCOMMIT, props);

            logger.debug(this.config.toString());

            if (driver != null && !driver.trim().equals("")) {
                loadClass(driver);
            }
            if (this.config.getConnectionHookClassName() != null) {
                Object hookClass = loadClass(this.config.getConnectionHookClassName()).newInstance();
                this.config.setConnectionHook((ConnectionHook) hookClass);
            }
            // create the connection pool
            this.pool = createPool(this.config);
        } catch (Exception e) {
            throw new HibernateException(e);
        }
    }

    /** Loads the given class, respecting the given classloader.
     * @param clazz class to load
     * @return Loaded class
     * @throws ClassNotFoundException
     */
    protected Class<?> loadClass(String clazz) throws ClassNotFoundException {
        if (this.classLoader == null) {
            return Class.forName(clazz);
        }

        return Class.forName(clazz, true, this.classLoader);

    }

    /** Creates the given connection pool with the given configuration. Extracted here to make unit mocking easier.
     * @param config configuration object.
     * @return BoneCP connection pool handle.
     */
    protected BoneCP createPool(BoneCPConfig config) {
        try {
            return new BoneCP(config);
        } catch (SQLException e) {
            throw new HibernateException(e);
        }
    }

    /**
     * {@inheritDoc}
     *
     * @see org.hibernate.service.jdbc.connections.spi.ConnectionProvider#getConnection()
     */
    public Connection getConnection() throws SQLException {
        Connection connection = this.pool.getConnection();

        // set the Transaction Isolation if defined
        try {
            // set the Transaction Isolation if defined
            if ((this.isolation != null) && (connection.getTransactionIsolation() != this.isolation.intValue())) {
                connection.setTransactionIsolation(this.isolation.intValue());
            }

            // toggle autoCommit to false if set
            if (connection.getAutoCommit() != this.autocommit) {
                connection.setAutoCommit(this.autocommit);
            }

            return connection;
        } catch (SQLException e) {
            try {
                connection.close();
            } catch (Exception e2) {
                logger.warn("Setting connection properties failed and closing this connection failed again", e);
            }

            throw e;
        }
    }

    /**
     * {@inheritDoc}
     *
     * @see org.hibernate.service.jdbc.connections.spi.ConnectionProvider#supportsAggressiveRelease()
     */
    public boolean supportsAggressiveRelease() {
        return false;
    }

    /** Returns the configuration object being used.
     * @return configuration object
     */
    protected BoneCPConfig getConfig() {
        return this.config;
    }

    /** Returns the classloader to use when attempting to load the jdbc driver (if a value is given).
     * @return the classLoader currently set.
     */
    public ClassLoader getClassLoader() {
        return this.classLoader;
    }

    /** Specifies the classloader to use when attempting to load the jdbc driver (if a value is given). Set to null to use the default
     * loader.
     * @param classLoader the classLoader to set
     */
    public void setClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    @SuppressWarnings("rawtypes")
    public boolean isUnwrappableAs(Class unwrapType) {
        return ConnectionProvider.class.equals(unwrapType)
                || BoneCPConnectionProvider.class.isAssignableFrom(unwrapType);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T unwrap(Class<T> unwrapType) {
        if (ConnectionProvider.class.equals(unwrapType)
                || BoneCPConnectionProvider.class.isAssignableFrom(unwrapType)) {
            return (T) this;
        }

        throw new UnknownUnwrapTypeException(unwrapType);
    }

    /**
     * Legacy conversion.
     * @param map
     * @return Properties
     */
    private Properties mapToProperties(Map<String, String> map) {
        Properties p = new Properties();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            p.put(entry.getKey(), entry.getValue());
        }
        return p;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public void configure(Map configurationValues) {
        configure(mapToProperties(configurationValues));
    }

    @Override
    public void stop() {
        close();
    }

    /**
     * alias for stop.
     */
    public void close() {
        this.pool.shutdown();
    }
}