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.transformer.TransformerException;
17 import org.mule.api.transport.OutputHandler;
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 TransformerException
265 {
266 return outputHandler;
267 }
268
269 public void setBody(MuleMessage msg) throws TransformerException
270 {
271 if (msg == null) return;
272
273 Object payload = msg.getPayload();
274 if (payload instanceof String)
275 {
276 setBody(payload.toString());
277 }
278 else if (payload instanceof NullPayload)
279 {
280 return;
281 }
282 else if (payload instanceof byte[])
283 {
284 setBody((byte[]) payload);
285 }
286 else
287 {
288 setBody((OutputHandler) msg.getPayload(OutputHandler.class));
289 }
290 }
291
292 public void setBody(OutputHandler outputHandler)
293 {
294 this.outputHandler = outputHandler;
295 }
296
297 public void setBody(final String string)
298 {
299 byte[] raw;
300 try
301 {
302 raw = string.getBytes(getCharset());
303 }
304 catch (UnsupportedEncodingException e)
305 {
306 raw = string.getBytes();
307 }
308 setBody(raw);
309 }
310
311 private void setBody(final byte[] raw)
312 {
313 if (!containsHeader(HttpConstants.HEADER_CONTENT_TYPE))
314 {
315 setHeader(new Header(HttpConstants.HEADER_CONTENT_TYPE, HttpConstants.DEFAULT_CONTENT_TYPE));
316 }
317 setHeader(new Header(HttpConstants.HEADER_CONTENT_LENGTH, Long.toString(raw.length)));
318
319 this.outputHandler = new OutputHandler() {
320
321 public void write(MuleEvent event, OutputStream out) throws IOException
322 {
323 out.write(raw);
324 }
325
326 };
327 }
328
329 public String getBodyAsString() throws IOException
330 {
331 if (!hasBody()) return "";
332
333 ByteArrayOutputStream out = new ByteArrayOutputStream();
334
335 outputHandler.write(RequestContext.getEvent(), out);
336
337 try
338 {
339 return new String(out.toByteArray(), getCharset());
340 }
341 catch (UnsupportedEncodingException e)
342 {
343 return new String(out.toByteArray());
344 }
345 }
346
347 public boolean isKeepAlive()
348 {
349 return !disableKeepAlive && keepAlive;
350 }
351
352 public void setKeepAlive(boolean keepAlive)
353 {
354 this.keepAlive = keepAlive;
355 }
356
357 public void disableKeepAlive(boolean keepalive)
358 {
359 disableKeepAlive = keepalive;
360 }
361
362 public String getFallbackCharset()
363 {
364 return fallbackCharset;
365 }
366
367 public void setFallbackCharset(String overrideCharset)
368 {
369 this.fallbackCharset = overrideCharset;
370 }
371
372 }