Coverage Report - org.mule.transport.http.components.RestServiceWrapper
 
Classes in this File Line Coverage Branch Coverage Complexity
RestServiceWrapper
0%
0/110
0%
0/54
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.http.components;
 8  
 
 9  
 import org.mule.DefaultMuleEventContext;
 10  
 import org.mule.DefaultMuleMessage;
 11  
 import org.mule.MessageExchangePattern;
 12  
 import org.mule.api.MuleEvent;
 13  
 import org.mule.api.MuleEventContext;
 14  
 import org.mule.api.MuleMessage;
 15  
 import org.mule.api.endpoint.EndpointBuilder;
 16  
 import org.mule.api.endpoint.OutboundEndpoint;
 17  
 import org.mule.api.expression.ExpressionEvaluator;
 18  
 import org.mule.api.expression.RequiredValueException;
 19  
 import org.mule.api.lifecycle.InitialisationException;
 20  
 import org.mule.api.routing.filter.Filter;
 21  
 import org.mule.component.AbstractComponent;
 22  
 import org.mule.config.i18n.CoreMessages;
 23  
 import org.mule.endpoint.EndpointURIEndpointBuilder;
 24  
 import org.mule.routing.filters.ExpressionFilter;
 25  
 import org.mule.transport.NullPayload;
 26  
 import org.mule.transport.http.HttpConnector;
 27  
 import org.mule.transport.http.HttpConstants;
 28  
 import org.mule.util.StringUtils;
 29  
 
 30  
 import java.net.MalformedURLException;
 31  
 import java.net.URL;
 32  
 import java.util.HashMap;
 33  
 import java.util.Iterator;
 34  
 import java.util.List;
 35  
 import java.util.Map;
 36  
 
 37  
 import org.apache.commons.logging.Log;
 38  
 import org.apache.commons.logging.LogFactory;
 39  
 
 40  
 /**
 41  
  * This service can used to proxy REST style services as local Mule Components. It
 42  
  * can be configured with a service URL plus a number of properties that allow you to
 43  
  * configure the parameters and error conditions on the service.
 44  
  */
 45  0
 public class RestServiceWrapper extends AbstractComponent
 46  
 {
 47  
     public static final String DELETE = HttpConstants.METHOD_DELETE;
 48  
     public static final String GET = HttpConstants.METHOD_GET;
 49  
     public static final String CONTENT_TYPE_VALUE = "application/x-www-form-urlencoded";
 50  
     public static final String HTTP_METHOD = "http.method";
 51  
 
 52  
     /**
 53  
      * logger used by this class
 54  
      */
 55  0
     protected transient Log logger = LogFactory.getLog(getClass());
 56  
 
 57  
     private String serviceUrl;
 58  0
     private Map requiredParams = new HashMap();
 59  0
     private Map optionalParams = new HashMap();
 60  0
     private String httpMethod = GET;
 61  
     private List payloadParameterNames;
 62  
     private Filter errorFilter;
 63  
 
 64  
     public String getServiceUrl()
 65  
     {
 66  0
         return serviceUrl;
 67  
     }
 68  
 
 69  
     public void setServiceUrl(String serviceUrl)
 70  
     {
 71  0
         this.serviceUrl = serviceUrl;
 72  0
     }
 73  
 
 74  
     public Map getRequiredParams()
 75  
     {
 76  0
         return requiredParams;
 77  
     }
 78  
 
 79  
     /**
 80  
      * Required params that are pulled from the message. If these params don't exist
 81  
      * the call will fail Note that you can use
 82  
      * {@link org.mule.api.expression.ExpressionEvaluator} expressions such as
 83  
      * xpath, header, xquery, etc
 84  
      *
 85  
      * @param requiredParams
 86  
      */
 87  
     public void setRequiredParams(Map requiredParams)
 88  
     {
 89  0
         this.requiredParams = requiredParams;
 90  0
     }
 91  
 
 92  
     /**
 93  
      * Optional params that are pulled from the message. If these params don't exist
 94  
      * execution will continue. Note that you can use {@link ExpressionEvaluator}
 95  
      * expressions such as xpath, header, xquery, etc
 96  
      */
 97  
     public Map getOptionalParams()
 98  
     {
 99  0
         return optionalParams;
 100  
     }
 101  
 
 102  
     public void setOptionalParams(Map optionalParams)
 103  
     {
 104  0
         this.optionalParams = optionalParams;
 105  0
     }
 106  
 
 107  
     public String getHttpMethod()
 108  
     {
 109  0
         return httpMethod;
 110  
     }
 111  
 
 112  
     public void setHttpMethod(String httpMethod)
 113  
     {
 114  0
         this.httpMethod = httpMethod;
 115  0
     }
 116  
 
 117  
     public List getPayloadParameterNames()
 118  
     {
 119  0
         return payloadParameterNames;
 120  
     }
 121  
 
 122  
     public void setPayloadParameterNames(List payloadParameterNames)
 123  
     {
 124  0
         this.payloadParameterNames = payloadParameterNames;
 125  0
     }
 126  
 
 127  
     public Filter getFilter()
 128  
     {
 129  0
         return errorFilter;
 130  
     }
 131  
 
 132  
     public void setFilter(Filter errorFilter)
 133  
     {
 134  0
         this.errorFilter = errorFilter;
 135  0
     }
 136  
 
 137  
     @Override
 138  
     protected void doInitialise() throws InitialisationException
 139  
     {
 140  0
         if (serviceUrl == null)
 141  
         {
 142  0
             throw new InitialisationException(CoreMessages.objectIsNull("serviceUrl"), this);
 143  
         }
 144  0
         else if (!muleContext.getExpressionManager().isExpression(serviceUrl))
 145  
         {
 146  
             try
 147  
             {
 148  0
                 new URL(serviceUrl);
 149  
             }
 150  0
             catch (MalformedURLException e)
 151  
             {
 152  0
                 throw new InitialisationException(e, this);
 153  0
             }
 154  
         }
 155  
 
 156  0
         if (errorFilter == null)
 157  
         {
 158  
             // We'll set a default filter that checks the return code
 159  0
             errorFilter = new ExpressionFilter("#[header:INBOUND:http.status!=200]");
 160  0
             logger.info("Setting default error filter to ExpressionFilter('#[header:INBOUND:http.status!=200]')");
 161  
         }
 162  0
     }
 163  
 
 164  
     @Override
 165  
     public Object doInvoke(MuleEvent event) throws Exception
 166  
     {
 167  
         Object requestBody;
 168  
 
 169  0
         Object request = event.getMessage().getPayload();
 170  0
         String tempUrl = serviceUrl;
 171  
         MuleMessage result;
 172  0
         if (muleContext.getExpressionManager().isExpression(serviceUrl))
 173  
         {
 174  0
             muleContext.getExpressionManager().validateExpression(serviceUrl);
 175  0
             tempUrl = muleContext.getExpressionManager().parse(serviceUrl, event.getMessage(), true);
 176  
         }
 177  
 
 178  0
         StringBuffer urlBuffer = new StringBuffer(tempUrl);
 179  
 
 180  0
         if (GET.equalsIgnoreCase(this.httpMethod) || DELETE.equalsIgnoreCase(this.httpMethod))
 181  
         {
 182  0
             requestBody = NullPayload.getInstance();
 183  
 
 184  0
             setRESTParams(urlBuffer, event.getMessage(), request, requiredParams, false, null);
 185  0
             setRESTParams(urlBuffer, event.getMessage(), request, optionalParams, true, null);
 186  
         }
 187  
         // if post
 188  
         else
 189  
         {
 190  0
             if (event.getMessage().getOutboundProperty(HttpConstants.HEADER_CONTENT_TYPE) == null)
 191  
             {
 192  0
                 event.getMessage().setOutboundProperty(HttpConstants.HEADER_CONTENT_TYPE, CONTENT_TYPE_VALUE);
 193  
             }
 194  
 
 195  0
             StringBuffer requestBodyBuffer = new StringBuffer();
 196  0
             setRESTParams(urlBuffer, event.getMessage(), request, requiredParams, false, requestBodyBuffer);
 197  0
             setRESTParams(urlBuffer, event.getMessage(), request, optionalParams, true, requestBodyBuffer);
 198  0
             requestBody = requestBodyBuffer.toString();
 199  
         }
 200  
 
 201  0
         tempUrl = urlBuffer.toString();
 202  0
         logger.info("Invoking REST service: " + tempUrl);
 203  
 
 204  0
         event.getMessage().setOutboundProperty(HttpConnector.HTTP_METHOD_PROPERTY, httpMethod);
 205  
 
 206  0
         EndpointBuilder endpointBuilder = new EndpointURIEndpointBuilder(tempUrl, muleContext);
 207  0
         endpointBuilder.setExchangePattern(MessageExchangePattern.REQUEST_RESPONSE);
 208  0
         OutboundEndpoint outboundEndpoint = endpointBuilder.buildOutboundEndpoint();
 209  
 
 210  0
         MuleEventContext eventContext = new DefaultMuleEventContext(event);
 211  0
         result = eventContext.sendEvent(
 212  
             new DefaultMuleMessage(requestBody, event.getMessage(), muleContext), outboundEndpoint);
 213  0
         if (isErrorPayload(result))
 214  
         {
 215  0
             handleException(new RestServiceException(CoreMessages.failedToInvokeRestService(tempUrl),
 216  
                 event), result);
 217  
         }
 218  
 
 219  0
         return result;
 220  
     }
 221  
 
 222  
     private String getSeparator(String url)
 223  
     {
 224  
         String sep;
 225  
 
 226  0
         if (url.indexOf("?") > -1)
 227  
         {
 228  0
             sep = "&";
 229  
         }
 230  
         else
 231  
         {
 232  0
             sep = "?";
 233  
         }
 234  
 
 235  0
         return sep;
 236  
     }
 237  
 
 238  
     private String updateSeparator(String sep)
 239  
     {
 240  0
         if (sep.compareTo("?") == 0 || sep.compareTo("") == 0)
 241  
         {
 242  0
             return ("&");
 243  
         }
 244  
 
 245  0
         return sep;
 246  
     }
 247  
 
 248  
     // if requestBodyBuffer is null, it means that the request is a GET, otherwise it
 249  
     // is a POST and
 250  
     // requestBodyBuffer must contain the body of the http method at the end of this
 251  
     // function call
 252  
     private void setRESTParams(StringBuffer url,
 253  
                                MuleMessage msg,
 254  
                                Object body,
 255  
                                Map args,
 256  
                                boolean optional,
 257  
                                StringBuffer requestBodyBuffer)
 258  
     {
 259  
         String sep;
 260  
 
 261  0
         if (requestBodyBuffer == null)
 262  
         {
 263  0
             sep = getSeparator(url.toString());
 264  
         }
 265  0
         else if(requestBodyBuffer.length() > 0)
 266  
         {
 267  0
             sep = "&";
 268  
         }
 269  
         else
 270  
         {
 271  0
             sep = StringUtils.EMPTY;
 272  
         }
 273  
 
 274  0
         for (Iterator iterator = args.entrySet().iterator(); iterator.hasNext();)
 275  
         {
 276  0
             Map.Entry entry = (Map.Entry) iterator.next();
 277  0
             String name = (String) entry.getKey();
 278  0
             String exp = (String) entry.getValue();
 279  0
             Object value = null;
 280  
 
 281  0
             if (muleContext.getExpressionManager().isExpression(exp))
 282  
             {
 283  0
                 muleContext.getExpressionManager().validateExpression(exp);
 284  
                 try
 285  
                 {
 286  0
                     value = muleContext.getExpressionManager().evaluate(exp, msg);
 287  
                 }
 288  0
                 catch (RequiredValueException e)
 289  
                 {
 290  
                     //ignore
 291  0
                 }
 292  
             }
 293  
             else
 294  
             {
 295  0
                 value = exp;
 296  
             }
 297  
 
 298  0
             if (value == null)
 299  
             {
 300  0
                 if (!optional)
 301  
                 {
 302  0
                     throw new IllegalArgumentException(CoreMessages.propertyIsNotSetOnEvent(exp).toString());
 303  
                 }
 304  
             }
 305  0
             else if (requestBodyBuffer != null) // implies this is a POST
 306  
             {
 307  0
                 requestBodyBuffer.append(sep);
 308  0
                 requestBodyBuffer.append(name).append('=').append(value);
 309  
             }
 310  
             else
 311  
             {
 312  0
                 url.append(sep);
 313  0
                 url.append(name).append('=').append(value);
 314  
             }
 315  
 
 316  0
             sep = updateSeparator(sep);
 317  0
         }
 318  
 
 319  0
         if (!optional && payloadParameterNames != null)
 320  
         {
 321  0
             if (body instanceof Object[])
 322  
             {
 323  0
                 Object[] requestArray = (Object[]) body;
 324  0
                 for (int i = 0; i < payloadParameterNames.size(); i++)
 325  
                 {
 326  0
                     if (requestBodyBuffer != null)
 327  
                     {
 328  0
                         requestBodyBuffer.append(sep).append(payloadParameterNames.get(i)).append('=').append(
 329  
                                 requestArray[i].toString());
 330  
                     }
 331  
                     else
 332  
                     {
 333  0
                         url.append(sep).append(payloadParameterNames.get(i)).append('=').append(
 334  
                                 requestArray[i].toString());
 335  
                     }
 336  
 
 337  0
                     sep = updateSeparator(sep);
 338  
                 }
 339  0
             }
 340  
             else
 341  
             {
 342  0
                 if (payloadParameterNames.get(0) != null)
 343  
                 {
 344  0
                     if (requestBodyBuffer != null)
 345  
                     {
 346  0
                         requestBodyBuffer.append(payloadParameterNames.get(0)).append('=').append(body.toString());
 347  
                     }
 348  
                     else
 349  
                     {
 350  0
                         url.append(sep).append(payloadParameterNames.get(0)).append('=').append(body.toString());
 351  
                     }
 352  
                 }
 353  
             }
 354  
         }
 355  0
     }
 356  
 
 357  
     protected boolean isErrorPayload(MuleMessage message)
 358  
     {
 359  0
         return errorFilter != null && errorFilter.accept(message);
 360  
     }
 361  
 
 362  
     protected void handleException(RestServiceException e, MuleMessage result) throws Exception
 363  
     {
 364  0
         throw e;
 365  
     }
 366  
 
 367  
 }