1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.http;
12
13 import org.mule.RequestContext;
14 import org.mule.api.MuleEvent;
15 import org.mule.api.MuleMessage;
16 import org.mule.api.transport.OutputHandler;
17 import org.mule.transformer.types.DataTypeFactory;
18 import org.mule.transport.NullPayload;
19
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.io.UnsupportedEncodingException;
25 import java.util.Iterator;
26
27 import org.apache.commons.httpclient.ChunkedInputStream;
28 import org.apache.commons.httpclient.ContentLengthInputStream;
29 import org.apache.commons.httpclient.Header;
30 import org.apache.commons.httpclient.HeaderElement;
31 import org.apache.commons.httpclient.HeaderGroup;
32 import org.apache.commons.httpclient.HttpStatus;
33 import org.apache.commons.httpclient.HttpVersion;
34 import org.apache.commons.httpclient.NameValuePair;
35 import org.apache.commons.httpclient.StatusLine;
36
37
38
39
40 public class HttpResponse
41 {
42
43 public static final String DEFAULT_CONTENT_CHARSET = "ISO-8859-1";
44
45 private HttpVersion ver = HttpVersion.HTTP_1_1;
46 private int statusCode = HttpStatus.SC_OK;
47 private String phrase = HttpStatus.getStatusText(HttpStatus.SC_OK);
48 private HeaderGroup headers = new HeaderGroup();
49 private boolean keepAlive = false;
50 private boolean disableKeepAlive = false;
51 private String fallbackCharset = DEFAULT_CONTENT_CHARSET;
52 private OutputHandler outputHandler;
53
54 public HttpResponse()
55 {
56 super();
57 }
58
59 public HttpResponse(final StatusLine statusline, final Header[] headers, final InputStream content)
60 throws IOException
61 {
62 super();
63 if (statusline == null)
64 {
65 throw new IllegalArgumentException("Status line may not be null");
66 }
67 setStatusLine(HttpVersion.parse(statusline.getHttpVersion()), statusline.getStatusCode(),
68 statusline.getReasonPhrase());
69 setHeaders(headers);
70 if (content != null)
71 {
72 InputStream in = content;
73 Header contentLength = this.headers.getFirstHeader(HttpConstants.HEADER_CONTENT_LENGTH);
74 Header transferEncoding = this.headers.getFirstHeader(HttpConstants.HEADER_TRANSFER_ENCODING);
75
76 if (transferEncoding != null)
77 {
78 if (transferEncoding.getValue().indexOf(HttpConstants.TRANSFER_ENCODING_CHUNKED) != -1)
79 {
80 in = new ChunkedInputStream(in);
81 }
82 }
83 else if (contentLength != null)
84 {
85 long len = getContentLength();
86 if (len >= 0)
87 {
88 in = new ContentLengthInputStream(in, len);
89 }
90 }
91 }
92 }
93
94 public void setStatusLine(final HttpVersion ver, int statuscode, final String phrase)
95 {
96 if (ver == null)
97 {
98 throw new IllegalArgumentException("HTTP version may not be null");
99 }
100 if (statuscode <= 0)
101 {
102 throw new IllegalArgumentException("Status code may not be negative or zero");
103 }
104 this.ver = ver;
105 this.statusCode = statuscode;
106 if (phrase != null)
107 {
108 this.phrase = phrase;
109 }
110 else
111 {
112 this.phrase = HttpStatus.getStatusText(statuscode);
113 }
114 }
115
116 public void setStatusLine(final HttpVersion ver, int statuscode)
117 {
118 setStatusLine(ver, statuscode, null);
119 }
120
121 public String getPhrase()
122 {
123 return this.phrase;
124 }
125
126
127
128
129
130 public int getStatuscode()
131 {
132 return this.getStatusCode();
133 }
134
135 public int getStatusCode()
136 {
137 return this.statusCode;
138 }
139
140 public HttpVersion getHttpVersion()
141 {
142 return this.ver;
143 }
144
145 public String getStatusLine()
146 {
147 StringBuffer buffer = new StringBuffer(64);
148 buffer.append(this.ver);
149 buffer.append(' ');
150 buffer.append(this.statusCode);
151 if (this.phrase != null)
152 {
153 buffer.append(' ');
154 buffer.append(this.phrase);
155 }
156 return buffer.toString();
157 }
158
159 public boolean containsHeader(final String name)
160 {
161 return this.headers.containsHeader(name);
162 }
163
164 public Header[] getHeaders()
165 {
166 return this.headers.getAllHeaders();
167 }
168
169 public Header getFirstHeader(final String name)
170 {
171 return this.headers.getFirstHeader(name);
172 }
173
174 public void removeHeaders(final String s)
175 {
176 if (s == null)
177 {
178 return;
179 }
180 Header[] headers = this.headers.getHeaders(s);
181 for (int i = 0; i < headers.length; i++)
182 {
183 this.headers.removeHeader(headers[i]);
184 }
185 }
186
187 public void addHeader(final Header header)
188 {
189 if (header == null)
190 {
191 return;
192 }
193 this.headers.addHeader(header);
194 }
195
196 public void setHeader(final Header header)
197 {
198 if (header == null)
199 {
200 return;
201 }
202 removeHeaders(header.getName());
203 addHeader(header);
204 }
205
206 public void setHeaders(final Header[] headers)
207 {
208 if (headers == null)
209 {
210 return;
211 }
212 this.headers.setHeaders(headers);
213 }
214
215 public Iterator getHeaderIterator()
216 {
217 return this.headers.getIterator();
218 }
219
220 public String getCharset()
221 {
222 String charset = getFallbackCharset();
223 Header contenttype = this.headers.getFirstHeader(HttpConstants.HEADER_CONTENT_TYPE);
224 if (contenttype != null)
225 {
226 HeaderElement values[] = contenttype.getElements();
227 if (values.length == 1)
228 {
229 NameValuePair param = values[0].getParameterByName("charset");
230 if (param != null)
231 {
232 charset = param.getValue();
233 }
234 }
235 }
236 return charset;
237 }
238
239 public long getContentLength()
240 {
241 Header contentLength = this.headers.getFirstHeader(HttpConstants.HEADER_CONTENT_LENGTH);
242 if (contentLength != null)
243 {
244 try
245 {
246 return Long.parseLong(contentLength.getValue());
247 }
248 catch (NumberFormatException e)
249 {
250 return -1;
251 }
252 }
253 else
254 {
255 return -1;
256 }
257 }
258
259 public boolean hasBody()
260 {
261 return outputHandler != null;
262 }
263
264 public OutputHandler getBody() throws IOException
265 {
266 return outputHandler;
267 }
268
269 public void setBody(MuleMessage msg) throws Exception
270 {
271 if (msg == null) return;
272
273
274
275
276
277
278
279
280
281 Object payload = msg.getPayload();
282 if (payload instanceof String)
283 {
284 setBody(payload.toString());
285 }
286 else if (payload instanceof NullPayload)
287 {
288 return;
289 }
290 else if (payload instanceof byte[])
291 {
292 setBody((byte[]) payload);
293 }
294 else
295 {
296 setBody(msg.getPayload(DataTypeFactory.create(OutputHandler.class)));
297 }
298 }
299
300 public void setBody(OutputHandler outputHandler)
301 {
302 this.outputHandler = outputHandler;
303 }
304
305 public void setBody(final String string)
306 {
307 byte[] raw;
308 try
309 {
310 raw = string.getBytes(getCharset());
311 }
312 catch (UnsupportedEncodingException e)
313 {
314 raw = string.getBytes();
315 }
316 setBody(raw);
317 }
318
319 private void setBody(final byte[] raw)
320 {
321 if (!containsHeader(HttpConstants.HEADER_CONTENT_TYPE))
322 {
323 setHeader(new Header(HttpConstants.HEADER_CONTENT_TYPE, HttpConstants.DEFAULT_CONTENT_TYPE));
324 }
325 if (!containsHeader(HttpConstants.HEADER_TRANSFER_ENCODING))
326 {
327 setHeader(new Header(HttpConstants.HEADER_CONTENT_LENGTH, Long.toString(raw.length)));
328 }
329
330 this.outputHandler = new OutputHandler() {
331
332 public void write(MuleEvent event, OutputStream out) throws IOException
333 {
334 out.write(raw);
335 }
336
337 };
338 }
339
340 public String getBodyAsString() throws IOException
341 {
342 if (!hasBody()) return "";
343
344 ByteArrayOutputStream out = new ByteArrayOutputStream();
345
346 outputHandler.write(RequestContext.getEvent(), out);
347
348 try
349 {
350 return new String(out.toByteArray(), getCharset());
351 }
352 catch (UnsupportedEncodingException e)
353 {
354 return new String(out.toByteArray());
355 }
356 }
357
358 public boolean isKeepAlive()
359 {
360 return !disableKeepAlive && keepAlive;
361 }
362
363 public void setKeepAlive(boolean keepAlive)
364 {
365 this.keepAlive = keepAlive;
366 }
367
368
369
370
371
372
373 protected void setupKeepAliveFromRequestVersion(HttpVersion version)
374 {
375 setKeepAlive(version.equals(HttpVersion.HTTP_1_1));
376 }
377
378 public void disableKeepAlive(boolean keepalive)
379 {
380 disableKeepAlive = keepalive;
381 }
382
383 public String getFallbackCharset()
384 {
385 return fallbackCharset;
386 }
387
388 public void setFallbackCharset(String overrideCharset)
389 {
390 this.fallbackCharset = overrideCharset;
391 }
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434 }