View Javadoc

1   /*
2    * $Id: MuleReceiverServlet.java 19697 2010-09-22 18:24:28Z esteban.robles $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transport.servlet;
12  
13  import org.mule.api.MuleEvent;
14  import org.mule.api.MuleException;
15  import org.mule.api.MuleMessage;
16  import org.mule.api.endpoint.EndpointException;
17  import org.mule.api.endpoint.EndpointURI;
18  import org.mule.api.endpoint.InboundEndpoint;
19  import org.mule.api.lifecycle.InitialisationException;
20  import org.mule.api.transport.MessageReceiver;
21  import org.mule.api.transport.NoReceiverForEndpointException;
22  import org.mule.api.transport.PropertyScope;
23  import org.mule.endpoint.DynamicURIInboundEndpoint;
24  import org.mule.endpoint.MuleEndpointURI;
25  import org.mule.routing.filters.WildcardFilter;
26  import org.mule.transport.http.HttpConnector;
27  import org.mule.transport.http.HttpMessageReceiver;
28  import org.mule.transport.http.i18n.HttpMessages;
29  import org.mule.transport.service.TransportFactory;
30  import org.mule.transport.servlet.i18n.ServletMessages;
31  import org.mule.util.PropertiesUtils;
32  
33  import java.io.IOException;
34  import java.util.Map;
35  import java.util.Properties;
36  
37  import javax.servlet.ServletException;
38  import javax.servlet.http.HttpServletRequest;
39  import javax.servlet.http.HttpServletResponse;
40  
41  /**
42   * Receives Http requests via a Servlet and routes them to listeners with servlet://
43   * endpoints
44   * <p/>
45   */
46  public class MuleReceiverServlet extends AbstractReceiverServlet
47  {
48      /**
49       * Serial version
50       */
51      private static final long serialVersionUID = 6631307373079767439L;
52  
53      protected ServletConnector connector = null;
54      
55      private boolean useCachedHttpServletRequest = false;
56  
57      @Override
58      protected void doInit() throws ServletException
59      {
60          connector = getOrCreateServletConnector(getServletConfig().getInitParameter(SERVLET_CONNECTOR_NAME_PROPERTY));
61      }
62  
63      protected ServletConnector getOrCreateServletConnector(String name) throws ServletException
64      {
65          ServletConnector servletConnector;
66          if (name == null)
67          {
68              servletConnector = (ServletConnector) new TransportFactory(muleContext).getConnectorByProtocol("servlet");
69              if (servletConnector == null)
70              {
71                  servletConnector = new ServletConnector(muleContext);
72                  servletConnector.setName("_generatedServletConnector");
73                  try
74                  {
75                      muleContext.getRegistry().registerConnector(servletConnector);
76                  }
77                  catch (MuleException e)
78                  {
79                      throw new ServletException("Failed to register the ServletConnector", e);
80                  }
81              }
82          }
83          else
84          {
85              servletConnector = (ServletConnector) muleContext.getRegistry().lookupConnector(name);
86              if (servletConnector == null)
87              {
88                  throw new ServletException(ServletMessages.noServletConnectorFound(name).toString());
89              }
90          }
91          this.useCachedHttpServletRequest = servletConnector.isUseCachedHttpServletRequest();
92          return servletConnector;
93      }
94  
95      protected void setupRequestMessage(HttpServletRequest request,
96                                         MuleMessage requestMessage,
97                                         MessageReceiver receiver)
98      {
99  
100         EndpointURI uri = receiver.getEndpointURI();
101         String reqUri = request.getRequestURI();
102         requestMessage.setProperty(HttpConnector.HTTP_REQUEST_PATH_PROPERTY, reqUri, PropertyScope.INBOUND);
103 
104         String queryString = request.getQueryString();
105         if (queryString != null)
106         {
107             reqUri += "?" + queryString;
108         }
109 
110         requestMessage.setProperty(HttpConnector.HTTP_REQUEST_PROPERTY, reqUri, PropertyScope.INBOUND);
111 
112         String path;
113         if ("servlet".equals(uri.getScheme()))
114         {
115             path = HttpConnector.normalizeUrl(request.getContextPath());
116             if ("/".equals(path))
117             {
118                 path = HttpConnector.normalizeUrl(request.getServletPath());
119             }
120             else
121             {
122                 path = path + HttpConnector.normalizeUrl(request.getServletPath());
123             }
124 
125             String pathPart2 = uri.getAddress();
126 
127             if (!path.endsWith("/"))
128             {
129                 // "/foo" + "bar"
130                 path = path + HttpConnector.normalizeUrl(pathPart2);
131             }
132             else if (pathPart2.startsWith("/"))
133             {
134                 // "/foo/" + "/bar"
135                 path = path + pathPart2.substring(1);
136             }
137             else
138             {
139                 // "/foo/" + "bar"
140                 path = path + pathPart2;
141             }
142         }
143         else
144         {
145             // The Jetty transport has normal paths
146             path = HttpConnector.normalizeUrl(uri.getPath());
147         }
148 
149         requestMessage.setProperty(HttpConnector.HTTP_CONTEXT_PATH_PROPERTY, path, PropertyScope.INBOUND);
150 
151         // Call this to keep API compatability
152         setupRequestMessage(request, requestMessage);
153     }
154 
155 
156     protected void setupRequestMessage(HttpServletRequest request, MuleMessage requestMessage)
157     {
158         // template method
159     }
160     
161     // We cannot override the service method and maintain MuleRESTServletReceiver
162     // functionality. See MULE-4806.
163     
164     @Override
165     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
166         throws ServletException, IOException
167     {
168         doAllMethods(req, resp);
169     }
170     
171     @Override
172     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
173         throws ServletException, IOException
174     {
175         doAllMethods(req, resp);
176     }
177     
178     @Override
179     protected void doHead(HttpServletRequest req, HttpServletResponse resp)
180         throws ServletException, IOException
181     {
182         doAllMethods(req, resp);
183     }
184     @Override
185     protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
186         throws ServletException, IOException
187     {
188         doAllMethods(req, resp);
189     }
190 
191     @Override
192     protected void doPut(HttpServletRequest req, HttpServletResponse resp)
193         throws ServletException, IOException
194     {
195         doAllMethods(req, resp);
196     }
197     @Override
198     protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
199         throws ServletException, IOException
200     {
201         doAllMethods(req, resp);
202     }
203     @Override
204     protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
205         throws ServletException, IOException
206     {
207         doAllMethods(req, resp);
208     }
209 
210     protected void doAllMethods(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
211     {
212         try
213         {
214         	if (this.useCachedHttpServletRequest)
215             {
216                 request = new CachedHttpServletRequest(request);
217             }
218             MessageReceiver receiver = getReceiverForURI(request);
219             
220             MuleMessage requestMessage = receiver.createMuleMessage(request);
221             requestMessage.setProperty(HttpConnector.HTTP_METHOD_PROPERTY, request.getMethod(), PropertyScope.INBOUND);
222 
223             setupRequestMessage(request, requestMessage, receiver);
224 
225             MuleEvent event = routeMessage(receiver, requestMessage, request);
226             MuleMessage result = event == null ? null : event.getMessage();
227             writeResponse(response, result);
228         }
229         catch (Exception e)
230         {
231             handleException(e, ServletMessages.failedToProcessRequest().getMessage(), response);
232         }
233     }
234 
235     protected MuleEvent routeMessage(MessageReceiver receiver, MuleMessage requestMessage, HttpServletRequest request)
236             throws MuleException
237     {
238         return receiver.routeMessage(requestMessage);
239     }
240 
241     protected MessageReceiver getReceiverForURI(HttpServletRequest httpServletRequest)
242             throws EndpointException
243     {
244         String uri = getReceiverName(httpServletRequest);
245         if (uri == null)
246         {
247             throw new EndpointException(
248                     HttpMessages.unableToGetEndpointUri(httpServletRequest.getRequestURI()));
249         }
250 
251         MessageReceiver receiver = getReceivers().get(uri);
252 
253         // Lets see if the uri matches up with the last part of
254         // any of the receiver keys.
255         if (receiver == null)
256         {
257             receiver = HttpMessageReceiver.findReceiverByStem(connector.getReceivers(), uri);
258         }
259 
260         if (receiver == null)
261         {
262             receiver = matchReceiverByWildcard(uri, receiver);
263         }
264 
265         if (receiver == null)
266         {
267             throw new NoReceiverForEndpointException(uri);
268         }
269 
270         InboundEndpoint endpoint = receiver.getEndpoint();
271 
272         // Ensure that this receiver is using a dynamic (mutable) endpoint
273         if (!(endpoint instanceof DynamicURIInboundEndpoint))
274         {
275             endpoint = new DynamicURIInboundEndpoint(receiver.getEndpoint());
276             receiver.setEndpoint(endpoint);
277         }
278 
279         // Tell the dynamic endpoint about our new URL
280         //Note we don't use the servlet: prefix since we need to be dealing with the raw endpoint here
281         EndpointURI epURI = new MuleEndpointURI(getRequestUrl(httpServletRequest), muleContext);
282 
283         try
284         {
285             epURI.initialise();
286             epURI.getParams().setProperty("servlet.endpoint", "true");
287             ((DynamicURIInboundEndpoint) endpoint).setEndpointURI(epURI);
288         }
289         catch (InitialisationException e)
290         {
291             throw new EndpointException(e);
292         }
293         return receiver;
294     }
295 
296     protected MessageReceiver matchReceiverByWildcard(String uri, MessageReceiver receiver)
297     {
298         // Now match wild cards
299         for (Object key : getReceivers().keySet())
300         {
301             if (new WildcardFilter(key.toString()).accept(uri))
302             {
303                 receiver = connector.getReceivers().get(key);
304                 break;
305             }
306         }
307         return receiver;
308     }
309 
310     protected String getRequestUrl(HttpServletRequest httpServletRequest)
311     {
312         StringBuffer url = new StringBuffer();
313 
314         url.append(httpServletRequest.getScheme());
315         url.append("://");
316         url.append(httpServletRequest.getServerName());
317         url.append(":");
318         url.append(httpServletRequest.getServerPort());
319         url.append(httpServletRequest.getServletPath());
320         
321         String pathInfo = httpServletRequest.getPathInfo();
322         if (pathInfo != null)
323         {
324             url.append(pathInfo);
325         }
326         
327         String queryString = httpServletRequest.getQueryString();
328         if (queryString != null)
329         {
330             url.append("?");
331             url.append(queryString);
332         }
333         return url.toString();
334     }
335 
336     protected String getReceiverName(HttpServletRequest httpServletRequest)
337     {
338         String name = httpServletRequest.getPathInfo();
339         if (name == null)
340         {
341             name = httpServletRequest.getServletPath();
342             if (name == null)
343             {
344                 name = httpServletRequest.getParameter("endpoint");
345                 if (name == null)
346                 {
347                     Properties params = PropertiesUtils.getPropertiesFromQueryString(httpServletRequest.getQueryString());
348                     name = params.getProperty("endpoint");
349                     if (name == null)
350                     {
351                         return null;
352                     }
353                 }
354             }
355         }
356 
357         if (name.startsWith("/"))
358         {
359             name = name.substring(1);
360         }
361         return name;
362     }
363 
364     protected Map<Object, MessageReceiver> getReceivers()
365     {
366         return connector.getReceivers();
367     }
368 }