Java tutorial
/******************************************************************************* * 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); } }