@Path("auto-ack/{subscription-id}")
  @DELETE
  public void deleteSubscription(
      @Context UriInfo uriInfo, @PathParam("subscription-id") String consumerId) {
    ActiveMQRestLogger.LOGGER.debug("Handling DELETE request for \"" + uriInfo.getPath() + "\"");

    internalDeleteSubscription(consumerId);
  }
  @Path("acknowledged/{consumer-id}")
  @HEAD
  public Response headAcknowledgedConsumer(
      @PathParam("consumer-id") String consumerId, @Context UriInfo uriInfo) throws Exception {
    ActiveMQRestLogger.LOGGER.debug("Handling HEAD request for \"" + uriInfo.getPath() + "\"");

    return internalHeadAcknowledgedConsumer(uriInfo, consumerId);
  }
  @Path("auto-ack/{consumer-id}")
  @GET
  public Response getAutoAckSubscription(
      @PathParam("consumer-id") String consumerId, @Context UriInfo uriInfo) throws Exception {
    ActiveMQRestLogger.LOGGER.debug("Handling GET request for \"" + uriInfo.getPath() + "\"");

    return internalHeadAutoAckSubscription(uriInfo, consumerId);
  }
 @Override
 public boolean testTimeout(String target, boolean autoShutdown) {
   QueueConsumer consumer = queueConsumers.get(target);
   Subscription subscription = (Subscription) consumer;
   if (consumer == null) return false;
   if (System.currentTimeMillis() - consumer.getLastPingTime() > subscription.getTimeout()) {
     ActiveMQRestLogger.LOGGER.shutdownRestSubscription(consumer.getId());
     if (autoShutdown) {
       shutdown(consumer);
     }
     return true;
   } else {
     return false;
   }
 }
  @POST
  public Response createSubscription(
      @FormParam("durable") @DefaultValue("false") boolean durable,
      @FormParam("autoAck") @DefaultValue("true") boolean autoAck,
      @FormParam("name") String subscriptionName,
      @FormParam("selector") String selector,
      @FormParam("delete-when-idle") Boolean destroyWhenIdle,
      @FormParam("idle-timeout") Long timeout,
      @Context UriInfo uriInfo) {
    ActiveMQRestLogger.LOGGER.debug("Handling POST request for \"" + uriInfo.getPath() + "\"");

    if (timeout == null) timeout = Long.valueOf(consumerTimeoutSeconds * 1000);
    boolean deleteWhenIdle = !durable; // default is true if non-durable
    if (destroyWhenIdle != null) deleteWhenIdle = destroyWhenIdle.booleanValue();

    if (subscriptionName != null) {
      // see if this is a reconnect
      QueueConsumer consumer = queueConsumers.get(subscriptionName);
      if (consumer != null) {
        boolean acked = consumer instanceof AcknowledgedSubscriptionResource;
        acked = !acked;
        if (acked != autoAck) {
          throw new WebApplicationException(
              Response.status(412)
                  .entity("Consumer already exists and ack-modes don't match.")
                  .type("text/plain")
                  .build());
        }
        Subscription sub = (Subscription) consumer;
        if (sub.isDurable() != durable) {
          throw new WebApplicationException(
              Response.status(412)
                  .entity("Consumer already exists and durability doesn't match.")
                  .type("text/plain")
                  .build());
        }
        Response.ResponseBuilder builder = Response.noContent();
        String pathToPullSubscriptions = uriInfo.getMatchedURIs().get(0);
        if (autoAck) {
          headAutoAckSubscriptionResponse(uriInfo, consumer, builder, pathToPullSubscriptions);
          consumer.setSessionLink(
              builder, uriInfo, pathToPullSubscriptions + "/auto-ack/" + consumer.getId());
        } else {
          headAcknowledgedConsumerResponse(uriInfo, (AcknowledgedQueueConsumer) consumer, builder);
          consumer.setSessionLink(
              builder, uriInfo, pathToPullSubscriptions + "/acknowledged/" + consumer.getId());
        }
        return builder.build();
      }
    } else {
      subscriptionName = generateSubscriptionName();
    }
    ClientSession session = null;
    try {
      // if this is not a reconnect, create the subscription queue
      if (!subscriptionExists(subscriptionName)) {
        session = sessionFactory.createSession();

        if (durable) {
          session.createQueue(destination, subscriptionName, true);
        } else {
          session.createTemporaryQueue(destination, subscriptionName);
        }
      }
      QueueConsumer consumer =
          createConsumer(durable, autoAck, subscriptionName, selector, timeout, deleteWhenIdle);
      queueConsumers.put(consumer.getId(), consumer);
      serviceManager.getTimeoutTask().add(this, consumer.getId());

      UriBuilder location = uriInfo.getAbsolutePathBuilder();
      if (autoAck) location.path("auto-ack");
      else location.path("acknowledged");
      location.path(consumer.getId());
      Response.ResponseBuilder builder = Response.created(location.build());
      if (autoAck) {
        QueueConsumer.setConsumeNextLink(
            serviceManager.getLinkStrategy(),
            builder,
            uriInfo,
            uriInfo.getMatchedURIs().get(0) + "/auto-ack/" + consumer.getId(),
            "-1");
      } else {
        AcknowledgedQueueConsumer.setAcknowledgeNextLink(
            serviceManager.getLinkStrategy(),
            builder,
            uriInfo,
            uriInfo.getMatchedURIs().get(0) + "/acknowledged/" + consumer.getId(),
            "-1");
      }
      return builder.build();

    } catch (ActiveMQException e) {
      throw new RuntimeException(e);
    } finally {
      if (session != null) {
        try {
          session.close();
        } catch (ActiveMQException e) {
        }
      }
    }
  }
  @Override
  public boolean push(ClientMessage message) {
    ActiveMQRestLogger.LOGGER.debug("Pushing " + message);
    String uri = createUri(message);
    for (int i = 0; i < registration.getMaxRetries(); i++) {
      long wait = registration.getRetryWaitMillis();
      System.out.println("Creating request from " + uri);
      ClientRequest request = executor.createRequest(uri);
      request.followRedirects(false);
      ActiveMQRestLogger.LOGGER.debug("Created request " + request);

      for (XmlHttpHeader header : registration.getHeaders()) {
        ActiveMQRestLogger.LOGGER.debug(
            "Setting XmlHttpHeader: " + header.getName() + "=" + header.getValue());
        request.header(header.getName(), header.getValue());
      }
      HttpMessageHelper.buildMessage(message, request, contentType, jmsOptions);
      ClientResponse<?> res = null;
      try {
        ActiveMQRestLogger.LOGGER.debug(method + " " + uri);
        res = request.httpMethod(method);
        int status = res.getStatus();
        ActiveMQRestLogger.LOGGER.debug("Status of push: " + status);
        if (status == 503) {
          String retryAfter = res.getStringHeaders().getFirst("Retry-After");
          if (retryAfter != null) {
            wait = Long.parseLong(retryAfter) * 1000;
          }
        } else if (status == 307) {
          uri = res.getLocation().toString();
          wait = 0;
        } else if ((status >= 200 && status < 299) || status == 303 || status == 304) {
          ActiveMQRestLogger.LOGGER.debug("Success");
          return true;
        } else if (status >= 400) {
          switch (status) {
            case 400: // these usually mean the message you are trying to send is crap, let dead
                      // letter logic take over
            case 411:
            case 412:
            case 413:
            case 414:
            case 415:
            case 416:
              throw new RuntimeException(
                  "Something is wrong with the message, status returned: "
                      + status
                      + " for push registration of URI: "
                      + uri);
            case 401: // might as well consider these critical failures and abort.  Immediately
                      // signal to disable push registration depending on config
            case 402:
            case 403:
            case 405:
            case 406:
            case 407:
            case 417:
            case 505:
              return false;
            case 404: // request timeout, gone, and not found treat as a retry
            case 408:
            case 409:
            case 410:
              break;
            default: // all 50x requests just retry (except 505)
              break;
          }
        }
      } catch (Exception e) {
        ActiveMQRestLogger.LOGGER.debug("failed to push message to " + uri, e);
        e.printStackTrace();
        return false;
      } finally {
        if (res != null) res.releaseConnection();
      }
      try {
        if (wait > 0) Thread.sleep(wait);
      } catch (InterruptedException e) {
        throw new RuntimeException("Interrupted");
      }
    }
    return false;
  }