1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.http;
12
13 import org.mule.DefaultMuleMessage;
14 import org.mule.MessageExchangePattern;
15 import org.mule.api.MuleContext;
16 import org.mule.api.MuleMessage;
17 import org.mule.api.transport.MessageTypeNotSupportedException;
18 import org.mule.transport.AbstractMuleMessageFactory;
19 import org.mule.util.CaseInsensitiveHashMap;
20 import org.mule.util.IOUtils;
21 import org.mule.util.PropertiesUtils;
22 import org.mule.util.StringUtils;
23
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.net.URI;
27 import java.net.URISyntaxException;
28 import java.util.HashMap;
29 import java.util.Map;
30
31 import org.apache.commons.httpclient.Cookie;
32 import org.apache.commons.httpclient.Header;
33 import org.apache.commons.httpclient.HeaderElement;
34 import org.apache.commons.httpclient.HttpMethod;
35 import org.apache.commons.httpclient.HttpVersion;
36 import org.apache.commons.httpclient.NameValuePair;
37 import org.apache.commons.httpclient.cookie.MalformedCookieException;
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40
41 public class HttpMuleMessageFactory extends AbstractMuleMessageFactory
42 {
43 private static Log log = LogFactory.getLog(HttpMuleMessageFactory.class);
44
45 private boolean enableCookies = false;
46 private String cookieSpec;
47 private MessageExchangePattern exchangePattern = MessageExchangePattern.REQUEST_RESPONSE;
48
49 public HttpMuleMessageFactory(MuleContext context)
50 {
51 super(context);
52 }
53
54 @Override
55 protected Class<?>[] getSupportedTransportMessageTypes()
56 {
57 return new Class[]{HttpRequest.class, HttpMethod.class};
58 }
59
60 @Override
61 protected Object extractPayload(Object transportMessage, String encoding) throws Exception
62 {
63 if (transportMessage instanceof HttpRequest)
64 {
65 return extractPayloadFromHttpRequest((HttpRequest) transportMessage);
66 }
67 else if (transportMessage instanceof HttpMethod)
68 {
69 return extractPayloadFromHttpMethod((HttpMethod) transportMessage);
70 }
71 else
72 {
73
74 throw new MessageTypeNotSupportedException(transportMessage, getClass());
75 }
76 }
77
78 protected Object extractPayloadFromHttpRequest(HttpRequest httpRequest) throws IOException
79 {
80 Object body = httpRequest.getBody();
81
82
83 if (body == null)
84 {
85 body = httpRequest.getRequestLine().getUri();
86 }
87 else
88 {
89
90
91
92
93 if (!exchangePattern.hasResponse())
94 {
95 log.debug("Reading HTTP POST InputStream into byte[] for asynchronous messaging.");
96 body = IOUtils.toByteArray((InputStream) body);
97 }
98 }
99
100 return body;
101 }
102
103 protected Object extractPayloadFromHttpMethod(HttpMethod httpMethod) throws IOException
104 {
105 InputStream body = httpMethod.getResponseBodyAsStream();
106 if (body != null)
107 {
108 return new ReleasingInputStream(body, httpMethod);
109 }
110 else
111 {
112 return StringUtils.EMPTY;
113 }
114 }
115
116 @Override
117 protected void addProperties(DefaultMuleMessage message, Object transportMessage) throws Exception
118 {
119 String method;
120 HttpVersion httpVersion;
121 String uri;
122 String statusCode = null;
123 Map<String, Object> headers;
124
125 if (transportMessage instanceof HttpRequest)
126 {
127 HttpRequest httpRequest = (HttpRequest) transportMessage;
128 method = httpRequest.getRequestLine().getMethod();
129 httpVersion = httpRequest.getRequestLine().getHttpVersion();
130 uri = httpRequest.getRequestLine().getUri();
131 headers = convertHeadersToMap(httpRequest.getHeaders(), uri);
132 convertMultiPartHeaders(headers);
133 }
134 else if (transportMessage instanceof HttpMethod)
135 {
136 HttpMethod httpMethod = (HttpMethod) transportMessage;
137 method = httpMethod.getName();
138 httpVersion = HttpVersion.parse(httpMethod.getStatusLine().getHttpVersion());
139 uri = httpMethod.getURI().toString();
140 statusCode = String.valueOf(httpMethod.getStatusCode());
141 headers = convertHeadersToMap(httpMethod.getResponseHeaders(), uri);
142 }
143 else
144 {
145
146 throw new MessageTypeNotSupportedException(transportMessage, getClass());
147 }
148
149 rewriteConnectionAndKeepAliveHeaders(headers);
150
151 headers = processIncomingHeaders(headers);
152
153
154 addUriParamsAsHeaders(headers, uri);
155
156 headers.put(HttpConnector.HTTP_METHOD_PROPERTY, method);
157 headers.put(HttpConnector.HTTP_REQUEST_PROPERTY, uri);
158 headers.put(HttpConnector.HTTP_VERSION_PROPERTY, httpVersion.toString());
159 if (enableCookies)
160 {
161 headers.put(HttpConnector.HTTP_COOKIE_SPEC_PROPERTY, cookieSpec);
162 }
163
164 if (statusCode != null)
165 {
166 headers.put(HttpConnector.HTTP_STATUS_PROPERTY, statusCode);
167 }
168
169 message.addInboundProperties(headers);
170
171
172
173 initEncoding(message, headers);
174 }
175
176 protected Map<String, Object> processIncomingHeaders(Map<String, Object> headers) throws Exception
177 {
178 Map<String, Object> outHeaders = new HashMap<String, Object>();
179
180 for (String headerName : headers.keySet())
181 {
182 Object headerValue = headers.get(headerName);
183
184
185 if (headerName.startsWith("X-MULE"))
186 {
187 headerName = headerName.substring(2);
188 }
189
190
191 outHeaders.put(headerName, headerValue);
192 }
193
194 return outHeaders;
195 }
196
197 Map<String, Object> convertHeadersToMap(Header[] headersArray, String uri)
198 throws URISyntaxException
199 {
200 Map<String, Object> headersMap = new CaseInsensitiveHashMap();
201 for (int i = 0; i < headersArray.length; i++)
202 {
203 final Header header = headersArray[i];
204
205
206 if (HttpConnector.HTTP_COOKIES_PROPERTY.equals(header.getName())
207 || HttpConstants.HEADER_COOKIE.equals(header.getName()))
208 {
209 putCookieHeaderInMapAsAServer(headersMap, header, uri);
210 }
211 else if (HttpConstants.HEADER_COOKIE_SET.equals(header.getName()))
212 {
213 putCookieHeaderInMapAsAClient(headersMap, header, uri);
214 }
215 else
216 {
217 if (headersMap.containsKey(header.getName()))
218 {
219 if (headersMap.get(header.getName()) instanceof String)
220 {
221
222 headersMap.put(header.getName(),
223 headersMap.get(header.getName()) + "," + header.getValue());
224 }
225 else
226 {
227
228 headersMap.put(header.getName(), header.getValue());
229 }
230 }
231 else
232 {
233 headersMap.put(header.getName(), header.getValue());
234 }
235 }
236 }
237 return headersMap;
238 }
239
240 private void putCookieHeaderInMapAsAClient(Map<String, Object> headersMap, final Header header, String uri)
241 throws URISyntaxException
242 {
243 try
244 {
245 final Cookie[] newCookies = CookieHelper.parseCookiesAsAClient(header.getValue(), cookieSpec,
246 new URI(uri));
247 final Object preExistentCookies = headersMap.get(HttpConstants.HEADER_COOKIE_SET);
248 final Object mergedCookie = CookieHelper.putAndMergeCookie(preExistentCookies, newCookies);
249 headersMap.put(HttpConstants.HEADER_COOKIE_SET, mergedCookie);
250 }
251 catch (MalformedCookieException e)
252 {
253 log.warn("Received an invalid cookie: " + header, e);
254 }
255 }
256
257 private void putCookieHeaderInMapAsAServer(Map<String, Object> headersMap, final Header header, String uri)
258 throws URISyntaxException
259 {
260 if (enableCookies)
261 {
262 Cookie[] newCookies = CookieHelper.parseCookiesAsAServer(header.getValue(), new URI(uri));
263 if (newCookies.length > 0)
264 {
265 Object oldCookies = headersMap.get(HttpConnector.HTTP_COOKIES_PROPERTY);
266 Object mergedCookies = CookieHelper.putAndMergeCookie(oldCookies, newCookies);
267 headersMap.put(HttpConnector.HTTP_COOKIES_PROPERTY, mergedCookies);
268 }
269 }
270 }
271
272 private void initEncoding(MuleMessage message, Map<String, Object> headers)
273 {
274 Object contentType = headers.get(HttpConstants.HEADER_CONTENT_TYPE);
275 if (contentType != null)
276 {
277
278
279 Header contentTypeHeader = new Header(HttpConstants.HEADER_CONTENT_TYPE,
280 contentType.toString());
281 HeaderElement values[] = contentTypeHeader.getElements();
282 if (values.length == 1)
283 {
284 NameValuePair param = values[0].getParameterByName("charset");
285 if (param != null)
286 {
287 message.setEncoding(param.getValue());
288 }
289 }
290 }
291 }
292
293 private void rewriteConnectionAndKeepAliveHeaders(Map<String, Object> headers)
294 {
295
296 String headerValue;
297 if (!isHttp11(headers))
298 {
299 String connection = (String) headers.get(HttpConstants.HEADER_CONNECTION);
300 if ((connection != null) && connection.equalsIgnoreCase("close"))
301 {
302 headerValue = Boolean.FALSE.toString();
303 }
304 else
305 {
306 headerValue = Boolean.TRUE.toString();
307 }
308 }
309 else
310 {
311 headerValue = (headers.get(HttpConstants.HEADER_CONNECTION) != null
312 ? Boolean.TRUE.toString()
313 : Boolean.FALSE.toString());
314 }
315
316 headers.put(HttpConstants.HEADER_CONNECTION, headerValue);
317 headers.put(HttpConstants.HEADER_KEEP_ALIVE, headerValue);
318 }
319
320 private boolean isHttp11(Map<String, Object> headers)
321 {
322 String httpVersion = (String) headers.get(HttpConnector.HTTP_VERSION_PROPERTY);
323 return !HttpConstants.HTTP10.equalsIgnoreCase(httpVersion);
324 }
325
326 protected void addUriParamsAsHeaders(Map headers, String uri)
327 {
328 int i = uri.indexOf("?");
329 if (i > -1)
330 {
331 headers.putAll(PropertiesUtils.getPropertiesFromQueryString(uri.substring(i + 1)));
332 }
333 }
334
335 protected void convertMultiPartHeaders(Map<String, Object> headers)
336 {
337
338 }
339
340 public void setEnableCookies(boolean enableCookies)
341 {
342 this.enableCookies = enableCookies;
343 }
344
345 public void setCookieSpec(String cookieSpec)
346 {
347 this.cookieSpec = cookieSpec;
348 }
349
350 public void setExchangePattern(MessageExchangePattern mep)
351 {
352 exchangePattern = mep;
353 }
354 }