com.eyeq.pivot4j.datasource.PooledOlapDataSource.java Source code

Java tutorial

Introduction

Here is the source code for com.eyeq.pivot4j.datasource.PooledOlapDataSource.java

Source

/*
 * ====================================================================
 * This software is subject to the terms of the Common Public License
 * Agreement, available at the following URL:
 *   http://www.opensource.org/licenses/cpl.html .
 * You must accept the terms of that agreement to use this software.
 * ====================================================================
 */
package com.eyeq.pivot4j.datasource;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.SQLException;

import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.olap4j.OlapConnection;
import org.olap4j.OlapDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.eyeq.pivot4j.PivotException;

public class PooledOlapDataSource extends AbstractOlapDataSource implements CloseableDataSource {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private GenericObjectPool.Config poolConfig;

    private GenericObjectPool<OlapConnection> pool;

    private OlapDataSource dataSource;

    private PooledOlapConnectionFactory connectionFactory;

    /**
     * @param dataSource
     */
    public PooledOlapDataSource(OlapDataSource dataSource) {
        this(dataSource, null);
    }

    /**
     * @param dataSource
     * @param poolConfig
     */
    public PooledOlapDataSource(OlapDataSource dataSource, GenericObjectPool.Config poolConfig) {
        if (dataSource == null) {
            throw new NullArgumentException("dataSource");
        }

        this.dataSource = dataSource;
        this.poolConfig = poolConfig == null ? new GenericObjectPool.Config() : poolConfig;
        this.connectionFactory = createConnectionFactory(dataSource);
        this.pool = createPool(connectionFactory, poolConfig);
    }

    /**
     * @return the dataSource
     */
    public OlapDataSource getDataSource() {
        return dataSource;
    }

    /**
     * @see com.eyeq.pivot4j.datasource.CloseableDataSource#close()
     */
    @Override
    public synchronized void close() throws SQLException {
        try {
            if (logger.isInfoEnabled()) {
                logger.info("Disposing the connection pool.");
            }

            this.getPool().close();
        } catch (SQLException e) {
            throw e;
        } catch (Exception e) {
            throw new SQLException(e);
        }
    }

    /**
     * @return the connectionFactory
     */
    protected PooledOlapConnectionFactory createConnectionFactory(OlapDataSource dataSource) {
        return new PooledOlapConnectionFactory(dataSource);
    }

    /**
     * @return the connectionFactory
     */
    protected PooledOlapConnectionFactory getConnectionFactory() {
        return connectionFactory;
    }

    /**
     * @param factory
     * @param config
     * @return the pool
     */
    protected GenericObjectPool<OlapConnection> createPool(PoolableObjectFactory<OlapConnection> factory,
            GenericObjectPool.Config config) {
        if (logger.isInfoEnabled()) {
            logger.info("Creating connection pool with following parameters : ");
            logger.info("   - max active : " + config.maxActive);
            logger.info("   - max idle : " + config.maxIdle);
            logger.info("   - min idle: " + config.minIdle);
            logger.info("   - max wait : " + config.maxWait);
        }
        return new GenericObjectPool<OlapConnection>(factory, config);
    }

    /**
     * @return the pool
     */
    protected GenericObjectPool<OlapConnection> getPool() {
        return pool;
    }

    /**
     * Note: Both 'userName' and 'password' are ignored.
     * 
     * @see com.eyeq.pivot4j.datasource.AbstractOlapDataSource#createConnection(java.lang.String,
     *      java.lang.String)
     */
    @Override
    protected OlapConnection createConnection(String userName, String password) throws SQLException {
        try {
            return pool.borrowObject();
        } catch (SQLException e) {
            throw e;
        } catch (Exception e) {
            throw new SQLException(e);
        }
    }

    /**
     * @return the number of active connections
     */
    public int getNumActive() {
        return pool.getNumActive();
    }

    /**
     * @return the number of idle connections
     */
    public int getNumIdle() {
        return pool.getNumIdle();
    }

    /**
     * @return the maxIdle
     */
    public int getMaxIdle() {
        return poolConfig.maxIdle;
    }

    /**
     * @return the maxActive
     */
    public int getMaxActive() {
        return poolConfig.maxActive;
    }

    /**
     * @return the maxWait
     */
    public long getMaxWait() {
        return poolConfig.maxWait;
    }

    /**
     * @return the whenExhaustedAction
     */
    public byte getWhenExhaustedAction() {
        return poolConfig.whenExhaustedAction;
    }

    /**
     * @return the testOnBorrow
     */
    public boolean isTestOnBorrow() {
        return poolConfig.testOnBorrow;
    }

    /**
     * @return the testOnReturn
     */
    public boolean isTestOnReturn() {
        return poolConfig.testOnReturn;
    }

    /**
     * @return the testWhileIdle
     */
    public boolean isTestWhileIdle() {
        return poolConfig.testWhileIdle;
    }

    /**
     * @return the timeBetweenEvictionRunsMillis
     */
    public long getTimeBetweenEvictionRunsMillis() {
        return poolConfig.timeBetweenEvictionRunsMillis;
    }

    /**
     * @return the numTestsPerEvictionRun
     */
    public int getNumTestsPerEvictionRun() {
        return poolConfig.numTestsPerEvictionRun;
    }

    /**
     * @return the minEvictableIdleTimeMillis
     */
    public long getMinEvictableIdleTimeMillis() {
        return poolConfig.minEvictableIdleTimeMillis;
    }

    class PooledOlapConnectionFactory extends OlapConnectionFactory {

        /**
         * @param dataSource
         */
        public PooledOlapConnectionFactory(OlapDataSource dataSource) {
            super(dataSource);
        }

        /**
         * @see com.eyeq.pivot4j.datasource.OlapConnectionFactory#makeObject()
         */
        @Override
        public OlapConnection makeObject() {
            final OlapConnection connection = super.makeObject();

            InvocationHandler handler = new InvocationHandler() {

                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                    if (method.getName().equals("close")) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Return a connection to the pool : " + connection);
                        }

                        pool.returnObject((OlapConnection) proxy);

                        if (logger.isDebugEnabled()) {
                            logger.debug("   - current pool size : " + pool.getNumActive() + " / "
                                    + pool.getMaxActive());
                        }

                        return null;
                    } else {
                        return method.invoke(connection, args);
                    }
                }
            };

            return (OlapConnection) Proxy.newProxyInstance(getClass().getClassLoader(),
                    new Class[] { OlapConnection.class }, handler);
        }

        /**
         * @see com.eyeq.pivot4j.datasource.OlapConnectionFactory#destroyObject(org
         *      .olap4j.OlapConnection)
         */
        @Override
        public void destroyObject(OlapConnection con) {
            if (logger.isDebugEnabled()) {
                logger.debug("Closing a returned connection object : " + con);
            }

            try {
                con.unwrap(OlapConnection.class).close();
            } catch (SQLException e) {
                throw new PivotException(e);
            }
        }
    }
}