/** {@inheritDoc} */
  public ConnectionListener getConnection(
      Transaction trackByTransaction, Subject subject, ConnectionRequestInfo cri)
      throws ResourceException {
    ConnectionListener cl = null;
    boolean separateNoTx = false;

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

    // Get specific managed connection pool key
    Object key = getKey(subject, cri, separateNoTx);

    // Get managed connection pool
    ManagedConnectionPool mcp = getManagedConnectionPool(key, subject, cri);

    // Are we doing track by transaction ?
    TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
    Object transactionKey = tsr != null ? tsr.getTransactionKey() : null;

    if (trackByTransaction == null || transactionKey == null) {
      return getSimpleConnection(subject, cri, mcp);
    }

    // Transaction old connections
    cl = getTransactionOldConnection(trackByTransaction, mcp);

    // Creates a new connection with given transaction
    if (cl == null) {
      cl = getTransactionNewConnection(trackByTransaction, mcp, subject, cri);
    }

    return cl;
  }
  /**
   * 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;
  }
  /**
   * Get any transaction integration associated with the pool.
   *
   * @return the transaction integration
   */
  protected TransactionIntegration getTransactionIntegration() {
    if (clf != null) return clf.getTransactionIntegration();

    return null;
  }