/**
   * Gets simple connection listener that wraps connection.
   *
   * @param subject Subject instance
   * @param cri Connection request info
   * @param mcp The managed connection pool
   * @return connection listener
   * @throws ResourceException ResourceException
   */
  private ConnectionListener getSimpleConnection(
      final Subject subject, final ConnectionRequestInfo cri, final ManagedConnectionPool mcp)
      throws ResourceException {
    ConnectionListener cl = null;

    try {
      // Get connection from the managed connection pool
      cl = mcp.getConnection(subject, cri);

      if (trace) log.tracef("Got connection from pool: %s", cl);

      return cl;
    } catch (ResourceException re) {
      if (re instanceof RetryableException) {
        if (log.isDebugEnabled())
          log.debug("Got a RetryableException - trying to reinitialize the pool");

        // Make sure that the managed connection pool is running
        if (!mcp.isRunning()) mcp.reenable();

        // Getting connection from pool
        cl = mcp.getConnection(subject, cri);

        if (trace) log.tracef("Got connection from pool (retried): %s", cl);

        return cl;
      } else {
        throw re;
      }
    }
  }
  /**
   * Test if a connection can be obtained
   *
   * @param subject Optional subject
   * @param cri Optional CRI
   * @return True if possible; otherwise false
   */
  protected boolean internalTestConnection(ConnectionRequestInfo cri, Subject subject) {
    boolean result = false;
    ConnectionListener cl = null;
    try {
      boolean separateNoTx = false;

      if (noTxSeparatePools) {
        separateNoTx = clf.isTransactional();
      }

      Object key = getKey(subject, cri, separateNoTx);
      ManagedConnectionPool mcp = getManagedConnectionPool(key, subject, cri);

      if (mcp.getStatistics().getAvailableCount() > 0) {
        cl = mcp.getConnection(subject, cri);
        result = true;
      }
    } catch (Throwable ignored) {
      // Ignore
    } finally {
      if (cl != null) {
        try {
          returnConnection(cl, false);
        } catch (ResourceException ire) {
          // Ignore
        }
      }
    }

    return result;
  }
  /**
   * Gets new connection listener if necessary instance with transaction. This method is package
   * protected beacause it is intended only for test case use. Please don't use it in your
   * production code.
   *
   * @param trackByTransaction transaction instance
   * @param mcp pool instance
   * @param subject subject instance
   * @param cri connection request info
   * @return connection listener instance
   * @throws ResourceException ResourceException
   */
  ConnectionListener getTransactionNewConnection(
      Transaction trackByTransaction,
      ManagedConnectionPool mcp,
      Subject subject,
      ConnectionRequestInfo cri)
      throws ResourceException {
    // Need a new one for this transaction
    // This must be done outside the tx local lock, otherwise
    // the tx timeout won't work and get connection can do a lot of other work
    // with many opportunities for deadlocks.
    // Instead we do a double check after we got the transaction to see
    // whether another thread beat us to the punch.
    ConnectionListener cl = mcp.getConnection(subject, cri);
    if (trace)
      log.tracef(
          "Got connection from pool tracked by transaction=%s tx=%s", cl, trackByTransaction);

    TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
    Lock lock = getLock();
    try {
      lock.lockInterruptibly();
    } catch (InterruptedException ie) {
      Thread.interrupted();

      throw new ResourceException(bundle.unableObtainLock(), ie);
    }
    try {
      // Check we weren't racing with another transaction
      ConnectionListener other = (ConnectionListener) tsr.getResource(mcp);

      if (other != null) {
        mcp.returnConnection(cl, false);

        if (trace)
          log.tracef(
              "Another thread already got a connection tracked by transaction=%s tx=%s",
              other, trackByTransaction);

        cl = other;
      }

      // This is the connection for this transaction
      cl.setTrackByTx(true);
      tsr.putResource(mcp, cl);

      if (trace)
        log.tracef(
            "Using connection from pool tracked by transaction=%s tx=%s", cl, trackByTransaction);

      return cl;
    } finally {
      lock.unlock();
    }
  }