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