private static synchronized void initialize(String poolname) {
    if (!isInitialized) {
      // create worker pool
      workerPool = new GenericObjectPool(new RWorkerObjectFactory(poolname));
      workerPool.setMaxActive(4);
      workerPool.setMaxIdle(4);
      workerPool.setTestOnBorrow(true);
      workerPool.setTestOnReturn(true);

      isInitialized = true;
    }
  }
  public static GenericObjectPool getInstance(
      String poolName, String driver, final String url, final String user, final String password) {

    String key = driver + "%" + poolName + "%" + url + "%" + user + "%" + password;

    // log.info("getInstance-key="+key);

    if (_pool.get(key) != null) return _pool.get(key);

    synchronized (lock) {
      if (_pool.get(key) == null) {
        try {
          Class.forName(driver);

          DBLayerInterface dbLayer =
              DBLayer.getLayer(
                  getDBType(url),
                  new ConnectionProvider() {
                    public Connection newConnection() throws SQLException {
                      return DriverManager.getConnection(url, user, password);
                    }
                  });

          GenericObjectPool p = new ServerObjectPool(new ServantProxyFactoryDB(poolName, dbLayer));

          _pool.put(key, p);
          p.setMaxIdle(0);
          p.setMaxActive(-1);
          p.setTestOnBorrow(true);
          p.setTestOnReturn(true);
        } catch (Exception e) {
          throw new RuntimeException(getStackTraceAsString(e));
        }
      }
      return _pool.get(key);
    }
  }
  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);
    }
  }