jp.co.acroquest.endosnipe.data.db.ConnectionManager.java Source code

Java tutorial

Introduction

Here is the source code for jp.co.acroquest.endosnipe.data.db.ConnectionManager.java

Source

/*******************************************************************************
 * ENdoSnipe 5.0 - (https://github.com/endosnipe)
 * 
 * The MIT License (MIT)
 * 
 * Copyright (c) 2012 Acroquest Technology Co.,Ltd.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE 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.
 ******************************************************************************/
package jp.co.acroquest.endosnipe.data.db;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.sql.DataSource;

import jp.co.acroquest.endosnipe.common.logger.ENdoSnipeLogger;
import jp.co.acroquest.endosnipe.common.util.SQLUtil;
import jp.co.acroquest.endosnipe.data.DBInitializer;
import jp.co.acroquest.endosnipe.data.LogMessageCodes;

import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.StackObjectPool;
import org.seasar.framework.util.StringUtil;

/**
 * ????????<br />
 * 
 * @author y-komori
 */
public class ConnectionManager implements LogMessageCodes {
    /**  */
    private static final ENdoSnipeLogger LOGGER = ENdoSnipeLogger.getLogger(ConnectionManager.class);

    /** ConnectionManager?? */
    private static ConnectionManager instance__;

    /** ?????DataSource? */
    private final List<DataSourceEntry> dataSourceList_;

    /** ??????? */
    private final Map<String, ObjectPool> connectionPoolMap_;

    /** ??? */
    private final Set<String> initializedDatabaseSet_;

    /** ? */
    private static List<DataSourceCreator> dataSouceCreatorList__;

    static {
        dataSouceCreatorList__ = new ArrayList<DataSourceCreator>();
        dataSouceCreatorList__.add(new H2DataSourceCreator());
        dataSouceCreatorList__.add(new PostgresDataSourceCreator());
    }

    /**
     * ????
     */
    private ConnectionManager() {
        this.dataSourceList_ = new ArrayList<DataSourceEntry>();
        this.connectionPoolMap_ = new ConcurrentHashMap<String, ObjectPool>();
        this.initializedDatabaseSet_ = new CopyOnWriteArraySet<String>();
    }

    /**
     * {@link ConnectionManager} ????<br />
     * 
     * @return 
     */
    public static synchronized ConnectionManager getInstance() {
        if (instance__ == null) {
            instance__ = new ConnectionManager();
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    instance__.closeAll();
                }
            });
        }
        return instance__;
    }

    /**
     * ?????<br />
     * 
     * @param dbname ??
     * @param connectOnlyExists ?????????? <code>true</code> ?
     *                          ??????????? <code>false</code>
     * @return {@link Connection} 
     * @throws SQLException ???????????
     */
    public synchronized Connection getConnection(final String dbname, final boolean connectOnlyExists)
            throws SQLException {
        return getConnection(dbname, connectOnlyExists, true);
    }

    /**
     * ?????<br />
     * 
     * @param dbname ??
     * @param connectOnlyExists ?????????? <code>true</code> ?
     *                          ??????????? <code>false</code>
     * @param initialize        ??????
     * @return {@link Connection} 
     * @throws SQLException ???????????
     */
    public synchronized Connection getConnection(final String dbname, final boolean connectOnlyExists,
            final boolean initialize) throws SQLException {
        if (dbname == null) {
            throw new IllegalArgumentException("dbname can't be null");
        }

        DataSource ds = getDataSource(dbname);
        if (ds != null) {
            Connection connection = getConnection(ds, dbname);
            if (this.initializedDatabaseSet_.contains(dbname) == false && initialize) {
                initialize(dbname, initialize, connection);
            }
            return connection;
        }

        ds = createPoolingDataSource(dbname, connectOnlyExists);

        Connection conn = getConnection(ds, dbname);

        // ??????? DataSource ?
        registDataSource(dbname, ds);

        initialize(dbname, initialize, conn);

        return conn;
    }

    private void initialize(final String dbname, final boolean initialize, Connection conn) throws SQLException {
        try {
            // ???????
            boolean isInitialized = DBInitializer.isInitialized(conn);
            if (isInitialized) {
                this.initializedDatabaseSet_.add(dbname);
            } else if (initialize == true && isInitialized == false) {
                DBInitializer.initialize(conn);
                LOGGER.log(DB_INITIALIZED, dbname);
                this.initializedDatabaseSet_.add(dbname);
            }

            DBInitializer.reinitialize(conn);
        } catch (Exception ex) {
            LOGGER.log(EXCEPTION_OCCURED, ex, ex.getMessage());
            SQLException sqlex = new SQLException();
            sqlex.initCause(ex);
            throw sqlex;
        }
    }

    /**
     * ????<br />
     *
     * ??????????<br />
     *
     * @param baseDir  <code>null</code> ???? ~
     */
    public synchronized void setBaseDir(final String baseDir) {
        boolean changeBaseDir = !StringUtil.equals(baseDir, DBManager.getDbDir());

        if (baseDir != null) {
            DBManager.setDbDir(baseDir);
        } else {
            DBManager.setDbDir("~");
        }
        for (DataSourceCreator creator : dataSouceCreatorList__) {
            creator.setBaseDir(DBManager.getDbDir());
        }

        if (changeBaseDir) {
            closeAll();
        }
    }

    /**
     * ?????????<br />
     *
     * @param dbname ??
     * @return ???? <code>true</code> ?????? <code>false</code>
     */
    public boolean existsDatabase(final String dbname) {
        // ?????????DB??
        Connection con = null;
        boolean exist = false;
        try {
            con = getConnection(dbname, true);
            exist = true;
        } catch (SQLException ex) {
            exist = false;
        } finally {
            SQLUtil.closeConnection(con);
        }
        return exist;
    }

    /**
     * ????????<br />
     * ????????????????
     */
    public void closeAll() {
        try {
            for (ObjectPool connectionPool : this.connectionPoolMap_.values()) {
                connectionPool.clear();
            }
            int numActive = getNumActive();
            if (numActive > 0) {
                LOGGER.log(ACTIVE_CONNECTIONS_REMAINED, numActive);
            }
            this.connectionPoolMap_.clear();
            this.dataSourceList_.clear();
        } catch (Exception ex) {
            LOGGER.log(EXCEPTION_OCCURED, ex, ex.getMessage());
        }
    }

    /**
     * ?????<br />
     *
     * @param dataSource 
     * @param dbName {@link ConnectionWrapper} ????
     * @return {@link Connection} 
     * @throws SQLException ???????????
     */
    protected Connection getConnection(final DataSource dataSource, final String dbName) throws SQLException {
        Connection conn = dataSource.getConnection();
        ConnectionWrapper wrapper = new ConnectionWrapper(conn, dbName);
        LOGGER.log(DB_CONNECTED, dbName);
        return wrapper;
    }

    /**
     * ???????<br />
     *
     * @param dbname ??
     * @return 
     */
    protected DataSource getDataSource(final String dbname) {
        for (DataSourceEntry entry : this.dataSourceList_) {
            if (entry.getDbname().equals(dbname)) {
                return entry.getDataSource();
            }
        }
        return null;
    }

    /**
     * ????<br />
     *
     * @param dbname ??
     * @param dataSource 
     */
    protected void registDataSource(final String dbname, final DataSource dataSource) {
        if (getDataSource(dbname) == null) {
            DataSourceEntry entry = new DataSourceEntry(dbname, dataSource);
            this.dataSourceList_.add(entry);
        }
    }

    /**
     * {@link DataSource} ????<br />
     *
     * @param dbname ??
     * @param connectOnlyExists ?????????? <code>true</code> ?
     *                          ??????????? <code>false</code>
     * @return {@link DataSource}
     * @throws SQLException ??????
     */
    protected DataSource createPoolingDataSource(final String dbname, final boolean connectOnlyExists)
            throws SQLException {
        DataSourceCreator creator = getDataSourceCreator();
        return creator.createPoolingDataSource(dbname, connectOnlyExists);
    }

    /**
     * ??? {@link DataSource} ???????????<br />
     * 
     * @author y-komori
     */
    private static class DataSourceEntry {
        private final String dbname_;

        private final DataSource dataSource_;

        /**
         * {@link DataSourceEntry} ???<br />
         * 
         * @param dbname ??
            
         * @param dataSource {@link DataSource} 
         */
        public DataSourceEntry(final String dbname, final DataSource dataSource) {
            this.dbname_ = dbname;
            this.dataSource_ = dataSource;
        }

        /**
         * ?????<br />
         * 
         * @return ??
            
         */
        public String getDbname() {
            return this.dbname_;
        }

        /**
         * ???<br />
         * 
         * @return 
         */
        public DataSource getDataSource() {
            return this.dataSource_;
        }
    }

    /**
     * ?????????<br />
     *
     * @return ????
     */
    private int getNumActive() {
        int numActive = 0;
        for (ObjectPool objectPool : this.connectionPoolMap_.values()) {
            numActive += objectPool.getNumActive();
        }
        return numActive;
    }

    /**
     * ??????
     * @param key 
     * @return ?
     */
    public ObjectPool getConnectionPool(final String key) {
        return this.connectionPoolMap_.get(key);
    }

    /**
     * ???????
     * @param key 
     * @return ?
     */
    public ObjectPool createNewConnectionPool(String key) {
        ObjectPool connectionPool = this.connectionPoolMap_.get(key);
        if (connectionPool == null) {
            connectionPool = new StackObjectPool();
            this.connectionPoolMap_.put(key, connectionPool);
        }
        return connectionPool;
    }

    /**
     * ?????<br />
     * 
     * @return ?
     */
    public synchronized DataSourceCreator getDataSourceCreator() {
        for (DataSourceCreator creator : dataSouceCreatorList__) {
            if (creator.isTarget()) {
                return creator;
            }
        }
        return null;
    }

    /**
     * ???SQL????
     * @param sequenceName ?
     * @return ??SQL
     */
    public String getSequenceSql(String sequenceName) {
        DataSourceCreator creator = getDataSourceCreator();
        return creator.getSequenceSql(sequenceName);
    }
}