view flys-backend/src/main/java/de/intevation/flys/utils/DBCPConnectionProvider.java @ 5200:42bb6ff78d1b 2.9.11

Directly set the connectionInitSqls on the datasource Somehow the factory fails to set the connectionInitSqls if we add it to the dbcpProperties. So we now set it directly
author Andre Heinecke <aheinecke@intevation.de>
date Fri, 08 Mar 2013 11:48:33 +0100
parents fb9dcc68b9c2
children
line wrap: on
line source
/*
 * Copyright 2004 The Apache Software Foundation.
 *
 * 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 de.intevation.flys.utils;

import java.sql.Connection;
import java.sql.SQLException;

import java.util.Iterator;
import java.util.Properties;
import java.util.Map;
import java.util.Collections;
import java.util.StringTokenizer;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;

import org.apache.log4j.Logger;

import org.hibernate.HibernateException;

import org.hibernate.connection.ConnectionProviderFactory;
import org.hibernate.connection.ConnectionProvider;

import org.hibernate.cfg.Environment;

/**
 * <p>A connection provider that uses an Apache commons DBCP connection pool.</p>
 *
 * <p>To use this connection provider set:<br>
 * <code>hibernate.connection.provider_class&nbsp;org.hibernate.connection.DBCPConnectionProvider</code></p>
 *
 * <pre>Supported Hibernate properties:
 *   hibernate.connection.driver_class
 *   hibernate.connection.url
 *   hibernate.connection.username
 *   hibernate.connection.password
 *   hibernate.connection.isolation
 *   hibernate.connection.autocommit
 *   hibernate.connection.pool_size
 *   hibernate.connection (JDBC driver properties)</pre>
 * <br>
 * All DBCP properties are also supported by using the hibernate.dbcp prefix.
 * A complete list can be found on the DBCP configuration page:
 * <a href="http://jakarta.apache.org/commons/dbcp/configuration.html">http://jakarta.apache.org/commons/dbcp/configuration.html</a>.
 * <br>
 * <pre>Example:
 *   hibernate.connection.provider_class org.hibernate.connection.DBCPConnectionProvider
 *   hibernate.connection.driver_class org.hsqldb.jdbcDriver
 *   hibernate.connection.username sa
 *   hibernate.connection.password
 *   hibernate.connection.url jdbc:hsqldb:test
 *   hibernate.connection.pool_size 20
 *   hibernate.dbcp.initialSize 10
 *   hibernate.dbcp.maxWait 3000
 *   hibernate.dbcp.validationQuery select 1 from dual</pre>
 *
 * <p>More information about configuring/using DBCP can be found on the
 * <a href="http://jakarta.apache.org/commons/dbcp/">DBCP website</a>.
 * There you will also find the DBCP wiki, mailing lists, issue tracking
 * and other support facilities</p>
 *
 * @see org.hibernate.connection.ConnectionProvider
 * @author Dirk Verbeeck
 */
public class DBCPConnectionProvider
implements   ConnectionProvider
{
    private static Logger log = Logger.getLogger(DBCPConnectionProvider.class);

    private static final String PREFIX = "hibernate.dbcp.";

    private BasicDataSource ds;

    // Old Environment property for backward-compatibility
    // (property removed in Hibernate3)
    private static final String DBCP_PS_MAXACTIVE =
        "hibernate.dbcp.ps.maxActive";

    // Property doesn't exists in Hibernate2
    private static final String AUTOCOMMIT =
        "hibernate.connection.autocommit";

    public void configure(Properties props) throws HibernateException {
        try {
            log.debug("Configure DBCPConnectionProvider");

            // DBCP properties used to create the BasicDataSource
            Properties dbcpProperties = new Properties();

            // DriverClass & url
            String jdbcDriverClass = props.getProperty(Environment.DRIVER);
            String jdbcUrl = props.getProperty(Environment.URL);
            dbcpProperties.put("driverClassName", jdbcDriverClass);
            dbcpProperties.put("url", jdbcUrl);

            // Username / password
            String username = props.getProperty(Environment.USER);
            String password = props.getProperty(Environment.PASS);
            dbcpProperties.put("username", username);
            dbcpProperties.put("password", password);

            // Isolation level
            String isolationLevel = props.getProperty(Environment.ISOLATION);
            if (isolationLevel != null
            && (isolationLevel = isolationLevel.trim()).length() > 0) {
                dbcpProperties.put("defaultTransactionIsolation", isolationLevel);
            }

            // Turn off autocommit (unless autocommit property is set)
            String autocommit = props.getProperty(AUTOCOMMIT);
            if (autocommit != null
            && (autocommit = autocommit.trim()).length() > 0) {
                dbcpProperties.put("defaultAutoCommit", autocommit);
            } else {
                dbcpProperties.put("defaultAutoCommit", String.valueOf(Boolean.FALSE));
            }

            // Pool size
            String poolSize = props.getProperty(Environment.POOL_SIZE);
            if (poolSize != null
            && (poolSize = poolSize.trim()).length() > 0
            && Integer.parseInt(poolSize) > 0)  {
                dbcpProperties.put("maxActive", poolSize);
            }

            // Copy all "driver" properties into "connectionProperties"
            Properties driverProps =
                ConnectionProviderFactory.getConnectionProperties(props);

            if (driverProps.size() > 0) {
                StringBuilder connectionProperties = new StringBuilder();
                for (Iterator iter = driverProps.entrySet().iterator();
                    iter.hasNext();
                ) {
                    Map.Entry entry = (Map.Entry)iter.next();
                    String    key   = (String)entry.getKey();
                    String    value = (String)entry.getValue();
                    connectionProperties
                        .append(key)
                        .append('=')
                        .append(value);
                    if (iter.hasNext()) {
                        connectionProperties.append(';');
                    }
                }
                dbcpProperties.put(
                    "connectionProperties", connectionProperties.toString());
            }

            // Copy all DBCP properties removing the prefix
            for (Iterator iter = props.entrySet().iterator() ; iter.hasNext() ;) {
                Map.Entry entry = (Map.Entry)iter.next();
                String    key   = (String)entry.getKey();
                if (key.startsWith(PREFIX)) {
                    String property = key.substring(PREFIX.length());
                    String value    = (String)entry.getValue();
                    dbcpProperties.put(property, value);
                }
            }

            // Backward-compatibility
            if (props.getProperty(DBCP_PS_MAXACTIVE) != null) {
                dbcpProperties.put(
                    "poolPreparedStatements",
                    String.valueOf(Boolean.TRUE));
                dbcpProperties.put(
                    "maxOpenPreparedStatements",
                    props.getProperty(DBCP_PS_MAXACTIVE));
            }

            // Some debug info
            /* // commented out, because it leaks the password
            if (log.isDebugEnabled()) {
                log.debug("Creating a DBCP BasicDataSource" +
                          " with the following DBCP factory properties:");
                StringWriter sw = new StringWriter();
                dbcpProperties.list(new PrintWriter(sw, true));
                log.debug(sw.toString());
            }
            */

            // Let the factory create the pool
            ds = (BasicDataSource)BasicDataSourceFactory
                .createDataSource(dbcpProperties);

            // This needs to be done manually as it is somehow ignored
            // by the BasicDataSourceFactory if you set it as a dbcpProperty
            String connectionInitSqls = props.getProperty("connectionInitSqls");
            if (connectionInitSqls != null) {
                StringTokenizer tokenizer = new StringTokenizer(connectionInitSqls, ";");
                ds.setConnectionInitSqls(Collections.list(tokenizer));
            }
            // The BasicDataSource has lazy initialization
            // borrowing a connection will start the DataSource
            // and make sure it is configured correctly.

            // Connection conn = ds.getConnection();
            // conn.close();
        }
        catch (Exception e) {
            String message = "Could not create a DBCP pool";
            log.fatal(message, e);
            if (ds != null) {
                BasicDataSource x = ds; ds = null;
                try {
                    x.close();
                }
                catch (SQLException sqle) {
                }
            }
            throw new HibernateException(message, e);
        }
        log.debug("Configure DBCPConnectionProvider complete");
    }

    public Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    public void closeConnection(Connection conn) throws SQLException {
        conn.close();
    }

    public void close() throws HibernateException {
        try {
            if (ds != null) {
                BasicDataSource x = ds; ds = null;
                x.close();
            }
        }
        catch (SQLException sqle) {
            throw new HibernateException("Could not close DBCP pool", sqle);
        }
    }

    public boolean supportsAggressiveRelease() {
        return false;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org