Coverage Report - org.mule.transport.servlet.ServletMuleMessageFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
ServletMuleMessageFactory
0%
0/109
0%
0/44
0
 
 1  
 /*
 2  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 3  
  * The software in this package is published under the terms of the CPAL v1.0
 4  
  * license, a copy of which has been included with this distribution in the
 5  
  * LICENSE.txt file.
 6  
  */
 7  
 package org.mule.transport.servlet;
 8  
 
 9  
 import org.mule.DefaultMuleMessage;
 10  
 import org.mule.api.MuleContext;
 11  
 import org.mule.api.MuleMessage;
 12  
 import org.mule.transport.AbstractMuleMessageFactory;
 13  
 import org.mule.transport.http.HttpConstants;
 14  
 
 15  
 import java.util.Enumeration;
 16  
 import java.util.HashMap;
 17  
 import java.util.List;
 18  
 import java.util.Map;
 19  
 
 20  
 import javax.servlet.http.HttpServletRequest;
 21  
 import javax.servlet.http.HttpSession;
 22  
 
 23  
 import org.apache.commons.collections.EnumerationUtils;
 24  
 
 25  
 public class ServletMuleMessageFactory extends AbstractMuleMessageFactory
 26  
 {
 27  
     private static final String REMOTE_ADDRESS_HEADER = "remoteAddress";
 28  
 
 29  
     public ServletMuleMessageFactory(MuleContext context)
 30  
     {
 31  0
         super(context);
 32  0
     }
 33  
 
 34  
     @Override
 35  
     protected Class<?>[] getSupportedTransportMessageTypes()
 36  
     {
 37  0
         return new Class[] { HttpServletRequest.class };
 38  
     }
 39  
 
 40  
     @Override
 41  
     protected Object extractPayload(Object transportMessage, String encoding) throws Exception
 42  
     {
 43  0
         HttpServletRequest request = (HttpServletRequest) transportMessage;
 44  
 
 45  0
         String method = request.getMethod();
 46  0
         if (HttpConstants.METHOD_GET.equalsIgnoreCase(method))
 47  
         {
 48  0
             return queryString(request);
 49  
         }
 50  
         else
 51  
         {
 52  0
             return extractPayloadFromPostRequest(request);
 53  
         }
 54  
     }
 55  
 
 56  
     protected Object extractPayloadFromPostRequest(HttpServletRequest request) throws Exception
 57  
     {
 58  
         /*
 59  
          * Servlet Spec v2.5:
 60  
          *
 61  
          * SRV.3.1.1
 62  
          * When Parameters Are Available
 63  
          *
 64  
          * The following are the conditions that must be met before post form data will
 65  
          * be populated to the parameter set:
 66  
          *
 67  
          * 1. The request is an HTTP or HTTPS request.
 68  
          * 2. The HTTP method is POST.
 69  
          * 3. The content type is application/x-www-form-urlencoded.
 70  
          * 4. The servlet has made an initial call of any of the getParameter family of meth-
 71  
          *    ods on the request object.
 72  
          *
 73  
          * If the conditions are not met and the post form data is not included in the
 74  
          * parameter set, the post data must still be available to the servlet via the request
 75  
          * object's input stream. If the conditions are met, post form data will no longer be
 76  
          * available for reading directly from the request object's input stream.
 77  
          *
 78  
          * -----------------------------------------------------------------------------------
 79  
          *
 80  
          * In plain english:if you call getInputStream on a POSTed request before you call one of
 81  
          * the getParameter* methods, you'll lose the parameters. So we touch the parameters first
 82  
          * and only then we return the input stream that will be the payload of the message.
 83  
          */
 84  0
         request.getParameterNames();
 85  
 
 86  0
         return request.getInputStream();
 87  
     }
 88  
 
 89  
     protected String queryString(HttpServletRequest request)
 90  
     {
 91  0
         StringBuilder buf = new StringBuilder(request.getRequestURI());
 92  
 
 93  0
         String queryString = request.getQueryString();
 94  0
         if (queryString != null)
 95  
         {
 96  0
             buf.append("?");
 97  0
             buf.append(queryString);
 98  
         }
 99  
 
 100  0
         return buf.toString();
 101  
     }
 102  
 
 103  
     @Override
 104  
     protected void addProperties(DefaultMuleMessage message, Object transportMessage) throws Exception
 105  
     {
 106  0
         HttpServletRequest request = (HttpServletRequest) transportMessage;
 107  
 
 108  0
         setupRequestParameters(request, message);
 109  0
         setupEncoding(request, message);
 110  0
         setupSessionId(request, message);
 111  0
         setupContentType(request, message);
 112  0
         setupCharacterEncoding(request, message);
 113  0
         setupRemoteAddress(request, message);
 114  0
         setupMessageProperties(request, message);
 115  0
     }
 116  
 
 117  
     @SuppressWarnings("unchecked")
 118  
     protected void setupRequestParameters(HttpServletRequest request, DefaultMuleMessage message)
 119  
     {
 120  0
         Enumeration<String> parameterNames = request.getParameterNames();
 121  0
         if (parameterNames != null)
 122  
         {
 123  0
             Map<String, Object> parameterProperties = new HashMap<String, Object>();
 124  0
             Map<String, Object> parameterMap = new HashMap<String, Object>();
 125  0
             while (parameterNames.hasMoreElements())
 126  
             {
 127  0
                 String name = parameterNames.nextElement();
 128  0
                 String key = ServletConnector.PARAMETER_PROPERTY_PREFIX + name;
 129  0
                 String value = request.getParameterValues(name)[0];
 130  
 
 131  0
                 parameterProperties.put(key, value);
 132  0
                 parameterMap.put(name, value);
 133  0
             }
 134  
 
 135  
             // support for the HttpRequestToParameterMap transformer: put the map of request
 136  
             // parameters under a well defined key into the message properties as well
 137  0
             parameterProperties.put(ServletConnector.PARAMETER_MAP_PROPERTY_KEY, parameterMap);
 138  
 
 139  0
             message.addInboundProperties(parameterProperties);
 140  
         }
 141  0
     }
 142  
 
 143  
     protected void setupEncoding(HttpServletRequest request, MuleMessage message)
 144  
     {
 145  0
         String contentType = request.getContentType();
 146  0
         if (contentType != null)
 147  
         {
 148  0
             int index = contentType.indexOf("charset");
 149  0
             if (index > -1)
 150  
             {
 151  0
                 int semicolonIndex = contentType.lastIndexOf(";");
 152  
                 String encoding;
 153  0
                 if (semicolonIndex > index)
 154  
                 {
 155  0
                     encoding = contentType.substring(index + 8, semicolonIndex);
 156  
                 }
 157  
                 else
 158  
                 {
 159  0
                     encoding = contentType.substring(index + 8);
 160  
                 }
 161  
                 // some stacks send quotes around the charset encoding
 162  0
                 message.setEncoding(encoding.replaceAll("\"", "").trim());
 163  
             }
 164  
         }
 165  0
     }
 166  
 
 167  
     protected void setupSessionId(HttpServletRequest request, MuleMessage message)
 168  
     {
 169  
         try
 170  
         {
 171  
             // We wrap this call as on some App Servers (Websphere) it can cause an NPE
 172  0
             HttpSession session = request.getSession(false);
 173  0
             if (session != null)
 174  
             {
 175  0
                 ((DefaultMuleMessage) message).setInboundProperty(ServletConnector.SESSION_ID_PROPERTY_KEY, session.getId());
 176  
             }
 177  
         }
 178  0
         catch (Exception e)
 179  
         {
 180  
             // C'est la vie
 181  0
         }
 182  0
     }
 183  
 
 184  
     protected void setupContentType(HttpServletRequest request, DefaultMuleMessage message)
 185  
     {
 186  0
         String contentType = request.getContentType();
 187  
 
 188  0
         Map<String, Object> properties = new HashMap<String, Object>();
 189  0
         properties.put(ServletConnector.CONTENT_TYPE_PROPERTY_KEY, contentType);
 190  
 
 191  0
         message.addInboundProperties(properties);
 192  0
     }
 193  
 
 194  
     protected void setupCharacterEncoding(HttpServletRequest request, DefaultMuleMessage message)
 195  
     {
 196  0
         String characterEncoding = request.getCharacterEncoding();
 197  
 
 198  0
         Map<String, Object> properties = new HashMap<String, Object>();
 199  0
         properties.put(ServletConnector.CHARACTER_ENCODING_PROPERTY_KEY, characterEncoding);
 200  
 
 201  0
         message.addInboundProperties(properties);
 202  0
     }
 203  
 
 204  
     protected void setupRemoteAddress(HttpServletRequest request, DefaultMuleMessage message)
 205  
     {
 206  0
         message.setInboundProperty(REMOTE_ADDRESS_HEADER, request.getRemoteAddr());
 207  0
     }
 208  
 
 209  
     protected void setupMessageProperties(HttpServletRequest request, DefaultMuleMessage message)
 210  
     {
 211  0
         Map<String, Object> messageProperties = new HashMap<String, Object>();
 212  
 
 213  0
         copyParameters(request, messageProperties);
 214  0
         copyAttributes(request, messageProperties);
 215  0
         copyHeaders(request, messageProperties);
 216  
 
 217  0
         message.addInboundProperties(messageProperties);
 218  0
     }
 219  
 
 220  
     protected void copyParameters(HttpServletRequest request, Map<String, Object> messageProperties)
 221  
     {
 222  0
         Map<?, ?> parameterMap = request.getParameterMap();
 223  0
         if (parameterMap != null && parameterMap.size() > 0)
 224  
         {
 225  0
             for (Map.Entry<?, ?> entry : parameterMap.entrySet())
 226  
             {
 227  0
                 String key = (String) entry.getKey();
 228  0
                 Object value = entry.getValue();
 229  0
                 if (value != null)
 230  
                 {
 231  0
                     if (value.getClass().isArray() && ((Object[]) value).length == 1)
 232  
                     {
 233  0
                         value = ((Object[]) value)[0];
 234  
                     }
 235  
                 }
 236  
 
 237  0
                 messageProperties.put(key, value);
 238  0
             }
 239  
         }
 240  0
     }
 241  
 
 242  
     protected void copyAttributes(HttpServletRequest request, Map<String, Object> messageProperties)
 243  
     {
 244  0
         for (Enumeration<?> e = request.getAttributeNames(); e.hasMoreElements();)
 245  
         {
 246  0
             String key = (String) e.nextElement();
 247  0
             messageProperties.put(key, request.getAttribute(key));
 248  0
         }
 249  0
     }
 250  
 
 251  
     protected void copyHeaders(HttpServletRequest request, Map<String, Object> messageProperties)
 252  
     {
 253  0
         for (Enumeration<?> e = request.getHeaderNames(); e.hasMoreElements();)
 254  
         {
 255  0
             String key = (String)e.nextElement();
 256  0
             String realKey = key;
 257  
 
 258  0
             if (key.startsWith(HttpConstants.X_PROPERTY_PREFIX))
 259  
             {
 260  0
                 realKey = key.substring(2);
 261  
             }
 262  
 
 263  
             // Workaround for containers that strip the port from the Host header.
 264  
             // This is needed so Mule components can figure out what port they're on.
 265  0
             if (HttpConstants.HEADER_HOST.equalsIgnoreCase(key))
 266  
             {
 267  0
                 realKey = HttpConstants.HEADER_HOST;
 268  
 
 269  0
                 String value = request.getHeader(key);
 270  0
                 int port = request.getLocalPort();
 271  0
                 if (!value.contains(":") && port != 80 && port != 443)
 272  
                 {
 273  0
                     value = value + ":" + port;
 274  
                 }
 275  0
                 messageProperties.put(realKey, value);
 276  0
             }
 277  
             else
 278  
             {
 279  0
                 Enumeration<?> valueEnum = request.getHeaders(key);
 280  0
                 List<?> values = EnumerationUtils.toList(valueEnum);
 281  0
                 if (values.size() > 1)
 282  
                 {
 283  0
                     messageProperties.put(realKey, values.toArray());
 284  
                 }
 285  
                 else
 286  
                 {
 287  0
                     messageProperties.put(realKey, values.get(0));
 288  
                 }
 289  
             }
 290  0
         }
 291  0
     }
 292  
 }