// package com.wrox.connectionpool; package com.idega.util.database; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; import java.util.StringTokenizer; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import com.idega.idegaweb.IWMainApplication; import com.idega.repository.data.RefactorClassRegistry; import com.idega.repository.data.Singleton; import com.idega.util.text.TextSoap; /** * * @author <a href="http://www.wrox.com">wrox</a> modified by <a * href="mailto:tryggvi@idega.is">Tryggvi Larusson</a> * @version 1.3 Class to deliver database connections through a connectionpool */ public class PoolManager implements Singleton { private static final Logger log = Logger.getLogger(PoolManager.class.getName()); private static final String IW_APPLICATION_PATH_PLACE_HOLDER = "{iw_application_path}";// a private static final String IW_BUNDLES_PATH_PLACE_HOLDER = "{iw_bundles_path}";// a private static String DEFAULT_DSN = "default"; static private PoolManager instance; //static private int clients; private static boolean isUnlocked = true; private Vector drivers = new Vector(); private Hashtable pools = new Hashtable(); private IWMainApplication iwma; private PoolManager() { init(System.getProperty("file.separator") + "db.properties"); } private PoolManager(String propertiesFileLocation) { init(propertiesFileLocation); } private PoolManager(String propertiesFileLocation, IWMainApplication iwMainApplication) { this.iwma = iwMainApplication; init(propertiesFileLocation); } public static void lock() { isUnlocked = false; } public static void unlock() { isUnlocked = true; } static synchronized public PoolManager getInstance() { if (instance == null && isUnlocked) { instance = new PoolManager(); } //clients++; return instance; } static synchronized public PoolManager getInstance(String propertiesFileLocation) { if (instance == null && isUnlocked) { instance = new PoolManager(propertiesFileLocation); } //clients++; return instance; } static synchronized public PoolManager getInstance(String propertiesFileLocation, IWMainApplication mainApplication) { if (instance == null && isUnlocked) { instance = new PoolManager(propertiesFileLocation, mainApplication); } //clients++; return instance; } private void init(String propertiesFile) { // InputStream is = getClass().getResourceAsStream(propertiesFile); InputStream is; Properties dbProps = new Properties(); try { is = new FileInputStream(propertiesFile); dbProps.load(is); } catch (Exception e) { log.warning("Can't read the properties file from the specified location"); return; } loadDrivers(dbProps); createPools(dbProps); } private void loadDrivers(Properties props) { String driverClasses = props.getProperty("drivers"); StringTokenizer st = new StringTokenizer(driverClasses); while (st.hasMoreElements()) { String driverClassName = st.nextToken().trim(); try { Driver driver = (Driver) RefactorClassRegistry.forName(driverClassName).newInstance(); DriverManager.registerDriver(driver); this.drivers.addElement(driver); log.info( "Registered JDBC driver " + driverClassName); } catch (Exception e) { log.log(Level.WARNING, "Can't register JDBC driver: " + driverClassName, e); } } } private void createPools(Properties props) { Enumeration propNames = props.propertyNames(); while (propNames.hasMoreElements()) { String name = (String) propNames.nextElement(); if (name.endsWith(".url")) { String poolName = name.substring(0, name.lastIndexOf(".")); String url = props.getProperty(poolName + ".url"); if (url == null) { log.warning("No URL specified for " + poolName); continue; } if (this.pools.containsKey(poolName)) { log.warning("Pool '" + poolName + "'already exists"); continue; } // replace the {iw_application_path} variable with the real path to the // applications we folder if (this.iwma != null) { String applicationRealPath = this.iwma.getApplicationRealPath(); String bundlesRealPath = this.iwma.getBundlesRealPath(); // does not work because the string must be an expression // url.replaceAll(IW_APPLICATION_PATH_PLACE_HOLDER, // applicationRealPath); if (url.indexOf(IW_APPLICATION_PATH_PLACE_HOLDER) != -1) { url = TextSoap.findAndReplace(url, IW_APPLICATION_PATH_PLACE_HOLDER, applicationRealPath); } else if (url.indexOf(IW_BUNDLES_PATH_PLACE_HOLDER) != -1) { url = TextSoap.findAndReplace(url, IW_BUNDLES_PATH_PLACE_HOLDER, bundlesRealPath); } } String user = props.getProperty(poolName + ".user"); String password = props.getProperty(poolName + ".password"); String maxConns = props.getProperty(poolName + ".maxconns", "0"); String sRefreshIntervalMinutes = props.getProperty(poolName + ".refreshminutes", "20"); long lRefreshIntervalMillis; int max; try { max = Integer.valueOf(maxConns).intValue(); } catch (NumberFormatException e) { log.warning("Invalid maxconns value " + maxConns + " for " + poolName); max = 0; } String initConns = props.getProperty(poolName + ".initconns", "0"); int init; try { init = Integer.valueOf(initConns).intValue(); } catch (NumberFormatException e) { log.warning("Invalid initconns value " + initConns + " for " + poolName); init = 0; } String loginTimeOut = props.getProperty(poolName + ".logintimeout", "5"); int timeOut; try { timeOut = Integer.valueOf(loginTimeOut).intValue(); } catch (NumberFormatException e) { log.warning("Invalid logintimeout value " + loginTimeOut + " for " + poolName); timeOut = 5; } try { int iRefreshIntervalMinutes = Long.valueOf(sRefreshIntervalMinutes).intValue(); lRefreshIntervalMillis = iRefreshIntervalMinutes * 60 * 1000; } catch (NumberFormatException e) { lRefreshIntervalMillis = 20 * 1000 * 60; log.warning("Invalid refreshminutes value " + sRefreshIntervalMinutes + " for " + poolName); max = 0; } ConnectionPool pool = new ConnectionPool(poolName, url, user, password, max, init, timeOut, lRefreshIntervalMillis); this.pools.put(poolName, pool); } } } public Connection getConnection() { return getConnection(DEFAULT_DSN); } public Connection getConnection(String dataSourceName) { Connection conn = null; ConnectionPool pool = (ConnectionPool) this.pools.get(dataSourceName); if (pool != null) { try { conn = pool.getConnection(); } catch (SQLException e) { log.log(Level.WARNING, "Exception getting connection from " + dataSourceName, e); } } return conn; } public void freeConnection(String datasourceName, Connection con) { ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { pool.freeConnection(con); } } public void freeConnection(Connection connection) { freeConnection(DEFAULT_DSN, connection); } public synchronized void release() { // Wait until called by the last client // if (--clients != 0) // { // return; // } // prevent creation PoolManager.lock(); Enumeration allPools = this.pools.elements(); while (allPools.hasMoreElements()) { ConnectionPool pool = (ConnectionPool) allPools.nextElement(); pool.release(); } Enumeration allDrivers = this.drivers.elements(); while (allDrivers.hasMoreElements()) { Driver driver = (Driver) allDrivers.nextElement(); try { DriverManager.deregisterDriver(driver); log.info("Deregistered JDBC driver " + driver.getClass().getName()); } catch (SQLException e) { log.log(Level.WARNING, "Couldn't deregister JDBC driver: " + driver.getClass().getName(), e); } } instance = null; } // debug public String getStats(String name) { ConnectionPool tempPool = (ConnectionPool) this.pools.get(name); return tempPool.getStats(); } // Status of all pools: public String getStats() { String returnString = ""; for (Enumeration e = this.pools.keys(); e.hasMoreElements();) { String name = (String) e.nextElement(); ConnectionPool tempPool = (ConnectionPool) this.pools.get(name); returnString = returnString + "\nStatus of datasource " + name + " is: " + tempPool.getStats() + " "; } return returnString; } public Hashtable getStatsHashtable() { Hashtable table = new Hashtable(); for (Enumeration e = this.pools.keys(); e.hasMoreElements();) { String name = (String) e.nextElement(); ConnectionPool tempPool = (ConnectionPool) this.pools.get(name); table.put(name, "Status of datasource " + name + " is: " + tempPool.getStats() + " "); } return table; } public String[] getDatasources() { Vector sources = new Vector(); for (Enumeration e = this.pools.keys(); e.hasMoreElements();) { String name = (String) e.nextElement(); sources.add(name); } return (String[]) sources.toArray(new String[0]); } public boolean hasDatasource(String datasource) { return this.pools.containsKey(datasource); } public String getPasswordForPool(String datasourceName) { String password = null; ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { password = pool.getPassword(); } return password; } public String getPasswordForPool() { return getPasswordForPool(DEFAULT_DSN); } public String getUserNameForPool(String datasourceName) { String userName = null; ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { userName = pool.getUserName(); } return userName; } public String getUserNameForPool() { return getUserNameForPool(DEFAULT_DSN); } public String getURLForPool(String datasourceName) { String URL = null; ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { URL = pool.getURL(); } return URL; } public String getURLForPool() { return getURLForPool(DEFAULT_DSN); } /** * * This only works if there is one driver definition in the db.properties file * * TODO: Fix this limitation * * * * public String getDriverClassForPool(String datasourceName){ * * String driverClass = null; * * ConnectionPool pool = (ConnectionPool) pools.get(datasourceName); * * if (pool != null) * { * * * * driverClass = drivers.elementAt(0); * * * } * * return driverClass; * } */ public String getDriverClassForPool() { String driverClass = null; // ConnectionPool pool = (ConnectionPool) pools.get(datasourceName); if (this.drivers != null) { driverClass = ((Driver) this.drivers.elementAt(0)).getClass().getName(); } return driverClass; // return getDriverClassForPool(DEFAULT_DSN); } public Connection recycleConnection(Connection conn) { return recycleConnection(conn, DEFAULT_DSN); } public Connection recycleConnection(Connection conn, String dataSourceName) { ConnectionPool pool = (ConnectionPool) this.pools.get(dataSourceName); return pool.recycleConnection(conn); } /** * * Trims the pool so that it has only size connections * */ public void trimTo(String datasourceName, int size) { trimTo(datasourceName, size, size, size); } /** * * Trims the pool so that it has only size,minSize,maxSize connections * */ public void trimTo(String datasourceName, int size, int minSize, int maxSize) { ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { pool.trimTo(size, minSize, maxSize); } } /** * * Enlarges the pool so it has size number of connections * */ public void enlargeTo(String datasourceName, int size) { this.enlargeTo(datasourceName, size, size, size); } /** * * Enlarges the pool so it has size number of connections * */ public void enlargeTo(String datasourceName, int size, int minSize, int maxSize) { ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { pool.enlargeTo(size, minSize, maxSize); } } public int getCurrentConnectionCount(String datasourceName) { ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { return pool.getCurrentConnectionCount(); } return 0; } public int getMaximumConnectionCount(String datasourceName) { ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { return pool.getMaximumConnectionCount(); } return 0; } public int getMaximumConnectionCount() { return getMaximumConnectionCount(DEFAULT_DSN); } public int getMinimumConnectionCount(String datasourceName) { ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { return pool.getMinimumConnectionCount(); } return 0; } public int getMinimumConnectionCount() { return getMinimumConnectionCount(DEFAULT_DSN); } public int getTimeOut(String datasourceName) { ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { return pool.getTimeOut(); } return 0; } public void setTimeOut(String datasourceName, int timeout) { ConnectionPool pool = (ConnectionPool) this.pools.get(datasourceName); if (pool != null) { pool.setTimeOut(timeout); } } }