View Javadoc

1   /*
2    * $Id: HttpResponse.java 11433 2008-03-20 03:43:57Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
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   * A generic HTTP response wrapper.
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      * @deprecated use {@link #getStatusCode()} instead
128      * @return HTTP status code
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 }