/** Allocates a connection. */
  private Object allocateConnection(
      ManagedConnectionFactory mcf, Subject subject, ConnectionRequestInfo info)
      throws ResourceException {
    UserPoolItem userPoolItem = null;

    try {
      while (true) {
        userPoolItem = null;
        UserTransactionImpl transaction = _tm.getUserTransaction();

        if (transaction != null) userPoolItem = allocateShared(transaction, mcf, subject, info);

        if (userPoolItem == null) userPoolItem = allocatePoolConnection(mcf, subject, info, null);

        Object userConn;

        userConn = userPoolItem.allocateUserConnection();

        if (userConn != null) {
          userPoolItem = null;
          return userConn;
        }

        userPoolItem.close();
      }
    } finally {
      if (userPoolItem != null) userPoolItem.close();
    }
  }
  /**
   * Notifies that an application has closed the connection.
   *
   * <p>Remove and close the UserPoolItem associated with the PoolItem. If it's the last
   * UserPoolItem, move to the idle state.
   */
  public void connectionClosed(ConnectionEvent event) {
    Object handle = event.getConnectionHandle();

    if (!_hasConnectionError && handle == null && _shareHead != null) {
      log.fine(
          L.l(
              "JCA close event '{0}' for {1} did not have a connection handle.  Please notify the JCA resource provider.",
              event, _mConn));
    }

    UserPoolItem ptr = _shareHead;
    UserPoolItem prev = null;

    while (ptr != null) {
      UserPoolItem next = ptr.getShareNext();

      Object userConn = ptr.getUserConnection();

      if (userConn == handle || handle == null) {
        if (prev != null) prev.setShareNext(next);
        else _shareHead = next;

        ptr.close();
      } else prev = ptr;

      ptr = next;
    }

    if (_shareHead == null) {
      toIdle();
      return;
    }
  }
  /** Closes the connection. */
  void destroy() {
    ManagedConnection mConn = _mConn;
    _mConn = null;

    UserTransactionImpl transaction = _transaction;
    _transaction = null;

    if (mConn == null) return;

    _cm.removeItem(this, mConn);

    UserPoolItem userItem = _shareHead;

    if (log.isLoggable(Level.FINE)) log.fine("connection pool destroy " + this);

    try {
      while (userItem != null) {
        UserPoolItem next = userItem.getShareNext();

        userItem.close();

        userItem = next;
      }

      if (transaction != null) transaction.delistPoolItem(this, XAResource.TMFAIL);
    } catch (Throwable e) {
      log.log(Level.FINE, e.toString(), e);
    }

    try {
      mConn.destroy();
    } catch (Exception e) {
      log.log(Level.FINE, e.toString(), e);
    } finally {
      _cm.getConnectionTimeProbe().end(_connectionStartTime);
    }
  }