View Javadoc

    1   /***
    2    *
    3    * Copyright 2004 Protique Ltd
    4    *
    5    * Licensed under the Apache License, Version 2.0 (the "License");
    6    * you may not use this file except in compliance with the License.
    7    * You may obtain a copy of the License at
    8    *
    9    * http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   **/
    18
    19  package org.codehaus.activemq.web;
    20
    21  import org.apache.commons.logging.Log;
    22  import org.apache.commons.logging.LogFactory;
    23  import org.codehaus.activemq.message.ActiveMQDestination;
    24
    25  import javax.jms.Destination;
    26  import javax.jms.JMSException;
    27  import javax.jms.Message;
    28  import javax.jms.MessageConsumer;
    29  import javax.jms.ObjectMessage;
    30  import javax.jms.TextMessage;
    31  import javax.servlet.ServletConfig;
    32  import javax.servlet.ServletException;
    33  import javax.servlet.http.HttpServletRequest;
    34  import javax.servlet.http.HttpServletResponse;
    35  import java.io.IOException;
    36
    37  /***
    38   * A servlet for sending and receiving messages to/from JMS destinations
    39   * using HTTP POST for sending and HTTP GET for receiving.
    40   * <p/>
    41   * You can specify the destination and whether it is a topic or queue
    42   * via configuration details on the servlet or as request parameters.
    43   * <p/>
    44   * For reading messages you can specify a readTimeout parameter to determine
    45   * how long the servlet should block for.
    46   *
    47   * @version $Revision: 1.6 $
    48   */
    49  public class MessageServlet extends MessageServletSupport {
    50      private static final Log log = LogFactory.getLog(MessageServlet.class);
    51
    52      private String readTimeoutParameter = "readTimeout";
    53      private long defaultReadTimeout = -1;
    54      private long maximumReadTimeout = 30000;
    55
    56      public void init(ServletConfig servletConfig) throws ServletException {
    57          super.init(servletConfig);
    58          String name = servletConfig.getInitParameter("defaultReadTimeout");
    59          if (name != null) {
    60              defaultReadTimeout = asLong(name);
    61          }
    62          name = servletConfig.getInitParameter("maximumReadTimeout");
    63          if (name != null) {
    64              maximumReadTimeout = asLong(name);
    65          }
    66      }
    67
    68      /***
    69       * Sends a message to a destination
    70       *
    71       * @param request
    72       * @param response
    73       * @throws ServletException
    74       * @throws IOException
    75       */
    76      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    77          // lets turn the HTTP post into a JMS Message
    78          try {
    79              WebClient client = getWebClient(request);
    80
    81              String text = getPostedMessageBody(request);
    82
    83              // lets create the destination from the URI?
    84              Destination destination = getDestination(client, request);
    85
    86              log.info("Sending message to: " + ActiveMQDestination.inspect(destination) + " with text: " + text);
    87
    88              TextMessage message = client.getSession().createTextMessage(text);
    89              appendParametersToMessage(request, message);
    90              client.send(destination, message);
    91
    92              // lets return a unique URI for reliable messaging
    93              response.setHeader("messageID", message.getJMSMessageID());
    94              response.setStatus(HttpServletResponse.SC_OK);
    95          }
    96          catch (JMSException e) {
    97              throw new ServletException("Could not post JMS message: " + e, e);
    98          }
    99      }
    100
    101     /***
    102      * Reads a message from a destination up to some specific timeout period
    103      *
    104      * @param request
    105      * @param response
    106      * @throws ServletException
    107      * @throws IOException
    108      */
    109     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    110         try {
    111             WebClient client = getWebClient(request);
    112
    113             // lets create the destination from the URI?
    114             Destination destination = getDestination(client, request);
    115
    116             long timeout = getReadTimeout(request);
    117
    118             log.info("Receiving message from: " + ActiveMQDestination.inspect(destination) + " with timeout: " + timeout);
    119
    120             MessageConsumer consumer = client.getConsumer(destination);
    121
    122             Message message = null;
    123             // ensure that only one thread uses the consumer at once
    124             synchronized (consumer) {
    125                 if (timeout == 0) {
    126                     message = consumer.receiveNoWait();
    127                 }
    128                 else {
    129                     message = consumer.receive(timeout);
    130                 }
    131             }
    132
    133             log.info("HTTP GET servlet done! message: " + message);
    134
    135             sendMessageResponse(request, response, message);
    136         }
    137         catch (JMSException e) {
    138             throw new ServletException("Could not post JMS message: " + e, e);
    139         }
    140
    141     }
    142
    143     /***
    144      * Supports a HTTP DELETE to be equivlanent of consuming a message from a queue
    145      */
    146     protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    147         try {
    148             WebClient client = getWebClient(request);
    149
    150             // lets create the destination from the URI?
    151             Destination destination = getDestination(client, request);
    152
    153             MessageConsumer consumer = client.getConsumer(destination);
    154
    155             Message message = null;
    156             // ensure that only one thread uses the consumer at once
    157             synchronized (consumer) {
    158                 message = consumer.receiveNoWait();
    159             }
    160
    161             sendMessageResponse(request, response, message);
    162         }
    163         catch (JMSException e) {
    164             throw new ServletException("Could not post JMS message: " + e, e);
    165         }
    166     }
    167
    168     protected void sendMessageResponse(HttpServletRequest request, HttpServletResponse response, Message message) throws JMSException, IOException {
    169         if (message == null) {
    170             response.setStatus(HttpServletResponse.SC_NO_CONTENT);
    171         }
    172         else {
    173             String type = getContentType(request);
    174             if (type != null) {
    175                 response.setContentType(type);
    176             }
    177             setResponseHeaders(response, message);
    178             if (message instanceof TextMessage) {
    179                 TextMessage textMsg = (TextMessage) message;
    180                 response.getWriter().print(textMsg.getText());
    181             }
    182             else if (message instanceof ObjectMessage) {
    183                 ObjectMessage objectMsg = (ObjectMessage) message;
    184                 Object object = objectMsg.getObject();
    185                 response.getWriter().print(object.toString());
    186             }
    187             response.setStatus(HttpServletResponse.SC_OK);
    188         }
    189     }
    190
    191     protected String getContentType(HttpServletRequest request) {
    192         /*
    193         log("Params: " + request.getParameterMap());
    194         Enumeration iter = request.getHeaderNames();
    195         while (iter.hasMoreElements()) {
    196             String name = (String) iter.nextElement();
    197             log("Header: " + name + " = " + request.getHeader(name));
    198         }
    199         */
    200         String value = request.getParameter("xml");
    201         if (value != null && "true".equalsIgnoreCase(value)) {
    202             return "text/xml";
    203         }
    204         return null;
    205     }
    206
    207     protected void setResponseHeaders(HttpServletResponse response, Message message) throws JMSException {
    208         response.setHeader("destination", message.getJMSDestination().toString());
    209         response.setHeader("id", message.getJMSMessageID());
    210     }
    211
    212     /***
    213      * @return the timeout value for read requests which is always >= 0
    214      *         and <= maximumReadTimeout to avoid DoS attacks
    215      */
    216     protected long getReadTimeout(HttpServletRequest request) {
    217         long answer = defaultReadTimeout;
    218
    219         String name = request.getParameter(readTimeoutParameter);
    220         if (name != null) {
    221             answer = asLong(name);
    222         }
    223         if (answer < 0 || answer > maximumReadTimeout) {
    224             answer = maximumReadTimeout;
    225         }
    226         return answer;
    227     }
    228
    229 }