/** * Reads a message from a destination up to some specific timeout period * * @param client The webclient * @param request * @param response * @throws ServletException * @throws IOException */ protected void doMessages( AjaxWebClient client, HttpServletRequest request, HttpServletResponse response) throws JMSException, IOException { int messages = 0; // This is a poll for any messages long timeout = getReadTimeout(request); if (LOG.isDebugEnabled()) { LOG.debug("doMessage timeout=" + timeout); } // this is non-null if we're resuming the continuation. // attributes set in AjaxListener UndeliveredAjaxMessage undelivered_message = null; Message message = null; undelivered_message = (UndeliveredAjaxMessage) request.getAttribute("undelivered_message"); if (undelivered_message != null) { message = (Message) undelivered_message.getMessage(); } synchronized (client) { List<MessageConsumer> consumers = client.getConsumers(); MessageAvailableConsumer consumer = null; if (undelivered_message != null) { consumer = (MessageAvailableConsumer) undelivered_message.getConsumer(); } if (message == null) { // Look for a message that is ready to go for (int i = 0; message == null && i < consumers.size(); i++) { consumer = (MessageAvailableConsumer) consumers.get(i); if (consumer.getAvailableListener() == null) { continue; } // Look for any available messages message = consumer.receive(10); if (LOG.isDebugEnabled()) { LOG.debug("received " + message + " from " + consumer); } } } // prepare the response response.setContentType("text/xml"); response.setHeader("Cache-Control", "no-cache"); if (message == null && client.getListener().getUndeliveredMessages().size() == 0) { Continuation continuation = ContinuationSupport.getContinuation(request); if (continuation.isExpired()) { response.setStatus(HttpServletResponse.SC_OK); StringWriter swriter = new StringWriter(); PrintWriter writer = new PrintWriter(swriter); writer.println("<ajax-response>"); writer.print("</ajax-response>"); writer.flush(); String m = swriter.toString(); response.getWriter().println(m); return; } continuation.setTimeout(timeout); continuation.suspend(); LOG.debug("Suspending continuation " + continuation); // Fetch the listeners AjaxListener listener = client.getListener(); listener.access(); // register this continuation with our listener. listener.setContinuation(continuation); return; } StringWriter swriter = new StringWriter(); PrintWriter writer = new PrintWriter(swriter); Map<MessageAvailableConsumer, String> consumerIdMap = client.getIdMap(); Map<MessageAvailableConsumer, String> consumerDestinationNameMap = client.getDestinationNameMap(); response.setStatus(HttpServletResponse.SC_OK); writer.println("<ajax-response>"); // Send any message we already have if (message != null) { String id = consumerIdMap.get(consumer); String destinationName = consumerDestinationNameMap.get(consumer); LOG.debug("sending pre-existing message"); writeMessageResponse(writer, message, id, destinationName); messages++; } // send messages buffered while continuation was unavailable. LinkedList<UndeliveredAjaxMessage> undeliveredMessages = ((AjaxListener) consumer.getAvailableListener()).getUndeliveredMessages(); LOG.debug("Send " + undeliveredMessages.size() + " unconsumed messages"); synchronized (undeliveredMessages) { for (Iterator<UndeliveredAjaxMessage> it = undeliveredMessages.iterator(); it.hasNext(); ) { messages++; UndeliveredAjaxMessage undelivered = it.next(); Message msg = (Message) undelivered.getMessage(); consumer = (MessageAvailableConsumer) undelivered.getConsumer(); String id = consumerIdMap.get(consumer); String destinationName = consumerDestinationNameMap.get(consumer); LOG.debug("sending undelivered/buffered messages"); LOG.debug("msg:" + msg + ", id:" + id + ", destinationName:" + destinationName); writeMessageResponse(writer, msg, id, destinationName); it.remove(); if (messages >= maximumMessages) { break; } } } // Send the rest of the messages for (int i = 0; i < consumers.size() && messages < maximumMessages; i++) { consumer = (MessageAvailableConsumer) consumers.get(i); if (consumer.getAvailableListener() == null) { continue; } // Look for any available messages while (messages < maximumMessages) { message = consumer.receiveNoWait(); if (message == null) { break; } messages++; String id = consumerIdMap.get(consumer); String destinationName = consumerDestinationNameMap.get(consumer); LOG.debug("sending final available messages"); writeMessageResponse(writer, message, id, destinationName); } } writer.print("</ajax-response>"); writer.flush(); String m = swriter.toString(); response.getWriter().println(m); } }
/** * Sends a message to a destination or manage subscriptions. If the the content type of the POST * is <code>application/x-www-form-urlencoded</code>, then the form parameters "destination", * "message" and "type" are used to pass a message or a subscription. If multiple messages or * subscriptions are passed in a single post, then additional parameters are shortened to "dN", * "mN" and "tN" where N is an index starting from 1. The type is either "send", "listen" or * "unlisten". For send types, the message is the text of the TextMessage, otherwise it is the ID * to be used for the subscription. If the content type is not <code> * application/x-www-form-urlencoded</code>, then the body of the post is sent as the message to a * destination that is derived from a query parameter, the URL or the default destination. * * @param request * @param response * @throws ServletException * @throws IOException */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // lets turn the HTTP post into a JMS Message AjaxWebClient client = getAjaxWebClient(request); String messageIds = ""; synchronized (client) { if (LOG.isDebugEnabled()) { LOG.debug( "POST client=" + client + " session=" + request.getSession().getId() + " clientId=" + request.getParameter("clientId") + " info=" + request.getPathInfo() + " contentType=" + request.getContentType()); // dump(request.getParameterMap()); } int messages = 0; // loop until no more messages while (true) { // Get the message parameters. Multiple messages are encoded // with more compact parameter names. String destinationName = request.getParameter(messages == 0 ? "destination" : ("d" + messages)); if (destinationName == null) { destinationName = request.getHeader("destination"); } String message = request.getParameter(messages == 0 ? "message" : ("m" + messages)); String type = request.getParameter(messages == 0 ? "type" : ("t" + messages)); if (destinationName == null || message == null || type == null) { break; } try { Destination destination = getDestination(client, request, destinationName); if (LOG.isDebugEnabled()) { LOG.debug( messages + " destination=" + destinationName + " message=" + message + " type=" + type); LOG.debug(destination + " is a " + destination.getClass().getName()); } messages++; if ("listen".equals(type)) { AjaxListener listener = client.getListener(); Map<MessageAvailableConsumer, String> consumerIdMap = client.getIdMap(); Map<MessageAvailableConsumer, String> consumerDestinationNameMap = client.getDestinationNameMap(); client.closeConsumer(destination); // drop any existing // consumer. MessageAvailableConsumer consumer = (MessageAvailableConsumer) client.getConsumer(destination, request.getHeader(WebClient.selectorName)); consumer.setAvailableListener(listener); consumerIdMap.put(consumer, message); consumerDestinationNameMap.put(consumer, destinationName); if (LOG.isDebugEnabled()) { LOG.debug("Subscribed: " + consumer + " to " + destination + " id=" + message); } } else if ("unlisten".equals(type)) { Map<MessageAvailableConsumer, String> consumerIdMap = client.getIdMap(); Map<MessageAvailableConsumer, String> consumerDestinationNameMap = client.getDestinationNameMap(); MessageAvailableConsumer consumer = (MessageAvailableConsumer) client.getConsumer(destination, request.getHeader(WebClient.selectorName)); consumer.setAvailableListener(null); consumerIdMap.remove(consumer); consumerDestinationNameMap.remove(consumer); client.closeConsumer(destination); if (LOG.isDebugEnabled()) { LOG.debug("Unsubscribed: " + consumer); } } else if ("send".equals(type)) { TextMessage text = client.getSession().createTextMessage(message); appendParametersToMessage(request, text); client.send(destination, text); messageIds += text.getJMSMessageID() + "\n"; if (LOG.isDebugEnabled()) { LOG.debug("Sent " + message + " to " + destination); } } else { LOG.warn("unknown type " + type); } } catch (JMSException e) { LOG.warn("jms", e); } } } if ("true".equals(request.getParameter("poll"))) { try { // TODO return message IDs doMessages(client, request, response); } catch (JMSException e) { throw new ServletException("JMS problem: " + e, e); } } else { // handle simple POST of a message if (request.getContentLength() != 0 && (request.getContentType() == null || !request .getContentType() .toLowerCase() .startsWith("application/x-www-form-urlencoded"))) { try { Destination destination = getDestination(client, request); String body = getPostedMessageBody(request); TextMessage message = client.getSession().createTextMessage(body); appendParametersToMessage(request, message); client.send(destination, message); if (LOG.isDebugEnabled()) { LOG.debug("Sent to destination: " + destination + " body: " + body); } messageIds += message.getJMSMessageID() + "\n"; } catch (JMSException e) { throw new ServletException(e); } } response.setContentType("text/plain"); response.setHeader("Cache-Control", "no-cache"); response.getWriter().print(messageIds); } }