/**
   * Checks if the pool item is still valid.
   *
   * @return true if the pool item is valid, false if it should be removed.
   */
  boolean isValid() {
    synchronized (this) {
      long now = Alarm.getCurrentTime();

      long maxIdleTime = _cm.getMaxIdleTime();
      long maxPoolTime = _cm.getMaxPoolTime();
      long maxActiveTime = _cm.getMaxActiveTime();

      boolean isActive = isActive() || _xid != null;
      boolean isDead = false;

      if (!isActive && _hasConnectionError) {
        isDead = true;
        log.fine("closing pool item from connection error:" + this);
      } else if (!isActive && 0 < maxIdleTime && _poolEventTime + maxIdleTime < now) {
        isDead = true;
        log.fine("closing pool item from idle timeout:" + this);
      } else if (!isActive && 0 < maxPoolTime && _poolStartTime + maxPoolTime < now) {
        isDead = true;
        log.fine("closing pool item from pool timeout:" + this);
      } else if (isActive && 0 < maxActiveTime && _poolEventTime + maxActiveTime < now) {
        isDead = true;
        log.warning("closing pool item from active timeout:" + this);
      }

      if (isDead) {
        _hasConnectionError = true;
        return false;
      } else return true;
    }
  }