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