Coverage Report - org.mule.components.rest.RestServiceWrapper
 
Classes in this File Line Coverage Branch Coverage Complexity
RestServiceWrapper
0%
0/109
0%
0/52
2.217
 
 1  
 /*
 2  
  * $Id: RestServiceWrapper.java 7963 2007-08-21 08:53:15Z dirk.olmes $
 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.components.rest;
 12  
 
 13  
 import org.mule.config.i18n.CoreMessages;
 14  
 import org.mule.impl.MuleMessage;
 15  
 import org.mule.impl.endpoint.MuleEndpointURI;
 16  
 import org.mule.providers.NullPayload;
 17  
 import org.mule.routing.filters.MessagePropertyFilter;
 18  
 import org.mule.routing.filters.RegExFilter;
 19  
 import org.mule.umo.UMOEventContext;
 20  
 import org.mule.umo.UMOFilter;
 21  
 import org.mule.umo.UMOMessage;
 22  
 import org.mule.umo.endpoint.UMOEndpointURI;
 23  
 import org.mule.umo.lifecycle.Callable;
 24  
 import org.mule.umo.lifecycle.Initialisable;
 25  
 import org.mule.umo.lifecycle.InitialisationException;
 26  
 import org.mule.util.properties.MessagePropertyExtractor;
 27  
 import org.mule.util.properties.PropertyExtractor;
 28  
 
 29  
 import java.net.MalformedURLException;
 30  
 import java.net.URL;
 31  
 import java.util.HashMap;
 32  
 import java.util.Iterator;
 33  
 import java.util.List;
 34  
 import java.util.Map;
 35  
 
 36  
 import org.apache.commons.logging.Log;
 37  
 import org.apache.commons.logging.LogFactory;
 38  
 
 39  
 /**
 40  
  * This component can used to proxy REST style services as local Mule Components. It
 41  
  * can be configured with a service URL plus a number of properties that allow you to
 42  
  * configure the parameters and error conditions on the service.
 43  
  */
 44  0
 public class RestServiceWrapper implements Callable, Initialisable
 45  
 {
 46  
     public static final String REST_SERVICE_URL = "rest.service.url";
 47  
     public static final String GET = "GET";
 48  
     public static final String CONTENT_TYPE = "Content-Type";
 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 boolean urlFromMessage = false;
 59  0
     private Map requiredParams = new HashMap();
 60  0
     private Map optionalParams = new HashMap();
 61  0
     private String httpMethod = "GET";
 62  
     private List payloadParameterNames;
 63  
     private UMOFilter errorFilter;
 64  
     private String errorExpression;
 65  
 
 66  0
     private PropertyExtractor propertyExtractor = new MessagePropertyExtractor();
 67  
 
 68  
     public String getServiceUrl()
 69  
     {
 70  0
         return serviceUrl;
 71  
     }
 72  
 
 73  
     public void setServiceUrl(String serviceUrl)
 74  
     {
 75  0
         this.serviceUrl = serviceUrl;
 76  0
     }
 77  
 
 78  
     public boolean isUrlFromMessage()
 79  
     {
 80  0
         return urlFromMessage;
 81  
     }
 82  
 
 83  
     public void setUrlFromMessage(boolean urlFromMessage)
 84  
     {
 85  0
         this.urlFromMessage = urlFromMessage;
 86  0
     }
 87  
 
 88  
     public Map getRequiredParams()
 89  
     {
 90  0
         return requiredParams;
 91  
     }
 92  
 
 93  
     public void setRequiredParams(Map requiredParams)
 94  
     {
 95  0
         this.requiredParams = requiredParams;
 96  0
     }
 97  
 
 98  
     public Map getOptionalParams()
 99  
     {
 100  0
         return optionalParams;
 101  
     }
 102  
 
 103  
     public void setOptionalParams(Map optionalParams)
 104  
     {
 105  0
         this.optionalParams = optionalParams;
 106  0
     }
 107  
 
 108  
     public String getHttpMethod()
 109  
     {
 110  0
         return httpMethod;
 111  
     }
 112  
 
 113  
     public void setHttpMethod(String httpMethod)
 114  
     {
 115  0
         this.httpMethod = httpMethod;
 116  0
     }
 117  
 
 118  
     public List getPayloadParameterNames()
 119  
     {
 120  0
         return payloadParameterNames;
 121  
     }
 122  
 
 123  
     public void setPayloadParameterNames(List payloadParameterNames)
 124  
     {
 125  0
         this.payloadParameterNames = payloadParameterNames;
 126  0
     }
 127  
 
 128  
     public UMOFilter getErrorFilter()
 129  
     {
 130  0
         return errorFilter;
 131  
     }
 132  
 
 133  
     public void setErrorFilter(UMOFilter errorFilter)
 134  
     {
 135  0
         this.errorFilter = errorFilter;
 136  0
     }
 137  
 
 138  
     public String getErrorExpression()
 139  
     {
 140  0
         return errorExpression;
 141  
     }
 142  
 
 143  
     public void setErrorExpression(String errorExpression)
 144  
     {
 145  0
         this.errorExpression = errorExpression;
 146  0
     }
 147  
 
 148  
     public void initialise() throws InitialisationException
 149  
     {
 150  0
         if (serviceUrl == null && !urlFromMessage)
 151  
         {
 152  0
             throw new InitialisationException(CoreMessages.objectIsNull("serviceUrl"), this);
 153  
         }
 154  0
         else if (serviceUrl != null)
 155  
         {
 156  
             try
 157  
             {
 158  0
                 new URL(serviceUrl);
 159  
             }
 160  0
             catch (MalformedURLException e)
 161  
             {
 162  0
                 throw new InitialisationException(e, this);
 163  0
             }
 164  
         }
 165  
 
 166  0
         if (errorFilter == null)
 167  
         {
 168  0
             if (errorExpression == null)
 169  
             {
 170  
                 // We'll set a default filter that checks the return code
 171  0
                 errorFilter = new MessagePropertyFilter("http.status!=200");
 172  0
                 logger.info("Setting default error filter to MessagePropertyFilter('http.status!=200')");
 173  
             }
 174  
             else
 175  
             {
 176  0
                 errorFilter = new RegExFilter(errorExpression);
 177  
             }
 178  
         }
 179  0
     }
 180  
 
 181  
     public Object onCall(UMOEventContext eventContext) throws Exception
 182  
     {
 183  
         String tempUrl;
 184  0
         Object request = eventContext.getTransformedMessage();
 185  
         Object requestBody;
 186  0
         if (urlFromMessage)
 187  
         {
 188  0
             tempUrl = eventContext.getMessage().getStringProperty(REST_SERVICE_URL, null);
 189  0
             if (tempUrl == null)
 190  
             {
 191  0
                 throw new IllegalArgumentException(
 192  
                     CoreMessages.propertyIsNotSetOnEvent(REST_SERVICE_URL).toString());
 193  
             }
 194  
         }
 195  
         else
 196  
         {
 197  0
             tempUrl = serviceUrl;
 198  
         }
 199  0
         StringBuffer urlBuffer = new StringBuffer(tempUrl);
 200  
         
 201  0
         if (GET.equalsIgnoreCase(this.httpMethod))
 202  
         {
 203  0
             requestBody = NullPayload.getInstance();
 204  
             
 205  0
             setRESTParams(urlBuffer, eventContext.getMessage(), request, requiredParams, false, null);
 206  0
             setRESTParams(urlBuffer, eventContext.getMessage(), request, optionalParams, true, null);
 207  
         }
 208  
         else //if post
 209  
         {
 210  0
             StringBuffer requestBodyBuffer = new StringBuffer();
 211  0
             eventContext.getMessage().setProperty(CONTENT_TYPE, CONTENT_TYPE_VALUE);
 212  
             
 213  0
             setRESTParams(urlBuffer, eventContext.getMessage(), request, requiredParams, false, requestBodyBuffer);
 214  0
             setRESTParams(urlBuffer, eventContext.getMessage(), request, optionalParams, true, requestBodyBuffer);
 215  
             
 216  0
             requestBody = requestBodyBuffer.toString();
 217  
         }
 218  
 
 219  0
         tempUrl = urlBuffer.toString();
 220  0
         logger.info("Invoking REST service: " + tempUrl);
 221  
 
 222  0
         UMOEndpointURI endpointURI = new MuleEndpointURI(tempUrl);
 223  0
         eventContext.getMessage().setProperty(HTTP_METHOD, httpMethod);
 224  
         
 225  
 
 226  0
         UMOMessage result = eventContext.sendEvent(new MuleMessage(requestBody, eventContext.getMessage()),
 227  
             endpointURI);
 228  
 
 229  0
         if (isErrorPayload(result))
 230  
         {
 231  0
             handleException(new RestServiceException(
 232  
                 CoreMessages.failedToInvokeRestService(tempUrl), result), result);
 233  
         }
 234  0
         return result;
 235  
     }
 236  
     
 237  
     private String getSeparator(String url)
 238  
     {
 239  
         String sep;
 240  
 
 241  0
         if (url.indexOf("?") > -1)
 242  
         {
 243  0
             sep = "&";
 244  
         }
 245  
         else
 246  
         {
 247  0
             sep = "?";
 248  
         }
 249  
         
 250  0
         return sep;
 251  
     }
 252  
     
 253  
     private String updateSeparator(String sep)
 254  
     {
 255  0
         if (sep.compareTo("?") == 0 || sep.compareTo("") == 0)
 256  
         {
 257  0
             return ("&");
 258  
         }
 259  
         
 260  0
         return sep;
 261  
     }
 262  
 
 263  
     //if requestBodyBuffer is null, it means that the request is a GET, otherwise it is a POST and  
 264  
     //requestBodyBuffer must contain the body of the http method at the end of this function call
 265  
     private void setRESTParams(StringBuffer url, UMOMessage msg, Object body, Map args, boolean optional, StringBuffer requestBodyBuffer)
 266  
     {
 267  
         String sep;
 268  
         
 269  0
         if (requestBodyBuffer == null)
 270  
         {
 271  0
             sep = getSeparator(url.toString());
 272  
         }
 273  
         else
 274  
         {
 275  0
             sep = "";
 276  
         }
 277  
 
 278  0
         for (Iterator iterator = args.entrySet().iterator(); iterator.hasNext();)
 279  
         {
 280  0
             Map.Entry entry = (Map.Entry) iterator.next();
 281  0
             String name = (String) entry.getKey();
 282  0
             String exp = (String) entry.getValue();
 283  0
             Object value = propertyExtractor.getProperty(exp, msg);
 284  
 
 285  0
             if (value == null)
 286  
             {
 287  0
                 if (!optional)
 288  
                 {
 289  0
                     throw new IllegalArgumentException(CoreMessages.propertyIsNotSetOnEvent(exp).toString());
 290  
                 }
 291  
             }
 292  0
             else if (requestBodyBuffer != null) //implies this is a POST
 293  
             {
 294  0
                 requestBodyBuffer.append(sep);
 295  0
                 requestBodyBuffer.append(name).append('=').append(value);
 296  
             }
 297  
             else
 298  
             {
 299  0
                 url.append(sep);
 300  0
                 url.append(name).append('=').append(value);
 301  
             }
 302  
             
 303  0
             sep = updateSeparator(sep);
 304  0
         }
 305  
 
 306  0
         if (!optional && payloadParameterNames != null)
 307  
         {
 308  0
             if (body instanceof Object[])
 309  
             {
 310  0
                 Object[] requestArray = (Object[])body;
 311  0
                 for(int i=0; i<payloadParameterNames.size(); i++)
 312  
                 {
 313  0
                     if (requestBodyBuffer != null)
 314  
                     {
 315  0
                         requestBodyBuffer.append(sep).append(payloadParameterNames.get(i)).append('=').append(requestArray[i].toString());
 316  
                     }
 317  
                     else
 318  
                     {
 319  0
                         url.append(sep).append(payloadParameterNames.get(i)).append('=').append(requestArray[i].toString());
 320  
                     }
 321  
                     
 322  0
                     sep = updateSeparator(sep);
 323  
                 }
 324  0
             }
 325  
             else
 326  
             {
 327  0
                 if (payloadParameterNames.get(0) != null)
 328  
                 {
 329  0
                     if (requestBodyBuffer != null)
 330  
                     {
 331  0
                         requestBodyBuffer.append(payloadParameterNames.get(0)).append('=').append(body.toString());
 332  
                     }
 333  
                     else
 334  
                     {
 335  0
                         url.append(sep).append(payloadParameterNames.get(0)).append('=').append(body.toString());
 336  
                     }
 337  
                 } 
 338  
             }
 339  
         }
 340  0
     }
 341  
 
 342  
     protected boolean isErrorPayload(UMOMessage message)
 343  
     {
 344  0
         return errorFilter != null && errorFilter.accept(message);
 345  
     }
 346  
 
 347  
     protected void handleException(RestServiceException e, UMOMessage result) throws Exception
 348  
     {
 349  0
         throw e;
 350  
     }
 351  
 }