public final NevadoMessage receiveMessage(
     NevadoConnection connection, NevadoDestination destination, long timeoutMs)
     throws JMSException, InterruptedException {
   long startTimeMs = new Date().getTime();
   SQSQueue sqsQueue = getSQSQueue(destination);
   SQSMessage sqsMessage =
       receiveSQSMessage(connection, destination, timeoutMs, startTimeMs, sqsQueue);
   if (sqsMessage != null) {
     _log.info("Received message " + sqsMessage.getMessageId());
   }
   return sqsMessage != null ? convertSqsMessage(destination, sqsMessage, false) : null;
 }
  protected final SQSMessage receiveSQSMessage(
      NevadoConnection connection,
      NevadoDestination destination,
      long timeoutMs,
      long startTimeMs,
      SQSQueue sqsQueue)
      throws JMSException, InterruptedException {
    SQSMessage sqsMessage;
    while (true) {
      if (connection.isRunning()) {
        sqsMessage = sqsQueue.receiveMessage();
        if (sqsMessage != null && !connection.isRunning()) {
          // Connection was stopped while the REST call to SQS was being made
          try {
            sqsQueue.setMessageVisibilityTimeout(
                sqsMessage.getReceiptHandle(),
                0); // Make it immediately available to the next requestor
          } catch (JMSException e) {
            String exMessage = "Unable to reset visibility timeout for message: " + e.getMessage();
            _log.warn(
                exMessage,
                e); // Non-fatal.  Just means the message will disappear until the visibility
                    // timeout expires.
          }
          sqsMessage = null;
        }
      } else {
        _log.debug("Not accepting messages.  Connection is paused or not started.");
        sqsMessage = null;
      }

      // Check for message or timeout
      if (sqsMessage != null
          || (timeoutMs > -1 && (new Date().getTime() - startTimeMs) >= timeoutMs)) {
        break;
      }

      Thread.sleep(_receiveCheckIntervalMs);
    }
    if (_log.isDebugEnabled()) {
      _log.debug(
          "Received message: " + ((sqsMessage != null) ? sqsMessage.getMessageBody() : null));
    }
    return sqsMessage;
  }
  protected final NevadoMessage convertSqsMessage(
      NevadoDestination destination, SQSMessage sqsMessage, boolean readOnly) throws JMSException {
    // Get the message
    NevadoMessage message;
    String messageBody;
    if (destination instanceof NevadoQueue) {
      messageBody = sqsMessage.getMessageBody();
    } else {
      try {
        messageBody = new JSONObject(sqsMessage.getMessageBody()).getString("Message");
      } catch (JSONException e) {
        throw new JMSException(
            "Unable to parse JSON from message body: " + sqsMessage.getMessageBody());
      }
    }
    try {
      message = deserializeMessage(messageBody);
    } catch (JMSException e) {
      message = new InvalidMessage(e);
    }

    // Set the JMS Message ID
    if (message.nevadoPropertyExists(NevadoProperty.DisableMessageID)
        && (Boolean) message.getNevadoProperty(NevadoProperty.DisableMessageID)) {
      message.setJMSMessageID(null);
    } else if (message.getJMSMessageID() == null) {
      message.setJMSMessageID("ID:" + sqsMessage.getMessageId());
    }

    // Set the receipt handle and the destination
    message.setNevadoProperty(NevadoProperty.SQSReceiptHandle, sqsMessage.getReceiptHandle());
    message.setJMSDestination(destination);

    // Set if this is readonly (browsing)
    message.setReadOnly(readOnly);

    return message;
  }