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