/** rollback the resource */
  public void rollback(Xid xid) throws XAException {
    try {
      int endFlags = _endFlags;
      _endFlags = -1;

      if (endFlags != -1 && _isXATransaction) {
        boolean isValid = false;

        try {
          endResource(xid, endFlags);
          isValid = true;
        } finally {
          if (!isValid) _xaResource.rollback(xid);
        }
      }

      if (log.isLoggable(Level.FINER)) log.finer("connection pool rollback XA: " + this);

      if (_isXATransaction) _xaResource.rollback(xid);
      else if (_localTransaction != null) {
        try {
          _isLocalTransaction = false;
          _localTransaction.rollback();
        } catch (ResourceException e) {
          throw new XAExceptionWrapper(e);
        }
      }
    } finally {
      if (_xaResource != null) _isXATransaction = true;

      clearXid();
    }
  }
  /** starts work on a transaction branch */
  public void start(Xid xid, int flags) throws XAException {
    if (_xid != null) {
      if (log.isLoggable(Level.FINER)) log.finer("connection pool start XA: rejoin " + this);

      return;
    }

    if (flags == TMJOIN && _xid == null) {
      // TMJOIN means the resource manager is managing more than one
      // connection.  The delegates tie the PoolItems managed by
      // the same resource manager together.

      _xid = xid;

      UserTransactionImpl trans = _cm.getTransaction();

      if (trans != null) {
        ManagedPoolItem xaHead = trans.findJoin(this);

        if (xaHead != null) {
          _xaNext = xaHead._xaNext;
          _xaHead = xaHead;
          xaHead._xaNext = this;
        }
      }
    }

    // local transaction optimization
    if (!_isXATransaction && flags != TMJOIN && _localTransaction != null) {
      try {
        if (log.isLoggable(Level.FINER))
          log.finer("begin-local-XA: " + xid + " " + _localTransaction);

        _localTransaction.begin();
      } catch (ResourceException e) {
        throw new XAExceptionWrapper(e);
      }

      _xid = xid;

      return;
    }

    if (_xaResource != null) {
      if (log.isLoggable(Level.FINER)) log.finer("start-XA: " + xid + " " + _xaResource);

      _xaResource.start(xid, flags);
      _isXATransaction = true;
    } else {
      if (log.isLoggable(Level.FINER))
        log.finer("start-XA with non XA resource: " + xid + " " + _xaResource);
    }

    _xid = xid;
  }
  /** commit the resource */
  public void commit(Xid xid, boolean onePhase) throws XAException {
    boolean logFiner = log.isLoggable(Level.FINER);

    try {
      int endFlags = _endFlags;
      _endFlags = -1;

      if (endFlags != -1 && _isXATransaction) {
        boolean isValid = false;

        try {
          endResource(xid, endFlags);
          isValid = true;
        } finally {
          if (!isValid) _xaResource.rollback(xid);
        }
      }

      if (_isXATransaction) {
        if (logFiner) {
          log.finer("commit-XA" + (onePhase ? "-1p: " : ": ") + xid + " " + _xaResource);
        }

        try {
          _xaResource.commit(xid, onePhase);
        } catch (XAException e) {
          if (logFiner) log.finer("commit-XA failed: " + _xaResource + " " + e);

          throw e;
        }
      } else if (_localTransaction != null) {
        if (logFiner) log.finer("commit-local: " + _localTransaction);

        try {
          _localTransaction.commit();
        } catch (ResourceException e) {
          if (logFiner) log.finer("commit failed: " + _localTransaction + " " + e);

          throw new XAExceptionWrapper(e);
        } finally {
          _isLocalTransaction = false;
        }
      } else {
        if (logFiner) log.finer("commit for resource with no XA support: " + this);
      }
    } finally {
      if (_xaResource != null) _isXATransaction = true;

      clearXid();
    }
  }