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.7 $
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() throws ServletException {
57          ServletConfig servletConfig = getServletConfig();
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 }