/* * $Id: ConnectionBroker.java,v 1.13.2.1 2007/01/12 19:32:58 idegaweb Exp $ * * Copyright (C) 2000-2005 Idega hf. All Rights Reserved. * * This software is the proprietary information of Idega hf. * Use is subject to license terms. * */ package com.idega.util.database; import java.sql.Connection; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; import com.idega.transaction.IdegaTransaction; import com.idega.transaction.IdegaTransactionManager; /** *<p> * This class is an abstraction of the underlying Database Pool.<br> * It can deliver connections from the old style idegaWeb PoolManager or a J2EE style JDBC/JNDI DataSource.<br> * Works in conjunction with com.idega.transaction.IdegaTransactionManager, * com.idega.util.database.PoolManager and javax.sql.DataSource.<br> * * Whenever a connection object is gotten with getConnection(x) there should always follow a call to freeConnection(x) * when the Connection is not used anymore, otherwise the Pool could get empty and unused connections left out in limbo. * <br> * The implementation is such that if a db.properties file is found in the webapp under either /idegaweb/properties * or /WEB-INF/idegaweb/properties/ then the idegaWeb Pool is used, if it does not exist then * the ConnectionBroker tries to look up a DataSource with the url 'jdbc/DefaultDS' in the JNDI directory. * <br> * </p> *@author <a href="mailto:tryggvi@idega.is">Tryggvi Larusson</a> * @version $Revision: 1.13.2.1 $ */ public class ConnectionBroker { private static Context initialContext; public final static String DEFAULT_POOL = "default"; public final static int POOL_MANAGER_TYPE_IDEGA = 1; public final static int POOL_MANAGER_TYPE_POOLMAN = 2; public final static int POOL_MANAGER_TYPE_JDBC_DATASOURCE = 3; public static int POOL_MANAGER_TYPE = POOL_MANAGER_TYPE_IDEGA; private static String DEFAULT_JDBC_JNDI_URL = "jdbc/DefaultDS"; private static DataSource defaultDs; private static Map dataSourcesMap=new HashMap(); private static Logger log = Logger.getLogger(ConnectionBroker.class.getName()); /** * Returns a Datastore connection from the default datasource */ public static Connection getConnection() { return getConnection(true); } /** * Returns a Datastore connection from the default datasource */ public static Connection getConnection(boolean doTransactionCheck) { if (doTransactionCheck) { return getConnection(DEFAULT_POOL); } else { return PoolManager.getInstance().getConnection(); } } /** * Returns a Datastore connection from the default datasource */ private static Connection getConnectionOld(boolean doTransactionCheck) { Connection conn = null; IdegaTransactionManager tm = (IdegaTransactionManager) IdegaTransactionManager.getInstance(); if (doTransactionCheck && tm.hasCurrentThreadBoundTransaction()) { try { conn = ((IdegaTransaction) tm.getTransaction()).getConnection(); } catch (Exception ex) { ex.printStackTrace(System.err); } } else { if (isUsingIdegaPool()) { conn = PoolManager.getInstance().getConnection(); } else if (isUsingPoolManPool()) { //try{ //conn = com.codestudio.util.SQLManager.getInstance().requestConnection(); /** * @todo: Commit in support for com.codestudio.util PoolMan */ //} //catch(SQLException e){ // throw new RuntimeException(e.getMessage()); //} } else { throw new RuntimeException("PoolManager not available"); } } return conn; } /** * Does not fully support TransactionManager * Returns a Datastore connection from the datasource */ public static Connection getConnection(String dataSourceName) { if (dataSourceName == null) { return getConnection(); } else { Connection conn = null; IdegaTransactionManager tm = (IdegaTransactionManager) IdegaTransactionManager.getInstance(); if (tm.hasCurrentThreadBoundTransaction()) { try { //System.out.println("Getting connection from transaction for datasource: "+dataSourceName); conn = ((IdegaTransaction) tm.getTransaction()).getConnection(); } catch (Exception ex) { ex.printStackTrace(System.err); } } else { if (isUsingIdegaPool()) { //System.out.println("Getting connection from pool for datasource: "+dataSourceName); conn = PoolManager.getInstance().getConnection(dataSourceName); } else if (isUsingJNDIDatasource()) { try { conn = getDataSource(dataSourceName).getConnection(); } catch (SQLException e) { System.out.println("Error getting connection from JDBC datasource : " + dataSourceName); e.printStackTrace(System.err); } } else if (isUsingPoolManPool()) { //try{ /** * @todo: Commit in support for com.codestudio.util PoolMan */ //conn = ((com.codestudio.util.JDBCPool)com.codestudio.util.SQLManager.getInstance().getPool(dataSourceName)).requestConnection(); //} //catch(SQLException e){ // throw new RuntimeException(e.getMessage()); //} } } return conn; } } /** * Frees (Reallocates) a Datastore connection to the default datasource */ public static void freeConnection(Connection connection) { freeConnection(connection, true); } /** * Returns a Datastore connection from the default datasource */ public static void freeConnection(Connection connection, boolean doTransactionCheck) { if (doTransactionCheck) { freeConnection(DEFAULT_POOL, connection); } else { freePooledConnection(null,connection); } } /** * Frees (Reallocates) a Datastore connection to the default datasource */ private static void freeConnectionOld(Connection connection, boolean doTransactionCheck) { if (doTransactionCheck && !((IdegaTransactionManager) IdegaTransactionManager.getInstance()).hasCurrentThreadBoundTransaction()) { freePooledConnection(null,connection); } else if (!doTransactionCheck) { freePooledConnection(null,connection); } } private static void freePooledConnection(String dataSourceName,Connection connection){ if (isUsingIdegaPool()) { if(dataSourceName==null){ PoolManager.getInstance().freeConnection(connection); } else{ PoolManager.getInstance().freeConnection(dataSourceName,connection); } } else if (isUsingJNDIDatasource()) { try { if(!connection.isClosed()){ connection.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else if (isUsingPoolManPool()) { /** * @todo: Commit in support for com.codestudio.util PoolMan */ //com.codestudio.util.SQLManager.getInstance().returnConnection(connection); } } /** * Frees (Reallocates) a Datastore connection to the datasource */ public static void freeConnection(String dataSourceName, Connection connection, boolean doTransactionCheck) { if (dataSourceName == null) { freeConnection(connection, doTransactionCheck); } else { if (doTransactionCheck && !((IdegaTransactionManager) IdegaTransactionManager.getInstance()).hasCurrentThreadBoundTransaction()) { freePooledConnection(dataSourceName,connection); } else if (!doTransactionCheck) { freePooledConnection(dataSourceName,connection); } } } /** * Frees (Reallocates) a Datastore connection to the datasource */ public static void freeConnection(String dataSourceName, Connection connection) { freeConnection(dataSourceName, connection, true); } public static String[] getDatasources() { return PoolManager.getInstance().getDatasources(); } public static String getURL() { return PoolManager.getInstance().getURLForPool(); } public static String getURL(String dataSourceName) { return PoolManager.getInstance().getURLForPool(dataSourceName); } public static String getUserName() { return PoolManager.getInstance().getUserNameForPool(); } public static String getUserName(String dataSourceName) { return PoolManager.getInstance().getUserNameForPool(dataSourceName); } public static String getPassword() { return PoolManager.getInstance().getPasswordForPool(); } public static String getPassword(String dataSourceName) { return PoolManager.getInstance().getPasswordForPool(dataSourceName); } public static String getDriverClass() { return PoolManager.getInstance().getDriverClassForPool(); } public Connection recycleConnection(Connection conn, String dataSourceName) { return PoolManager.getInstance().recycleConnection(conn, dataSourceName); } public Connection recycleConnection(Connection conn) { return PoolManager.getInstance().recycleConnection(conn); } public static boolean isUsingIdegaPool() { return (POOL_MANAGER_TYPE == POOL_MANAGER_TYPE_IDEGA); } public static boolean isUsingPoolManPool() { return (POOL_MANAGER_TYPE == POOL_MANAGER_TYPE_POOLMAN); } public static boolean isUsingJNDIDatasource() { return (POOL_MANAGER_TYPE == POOL_MANAGER_TYPE_JDBC_DATASOURCE); } public static boolean tryDefaultJNDIDataSource(){ /** * @todo change: * only supports the default datasource now implement support for others */ DataSource ds; try{ log.info("Trying DataSource with url: '"+DEFAULT_JDBC_JNDI_URL+"'"); ds = getDataSource(DEFAULT_POOL); } catch(Exception e){ e.printStackTrace(); return false; } if(ds!=null){ POOL_MANAGER_TYPE=POOL_MANAGER_TYPE_JDBC_DATASOURCE; log.info("Successfully enabled Database from DataSource: "+DEFAULT_JDBC_JNDI_URL); return true; } return false; } /** * <p> * Gets the datasource from the string 'datasourceName'<br> * If dataSourceName is 'default' it returns the default datasource from 'jdbc/DefaultDS' otherwise it tries to look up * a datasource from jdbc/[datasourceName]. * </p> * @param datasourceName * @return */ static DataSource getDataSource(String datasourceName) { if(datasourceName == null || datasourceName == DEFAULT_POOL || datasourceName.equals(DEFAULT_POOL)){ if (defaultDs == null) { try { defaultDs = (DataSource) getEnvContext().lookup(DEFAULT_JDBC_JNDI_URL); dataSourcesMap.put(DEFAULT_POOL,defaultDs); } catch (NamingException e) { throw new RuntimeException("Error initializing datasource: " + datasourceName + ". Error was: " + e.getMessage()); } } return defaultDs; } else{ DataSource dataSource = (DataSource)dataSourcesMap.get(datasourceName); if(dataSource==null){ try { dataSource = (DataSource) getEnvContext().lookup("jdbc/"+datasourceName); dataSourcesMap.put(datasourceName,dataSource); } catch (NamingException e) { throw new RuntimeException("Error initializing datasource: " + datasourceName + ". Error was: " + e.getMessage()); } } return dataSource; } } /** * Sets the url to the default datasource if the JDBC datasource is the current pool type * @param url */ public static void setDefaultJDBCDatasourceURL(String url){ DEFAULT_JDBC_JNDI_URL=url; } private static Context getEnvContext()throws NamingException{ if(initialContext==null){ initialContext = new InitialContext(); } return (Context) initialContext.lookup("java:comp/env"); } public static String getDefaultJNDIUrl(){ return DEFAULT_JDBC_JNDI_URL; } }