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