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