1
2
3
4
5
6
7 package org.mule.transport.http.transformers;
8
9 import org.mule.RequestContext;
10 import org.mule.api.MuleEvent;
11 import org.mule.api.MuleMessage;
12 import org.mule.api.config.MuleProperties;
13 import org.mule.api.transformer.TransformerException;
14 import org.mule.api.transport.OutputHandler;
15 import org.mule.api.transport.PropertyScope;
16 import org.mule.message.ds.StringDataSource;
17 import org.mule.transformer.AbstractMessageTransformer;
18 import org.mule.transformer.types.DataTypeFactory;
19 import org.mule.transport.NullPayload;
20 import org.mule.transport.http.HttpConnector;
21 import org.mule.transport.http.HttpConstants;
22 import org.mule.transport.http.PatchMethod;
23 import org.mule.transport.http.StreamPayloadRequestEntity;
24 import org.mule.transport.http.i18n.HttpMessages;
25 import org.mule.util.IOUtils;
26 import org.mule.util.ObjectUtils;
27 import org.mule.util.SerializationUtils;
28 import org.mule.util.StringUtils;
29
30 import java.io.InputStream;
31 import java.io.Serializable;
32 import java.io.UnsupportedEncodingException;
33 import java.net.URI;
34 import java.net.URISyntaxException;
35 import java.net.URLEncoder;
36 import java.util.Iterator;
37 import java.util.Map;
38
39 import javax.activation.DataHandler;
40 import javax.activation.FileDataSource;
41 import javax.activation.URLDataSource;
42
43 import org.apache.commons.httpclient.HttpMethod;
44 import org.apache.commons.httpclient.HttpVersion;
45 import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
46 import org.apache.commons.httpclient.methods.DeleteMethod;
47 import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
48 import org.apache.commons.httpclient.methods.GetMethod;
49 import org.apache.commons.httpclient.methods.HeadMethod;
50 import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
51 import org.apache.commons.httpclient.methods.OptionsMethod;
52 import org.apache.commons.httpclient.methods.PostMethod;
53 import org.apache.commons.httpclient.methods.PutMethod;
54 import org.apache.commons.httpclient.methods.StringRequestEntity;
55 import org.apache.commons.httpclient.methods.TraceMethod;
56 import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource;
57 import org.apache.commons.httpclient.methods.multipart.FilePart;
58 import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
59 import org.apache.commons.httpclient.methods.multipart.Part;
60 import org.apache.commons.httpclient.methods.multipart.StringPart;
61 import org.apache.commons.httpclient.params.HttpMethodParams;
62
63
64
65
66
67 public class ObjectToHttpClientMethodRequest extends AbstractMessageTransformer
68 {
69 public ObjectToHttpClientMethodRequest()
70 {
71 setReturnDataType(DataTypeFactory.create(HttpMethod.class));
72 registerSourceType(DataTypeFactory.MULE_MESSAGE);
73 registerSourceType(DataTypeFactory.BYTE_ARRAY);
74 registerSourceType(DataTypeFactory.STRING);
75 registerSourceType(DataTypeFactory.INPUT_STREAM);
76 registerSourceType(DataTypeFactory.create(OutputHandler.class));
77 registerSourceType(DataTypeFactory.create(NullPayload.class));
78 }
79
80 @Override
81 public Object transformMessage(MuleMessage msg, String outputEncoding) throws TransformerException
82 {
83 String method = detectHttpMethod(msg);
84 try
85 {
86 HttpMethod httpMethod;
87
88 if (HttpConstants.METHOD_GET.equals(method))
89 {
90 httpMethod = createGetMethod(msg, outputEncoding);
91 }
92 else if (HttpConstants.METHOD_POST.equalsIgnoreCase(method))
93 {
94 httpMethod = createPostMethod(msg, outputEncoding);
95 }
96 else if (HttpConstants.METHOD_PUT.equalsIgnoreCase(method))
97 {
98 httpMethod = createPutMethod(msg, outputEncoding);
99 }
100 else if (HttpConstants.METHOD_DELETE.equalsIgnoreCase(method))
101 {
102 httpMethod = createDeleteMethod(msg);
103 }
104 else if (HttpConstants.METHOD_HEAD.equalsIgnoreCase(method))
105 {
106 httpMethod = createHeadMethod(msg);
107 }
108 else if (HttpConstants.METHOD_OPTIONS.equalsIgnoreCase(method))
109 {
110 httpMethod = createOptionsMethod(msg);
111 }
112 else if (HttpConstants.METHOD_TRACE.equalsIgnoreCase(method))
113 {
114 httpMethod = createTraceMethod(msg);
115 }
116 else if (HttpConstants.METHOD_PATCH.equalsIgnoreCase(method))
117 {
118 httpMethod = createPatchMethod(msg);
119 }
120 else
121 {
122 throw new TransformerException(HttpMessages.unsupportedMethod(method));
123 }
124
125
126 final HttpMethodParams params = (HttpMethodParams) msg.removeProperty(
127 HttpConnector.HTTP_PARAMS_PROPERTY, PropertyScope.OUTBOUND);
128 if (params != null)
129 {
130 httpMethod.setParams(params);
131 }
132 else
133 {
134
135 final String httpVersion = msg.getOutboundProperty(HttpConnector.HTTP_VERSION_PROPERTY,
136 HttpConstants.HTTP11);
137 if (HttpConstants.HTTP10.equals(httpVersion))
138 {
139 httpMethod.getParams().setVersion(HttpVersion.HTTP_1_0);
140 }
141 else
142 {
143 httpMethod.getParams().setVersion(HttpVersion.HTTP_1_1);
144 }
145 }
146
147 setHeaders(httpMethod, msg);
148
149 return httpMethod;
150 }
151 catch (final Exception e)
152 {
153 throw new TransformerException(this, e);
154 }
155 }
156
157 protected String detectHttpMethod(MuleMessage msg)
158 {
159 String method = msg.getOutboundProperty(HttpConnector.HTTP_METHOD_PROPERTY, null);
160 if (method == null)
161 {
162 method = msg.getInvocationProperty(HttpConnector.HTTP_METHOD_PROPERTY, HttpConstants.METHOD_POST);
163 }
164 return method;
165 }
166
167 protected HttpMethod createGetMethod(MuleMessage msg, String outputEncoding) throws Exception
168 {
169 final Object src = msg.getPayload();
170
171
172
173 final URI uri = getURI(msg);
174 HttpMethod httpMethod;
175 String query = uri.getRawQuery();
176
177 httpMethod = new GetMethod(uri.toString());
178 String paramName = msg.getOutboundProperty(HttpConnector.HTTP_GET_BODY_PARAM_PROPERTY, null);
179 if (paramName != null)
180 {
181 paramName = URLEncoder.encode(paramName, outputEncoding);
182
183 String paramValue;
184 Boolean encode = msg.getInvocationProperty(HttpConnector.HTTP_ENCODE_PARAMVALUE);
185 if (encode == null)
186 {
187 encode = msg.getOutboundProperty(HttpConnector.HTTP_ENCODE_PARAMVALUE, true);
188 }
189
190 if (encode)
191 {
192 paramValue = URLEncoder.encode(src.toString(), outputEncoding);
193 }
194 else
195 {
196 paramValue = src.toString();
197 }
198
199 if (!(src instanceof NullPayload) && !StringUtils.EMPTY.equals(src))
200 {
201 if (query == null)
202 {
203 query = paramName + "=" + paramValue;
204 }
205 else
206 {
207 query += "&" + paramName + "=" + paramValue;
208 }
209 }
210 }
211
212 httpMethod.setQueryString(query);
213 return httpMethod;
214 }
215
216 protected HttpMethod createPostMethod(MuleMessage msg, String outputEncoding) throws Exception
217 {
218 URI uri = getURI(msg);
219 PostMethod postMethod = new PostMethod(uri.toString());
220
221 String bodyParameterName = getBodyParameterName(msg);
222 Object src = msg.getPayload();
223 if (src instanceof Map)
224 {
225 for (Map.Entry<?, ?> entry : ((Map<?, ?>) src).entrySet())
226 {
227 postMethod.addParameter(entry.getKey().toString(), entry.getValue().toString());
228 }
229 }
230 else if (bodyParameterName != null)
231 {
232 postMethod.addParameter(bodyParameterName, src.toString());
233
234 }
235 else
236 {
237 setupEntityMethod(src, outputEncoding, msg, postMethod);
238 }
239
240 setContentType(msg, postMethod);
241
242 return postMethod;
243 }
244
245 protected String getBodyParameterName(MuleMessage message)
246 {
247 String bodyParameter = message.getOutboundProperty(HttpConnector.HTTP_POST_BODY_PARAM_PROPERTY);
248 if (bodyParameter == null)
249 {
250 bodyParameter = message.getInvocationProperty(HttpConnector.HTTP_POST_BODY_PARAM_PROPERTY);
251 }
252 return bodyParameter;
253 }
254
255 protected HttpMethod createPutMethod(MuleMessage msg, String outputEncoding) throws Exception
256 {
257 URI uri = getURI(msg);
258 PutMethod putMethod = new PutMethod(uri.toString());
259 setContentType(msg, putMethod);
260
261 Object payload = msg.getPayload();
262 setupEntityMethod(payload, outputEncoding, msg, putMethod);
263
264 return putMethod;
265 }
266
267 private void setContentType(MuleMessage msg, HttpMethod putMethod)
268 {
269
270 String outgoingContentType = msg.getInvocationProperty(HttpConstants.HEADER_CONTENT_TYPE);
271 if (outgoingContentType != null)
272 {
273 putMethod.setRequestHeader(HttpConstants.HEADER_CONTENT_TYPE, outgoingContentType);
274 }
275 }
276
277 protected HttpMethod createDeleteMethod(MuleMessage message) throws Exception
278 {
279 URI uri = getURI(message);
280 return new DeleteMethod(uri.toString());
281 }
282
283 protected HttpMethod createHeadMethod(MuleMessage message) throws Exception
284 {
285 URI uri = getURI(message);
286 return new HeadMethod(uri.toString());
287 }
288
289 protected HttpMethod createOptionsMethod(MuleMessage message) throws Exception
290 {
291 URI uri = getURI(message);
292 return new OptionsMethod(uri.toString());
293 }
294
295 protected HttpMethod createTraceMethod(MuleMessage message) throws Exception
296 {
297 URI uri = getURI(message);
298 return new TraceMethod(uri.toString());
299 }
300
301 protected HttpMethod createPatchMethod(MuleMessage message) throws Exception
302 {
303 URI uri = getURI(message);
304 return new PatchMethod(uri.toString());
305 }
306
307 protected URI getURI(MuleMessage message) throws URISyntaxException, TransformerException
308 {
309 String endpointAddress = message.getOutboundProperty(MuleProperties.MULE_ENDPOINT_PROPERTY, null);
310 if (endpointAddress == null)
311 {
312 throw new TransformerException(
313 HttpMessages.eventPropertyNotSetCannotProcessRequest(MuleProperties.MULE_ENDPOINT_PROPERTY),
314 this);
315 }
316 return new URI(endpointAddress);
317 }
318
319 protected void setupEntityMethod(Object src, String encoding, MuleMessage msg,
320 EntityEnclosingMethod postMethod) throws UnsupportedEncodingException, TransformerException
321 {
322
323
324 if (!(msg.getPayload() instanceof NullPayload))
325 {
326 String outboundMimeType = (String) msg.getProperty(HttpConstants.HEADER_CONTENT_TYPE,
327 PropertyScope.OUTBOUND);
328 if (outboundMimeType == null)
329 {
330 outboundMimeType = (getEndpoint() != null ? getEndpoint().getMimeType() : null);
331 }
332 if (outboundMimeType == null)
333 {
334 outboundMimeType = HttpConstants.DEFAULT_CONTENT_TYPE;
335 logger.info("Content-Type not set on outgoing request, defaulting to: " + outboundMimeType);
336 }
337
338 if (encoding != null && !"UTF-8".equals(encoding.toUpperCase())
339 && outboundMimeType.indexOf("charset") == -1)
340 {
341 outboundMimeType += "; charset=" + encoding;
342 }
343
344
345
346 final String httpVersion = msg.getOutboundProperty(HttpConnector.HTTP_VERSION_PROPERTY,
347 HttpConstants.HTTP11);
348 if (HttpConstants.HTTP10.equals(httpVersion))
349 {
350 try
351 {
352 src = msg.getPayloadAsBytes();
353 }
354 catch (final Exception e)
355 {
356 throw new TransformerException(this, e);
357 }
358 }
359
360 if (msg.getOutboundAttachmentNames() != null && msg.getOutboundAttachmentNames().size() > 0)
361 {
362 try
363 {
364 postMethod.setRequestEntity(createMultiPart(msg, postMethod));
365 return;
366 }
367 catch (final Exception e)
368 {
369 throw new TransformerException(this, e);
370 }
371 }
372 if (src instanceof String)
373 {
374 postMethod.setRequestEntity(new StringRequestEntity(src.toString(), outboundMimeType, encoding));
375 return;
376 }
377
378 if (src instanceof InputStream)
379 {
380 postMethod.setRequestEntity(new InputStreamRequestEntity((InputStream) src, outboundMimeType));
381 }
382 else if (src instanceof byte[])
383 {
384 postMethod.setRequestEntity(new ByteArrayRequestEntity((byte[]) src, outboundMimeType));
385 }
386 else if (src instanceof OutputHandler)
387 {
388 final MuleEvent event = RequestContext.getEvent();
389 postMethod.setRequestEntity(new StreamPayloadRequestEntity((OutputHandler) src, event));
390 }
391 else
392 {
393 final byte[] buffer = SerializationUtils.serialize((Serializable) src);
394 postMethod.setRequestEntity(new ByteArrayRequestEntity(buffer, outboundMimeType));
395 }
396 }
397 else if (msg.getOutboundAttachmentNames() != null && msg.getOutboundAttachmentNames().size() > 0)
398 {
399 try
400 {
401 postMethod.setRequestEntity(createMultiPart(msg, postMethod));
402 }
403 catch (Exception e)
404 {
405 throw new TransformerException(this, e);
406 }
407 }
408 }
409
410 protected void setHeaders(HttpMethod httpMethod, MuleMessage msg) throws TransformerException
411 {
412 for (String headerName : msg.getOutboundPropertyNames())
413 {
414 String headerValue = ObjectUtils.getString(msg.getOutboundProperty(headerName), null);
415
416 if (headerName.startsWith(MuleProperties.PROPERTY_PREFIX))
417 {
418
419 headerName = new StringBuffer(30).append("X-").append(headerName).toString();
420 httpMethod.addRequestHeader(headerName, headerValue);
421
422 }
423 else if (!HttpConstants.RESPONSE_HEADER_NAMES.containsKey(headerName)
424 && !HttpConnector.HTTP_INBOUND_PROPERTIES.contains(headerName)
425 && !HttpConnector.HTTP_COOKIES_PROPERTY.equals(headerName))
426 {
427
428 httpMethod.addRequestHeader(headerName, headerValue);
429 }
430 }
431 }
432
433 protected MultipartRequestEntity createMultiPart(MuleMessage msg, EntityEnclosingMethod method)
434 throws Exception
435 {
436 Part[] parts;
437 int i = 0;
438 if (msg.getPayload() instanceof NullPayload)
439 {
440 parts = new Part[msg.getOutboundAttachmentNames().size()];
441 }
442 else
443 {
444 parts = new Part[msg.getOutboundAttachmentNames().size() + 1];
445 parts[i++] = new FilePart("payload", new ByteArrayPartSource("payload", msg.getPayloadAsBytes()));
446 }
447
448 for (final Iterator<String> iterator = msg.getOutboundAttachmentNames().iterator(); iterator.hasNext(); i++)
449 {
450 final String attachmentNames = iterator.next();
451 String fileName = attachmentNames;
452 final DataHandler dh = msg.getOutboundAttachment(attachmentNames);
453 if (dh.getDataSource() instanceof StringDataSource)
454 {
455 final StringDataSource ds = (StringDataSource) dh.getDataSource();
456 parts[i] = new StringPart(ds.getName(), IOUtils.toString(ds.getInputStream()));
457 }
458 else
459 {
460 if (dh.getDataSource() instanceof FileDataSource)
461 {
462 fileName = ((FileDataSource) dh.getDataSource()).getFile().getName();
463 }
464 else if (dh.getDataSource() instanceof URLDataSource)
465 {
466 fileName = ((URLDataSource) dh.getDataSource()).getURL().getFile();
467
468 final int x = fileName.lastIndexOf("/");
469 if (x > -1)
470 {
471 fileName = fileName.substring(x + 1);
472 }
473 }
474 parts[i] = new FilePart(dh.getName(), new ByteArrayPartSource(fileName,
475 IOUtils.toByteArray(dh.getInputStream())), dh.getContentType(), null);
476 }
477 }
478
479 return new MultipartRequestEntity(parts, method.getParams());
480 }
481 }