/**
   * Obtain a queue message synchronously.
   *
   * @param queueName Name of the queue from where to retrieve a message
   * @param timeout Timeout, in milliseconds. When timeout is reached a TimeoutException is thrown.
   *     Zero means that the client wants to wait forever. A negative value means that the client
   *     doesn't want to wait if there are no messages is local agent's queue.
   * @param reserveTime Message reserve time, in milliseconds. Polled messages are reserved, by
   *     default, for 15 minutes. If clients prefer a different reserve time , bigger or small, they
   *     can specify it.
   * @param acceptRequest An AcceptRequest object used handling Accept messages.
   * @return A notification containing the queue message. Or null if timeout was a negative value
   *     and there was no message in local agent's queue.
   */
  public NetNotification poll(
      String queueName, long timeout, long reserveTime, AcceptRequest acceptRequest)
      throws Throwable {
    if (StringUtils.isBlank(queueName))
      throw new IllegalArgumentException("Mal-formed Poll request. queueName is blank.");

    NetPoll poll = new NetPoll(queueName, timeout);
    NetAction action = new NetAction(ActionType.POLL);
    action.setPollMessage(poll);

    NetMessage message = buildMessage(action);

    SynchronousQueue<NetMessage> synQueue = new SynchronousQueue<NetMessage>();

    synchronized (_syncSubscriptions) {
      if (_syncSubscriptions.containsKey(queueName))
        throw new IllegalArgumentException("Queue " + queueName + " has already a poll runnig.");
      _syncSubscriptions.put(queueName, message);

      pendingPolls.put(queueName, synQueue);
    }

    if (reserveTime > 0) {
      message.getHeaders().put(Headers.RESERVE_TIME, reserveTime + "");
    }

    if (acceptRequest != null) {
      poll.setActionId(acceptRequest.getActionId());
      PendingAcceptRequestsManager.addAcceptRequest(acceptRequest);
    }

    getNetHandler().sendMessage(message);

    NetMessage receivedMsg = synQueue.take();

    synchronized (_syncSubscriptions) {
      _syncSubscriptions.remove(queueName);
      pendingPolls.remove(queueName);
    }

    if (receivedMsg == BrokerProtocolHandler.TimeoutUnblockNotification)
      throw new TimeoutException();
    if (receivedMsg == BrokerProtocolHandler.NoMessageUnblockNotification) return null;

    NetNotification m = null;
    if (receivedMsg.getAction().getActionType().equals(ActionType.NOTIFICATION)) {
      m = receivedMsg.getAction().getNotificationMessage();
    } else {
      log.error(
          "Poll unbloqued by a message that wasn't of any of the expeceted error nor a notification.");
      return null;
    }

    return m;
  }