/** @return @throws Exception */
  public DataSource setUp() throws Exception {
    /** Load JDBC Driver class. */
    Class.forName(ConnectionPool.DRIVER).newInstance();

    /** Creates an instance of GenericObjectPool that holds our pool of connections object. */
    connectionPool = new GenericObjectPool();
    // set the max number of connections
    connectionPool.setMaxActive(connections);
    // if the pool is exhausted (i.e., the maximum number of active objects has been reached), the
    // borrowObject() method should simply create a new object anyway
    connectionPool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);

    /**
     * Creates a connection factory object which will be used by the pool to create the connection
     * object. We pass the JDBC url info, username and password.
     */
    ConnectionFactory cf =
        new DriverManagerConnectionFactory(
            ConnectionPool.URL, ConnectionPool.USERNAME, ConnectionPool.PASSWORD);

    /**
     * Creates a PoolableConnectionFactory that will wrap the connection object created by the
     * ConnectionFactory to add object pooling functionality.
     */
    PoolableConnectionFactory pcf =
        new PoolableConnectionFactory(cf, connectionPool, null, null, false, true);
    return new PoolingDataSource(connectionPool);
  }
  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);
    }
  }