1
2
3
4
5
6
7
8
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
41
42
43
44 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
54
55 protected transient Log logger = LogFactory.getLog(getClass());
56
57 private String serviceUrl;
58 private boolean urlFromMessage = false;
59 private Map requiredParams = new HashMap();
60 private Map optionalParams = new HashMap();
61 private String httpMethod = "GET";
62 private List payloadParameterNames;
63 private UMOFilter errorFilter;
64 private String errorExpression;
65
66 private PropertyExtractor propertyExtractor = new MessagePropertyExtractor();
67
68 public String getServiceUrl()
69 {
70 return serviceUrl;
71 }
72
73 public void setServiceUrl(String serviceUrl)
74 {
75 this.serviceUrl = serviceUrl;
76 }
77
78 public boolean isUrlFromMessage()
79 {
80 return urlFromMessage;
81 }
82
83 public void setUrlFromMessage(boolean urlFromMessage)
84 {
85 this.urlFromMessage = urlFromMessage;
86 }
87
88 public Map getRequiredParams()
89 {
90 return requiredParams;
91 }
92
93 public void setRequiredParams(Map requiredParams)
94 {
95 this.requiredParams = requiredParams;
96 }
97
98 public Map getOptionalParams()
99 {
100 return optionalParams;
101 }
102
103 public void setOptionalParams(Map optionalParams)
104 {
105 this.optionalParams = optionalParams;
106 }
107
108 public String getHttpMethod()
109 {
110 return httpMethod;
111 }
112
113 public void setHttpMethod(String httpMethod)
114 {
115 this.httpMethod = httpMethod;
116 }
117
118 public List getPayloadParameterNames()
119 {
120 return payloadParameterNames;
121 }
122
123 public void setPayloadParameterNames(List payloadParameterNames)
124 {
125 this.payloadParameterNames = payloadParameterNames;
126 }
127
128 public UMOFilter getErrorFilter()
129 {
130 return errorFilter;
131 }
132
133 public void setErrorFilter(UMOFilter errorFilter)
134 {
135 this.errorFilter = errorFilter;
136 }
137
138 public String getErrorExpression()
139 {
140 return errorExpression;
141 }
142
143 public void setErrorExpression(String errorExpression)
144 {
145 this.errorExpression = errorExpression;
146 }
147
148 public void initialise() throws InitialisationException
149 {
150 if (serviceUrl == null && !urlFromMessage)
151 {
152 throw new InitialisationException(CoreMessages.objectIsNull("serviceUrl"), this);
153 }
154 else if (serviceUrl != null)
155 {
156 try
157 {
158 new URL(serviceUrl);
159 }
160 catch (MalformedURLException e)
161 {
162 throw new InitialisationException(e, this);
163 }
164 }
165
166 if (errorFilter == null)
167 {
168 if (errorExpression == null)
169 {
170
171 errorFilter = new MessagePropertyFilter("http.status!=200");
172 logger.info("Setting default error filter to MessagePropertyFilter('http.status!=200')");
173 }
174 else
175 {
176 errorFilter = new RegExFilter(errorExpression);
177 }
178 }
179 }
180
181 public Object onCall(UMOEventContext eventContext) throws Exception
182 {
183 String tempUrl;
184 Object request = eventContext.getTransformedMessage();
185 Object requestBody;
186 if (urlFromMessage)
187 {
188 tempUrl = eventContext.getMessage().getStringProperty(REST_SERVICE_URL, null);
189 if (tempUrl == null)
190 {
191 throw new IllegalArgumentException(
192 CoreMessages.propertyIsNotSetOnEvent(REST_SERVICE_URL).toString());
193 }
194 }
195 else
196 {
197 tempUrl = serviceUrl;
198 }
199 StringBuffer urlBuffer = new StringBuffer(tempUrl);
200
201 if (this.httpMethod.compareToIgnoreCase(GET) == 0)
202 {
203 requestBody = NullPayload.getInstance();
204
205 setRESTParams(urlBuffer, eventContext.getMessage(), request, requiredParams, false, null);
206 setRESTParams(urlBuffer, eventContext.getMessage(), request, optionalParams, true, null);
207 }
208 else
209 {
210 StringBuffer requestBodyBuffer = new StringBuffer();
211 eventContext.getMessage().setProperty(CONTENT_TYPE, CONTENT_TYPE_VALUE);
212
213 setRESTParams(urlBuffer, eventContext.getMessage(), request, requiredParams, false, requestBodyBuffer);
214 setRESTParams(urlBuffer, eventContext.getMessage(), request, optionalParams, true, requestBodyBuffer);
215
216 requestBody = requestBodyBuffer.toString();
217 }
218
219 tempUrl = urlBuffer.toString();
220 logger.info("Invoking REST service: " + tempUrl);
221
222 UMOEndpointURI endpointURI = new MuleEndpointURI(tempUrl);
223 eventContext.getMessage().setProperty(HTTP_METHOD, httpMethod);
224
225
226 UMOMessage result = eventContext.sendEvent(new MuleMessage(requestBody, eventContext.getMessage()),
227 endpointURI);
228
229 if (isErrorPayload(result))
230 {
231 handleException(new RestServiceException(
232 CoreMessages.failedToInvokeRestService(tempUrl), result), result);
233 }
234 return result;
235 }
236
237 private String getSeparator(String url)
238 {
239 String sep;
240
241 if (url.indexOf("?") > -1)
242 {
243 sep = "&";
244 }
245 else
246 {
247 sep = "?";
248 }
249
250 return sep;
251 }
252
253 private String updateSeparator(String sep)
254 {
255 if (sep.compareTo("?") == 0 || sep.compareTo("") == 0)
256 {
257 return ("&");
258 }
259
260 return sep;
261 }
262
263
264
265 private void setRESTParams(StringBuffer url, UMOMessage msg, Object body, Map args, boolean optional, StringBuffer requestBodyBuffer)
266 {
267 String sep;
268
269 if (requestBodyBuffer == null)
270 {
271 sep = getSeparator(url.toString());
272 }
273 else
274 {
275 sep = "";
276 }
277
278 for (Iterator iterator = args.entrySet().iterator(); iterator.hasNext();)
279 {
280 Map.Entry entry = (Map.Entry) iterator.next();
281 String name = (String) entry.getKey();
282 String exp = (String) entry.getValue();
283 Object value = propertyExtractor.getProperty(exp, msg);
284
285 if (value == null)
286 {
287 if (!optional)
288 {
289 throw new IllegalArgumentException(CoreMessages.propertyIsNotSetOnEvent(exp).toString());
290 }
291 }
292 else if (requestBodyBuffer != null)
293 {
294 requestBodyBuffer.append(sep);
295 requestBodyBuffer.append(name).append('=').append(value);
296 }
297 else
298 {
299 url.append(sep);
300 url.append(name).append('=').append(value);
301 }
302
303 sep = updateSeparator(sep);
304 }
305
306 if (!optional && payloadParameterNames != null)
307 {
308 if (body instanceof Object[])
309 {
310 Object[] requestArray = (Object[])body;
311 for(int i=0; i<payloadParameterNames.size(); i++)
312 {
313 if (requestBodyBuffer != null)
314 {
315 requestBodyBuffer.append(sep).append(payloadParameterNames.get(i)).append('=').append(requestArray[i].toString());
316 }
317 else
318 {
319 url.append(sep).append(payloadParameterNames.get(i)).append('=').append(requestArray[i].toString());
320 }
321
322 sep = updateSeparator(sep);
323 }
324 }
325 else
326 {
327 if (payloadParameterNames.get(0) != null)
328 {
329 if (requestBodyBuffer != null)
330 {
331 requestBodyBuffer.append(payloadParameterNames.get(0)).append('=').append(body.toString());
332 }
333 else
334 {
335 url.append(sep).append(payloadParameterNames.get(0)).append('=').append(body.toString());
336 }
337 }
338 }
339 }
340 }
341
342 protected boolean isErrorPayload(UMOMessage message)
343 {
344 if (errorFilter != null)
345 {
346 return errorFilter.accept(message);
347 }
348 return false;
349 }
350
351 protected void handleException(RestServiceException e, UMOMessage result) throws Exception
352 {
353 throw e;
354 }
355 }