/**
   * Performs the two-phase voting on the decree. After the voting each group member remains in the
   * same state as others.
   */
  public boolean vote(Object decree, long timeout, VoteResponseProcessor voteResponseProcessor)
      throws ChannelException {
    // wrap real decree
    TwoPhaseWrapper wrappedDecree = new TwoPhaseWrapper(decree);

    // check the decree acceptance
    try {
      if (voteChannel.vote(wrappedDecree, timeout / 3, voteResponseProcessor)) {
        wrappedDecree.commit();

        // try to commit decree
        if (!voteChannel.vote(wrappedDecree, timeout / 3, voteResponseProcessor)) {
          // strange, should fail during prepare... abort all
          wrappedDecree.abort();
          voteChannel.vote(wrappedDecree, timeout / 3, voteResponseProcessor);
          return false;
        } else return true;

      } else {
        // somebody is not accepting the decree... abort
        wrappedDecree.abort();
        voteChannel.vote(wrappedDecree, timeout / 3, voteResponseProcessor);
        return false;
      }
    } catch (ChannelException chex) {
      wrappedDecree.abort();
      voteChannel.vote(wrappedDecree, timeout / 3, voteResponseProcessor);
      throw chex;
    }
  }
    public boolean vote(Object decree) throws VoteException {
      if (!(decree instanceof TwoPhaseWrapper))
        throw new VoteException("Not my type of decree. Ignore me.");

      TwoPhaseWrapper wrapper = (TwoPhaseWrapper) decree;

      // invoke the corresponding operation
      if (wrapper.isPrepare()) return listener.prepare(wrapper.getDecree());
      else if (wrapper.isCommit()) return listener.commit(wrapper.getDecree());
      else {
        listener.abort(wrapper.getDecree());
        return false;
      }
    }