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