/** Create dataSource object using given parameters */
  public DataSource setupDataSource(
      String connectionURL, String username, String password, int minIdle, int maxActive)
      throws Exception {
    GenericObjectPool connectionPool = new GenericObjectPool(null);
    connectionPool.setMinIdle(minIdle);
    connectionPool.setMaxActive(maxActive);
    connectionPool.setMaxWait(1000 * 60);

    pool = connectionPool;
    ConnectionFactory connectionFactory =
        new DriverManagerConnectionFactory(connectionURL, username, password);
    PoolableConnectionFactory factory =
        new PoolableConnectionFactory(connectionFactory, connectionPool, null, null, false, true);

    pool.setFactory(factory);
    PoolingDataSource dataSource = new PoolingDataSource(connectionPool);
    dataSource.setAccessToUnderlyingConnectionAllowed(true);
    return dataSource;
  }
  private synchronized void registerPool(String username, String password)
      throws javax.naming.NamingException {
    Map pools = (Map) dsInstanceMap.get(instanceKey);
    PoolKey key = getPoolKey(username);
    if (!pools.containsKey(key)) {
      int maxActive = getDefaultMaxActive();
      int maxIdle = getDefaultMaxIdle();
      int maxWait = getDefaultMaxWait();

      // The source of physical db connections
      ConnectionPoolDataSource cpds = this.cpds;
      if (cpds == null) {
        Context ctx = null;
        if (jndiEnvironment == null) {
          ctx = new InitialContext();
        } else {
          ctx = new InitialContext(jndiEnvironment);
        }
        cpds = (ConnectionPoolDataSource) ctx.lookup(dataSourceName);
      }

      Object whicheverPool = null;
      if (perUserMaxActive != null && perUserMaxActive.containsKey(username)) {
        Integer userMax = getPerUserMaxActive(username);
        if (userMax != null) {
          maxActive = userMax.intValue();
        }
        userMax = getPerUserMaxIdle(username);
        if (userMax != null) {
          maxIdle = userMax.intValue();
        }
        userMax = getPerUserMaxWait(username);
        if (userMax != null) {
          maxWait = userMax.intValue();
        }

        // Create an object pool to contain our PooledConnections
        GenericObjectPool pool = new GenericObjectPool(null);
        pool.setMaxActive(maxActive);
        pool.setMaxIdle(maxIdle);
        pool.setMaxWait(maxWait);
        pool.setWhenExhaustedAction(getWhenExhausted(maxActive, maxWait));
        pool.setTestOnBorrow(getTestOnBorrow());
        pool.setTestOnReturn(getTestOnReturn());
        pool.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis());
        pool.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun());
        pool.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
        pool.setTestWhileIdle(getTestWhileIdle());

        // Set up the factory we will use (passing the pool associates
        // the factory with the pool, so we do not have to do so
        // explicitly)
        new CPDSConnectionFactory(cpds, pool, validationQuery, username, password);
        whicheverPool = pool;
      } else {
        // use default pool
        // Create an object pool to contain our PooledConnections
        GenericKeyedObjectPool pool = new GenericKeyedObjectPool(null);
        pool.setMaxActive(maxActive);
        pool.setMaxIdle(maxIdle);
        pool.setMaxWait(maxWait);
        pool.setWhenExhaustedAction(getWhenExhausted(maxActive, maxWait));
        pool.setTestOnBorrow(getTestOnBorrow());
        pool.setTestOnReturn(getTestOnReturn());
        pool.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis());
        pool.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun());
        pool.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
        pool.setTestWhileIdle(getTestWhileIdle());

        // Set up the factory we will use (passing the pool associates
        // the factory with the pool, so we do not have to do so
        // explicitly)
        new KeyedCPDSConnectionFactory(cpds, pool, validationQuery);
        whicheverPool = pool;
      }

      // pools is a FastHashMap set to put the pool in a thread-safe way
      pools.put(key, whicheverPool);
    }
  }