1   /*
2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/server/SimpleResponse.java,v 1.8 2004/11/13 12:21:28 olegk Exp $
3    * $Revision: 155418 $
4    * $Date: 2005-02-26 08:01:52 -0500 (Sat, 26 Feb 2005) $
5    *
6    * ====================================================================
7    *
8    *  Copyright 1999-2004 The Apache Software Foundation
9    *
10   *  Licensed under the Apache License, Version 2.0 (the "License");
11   *  you may not use this file except in compliance with the License.
12   *  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   */
29  
30  package org.apache.commons.httpclient.server;
31  
32  import java.io.ByteArrayInputStream;
33  import java.io.ByteArrayOutputStream;
34  import java.io.IOException;
35  import java.io.InputStream;
36  import java.io.UnsupportedEncodingException;
37  import java.util.Iterator;
38  
39  import org.apache.commons.httpclient.ChunkedInputStream;
40  import org.apache.commons.httpclient.ContentLengthInputStream;
41  import org.apache.commons.httpclient.Header;
42  import org.apache.commons.httpclient.HeaderElement;
43  import org.apache.commons.httpclient.HeaderGroup;
44  import org.apache.commons.httpclient.HttpStatus;
45  import org.apache.commons.httpclient.HttpVersion;
46  import org.apache.commons.httpclient.NameValuePair;
47  import org.apache.commons.httpclient.StatusLine;
48  
49  /***
50   * A generic HTTP response.
51   * 
52   * @author Christian Kohlschuetter
53   * @author Oleg Kalnichevski
54   */
55  public class SimpleResponse {
56      
57      public static final String DEFAULT_CONTENT_CHARSET = "ISO-8859-1";
58      
59      private HttpVersion ver = HttpVersion.HTTP_1_1;
60      private int statuscode = HttpStatus.SC_OK;
61      private String phrase = HttpStatus.getStatusText(HttpStatus.SC_OK);
62      private HeaderGroup headers = new HeaderGroup();
63      private InputStream entity = null;
64  
65      public SimpleResponse() {
66          super();
67      }
68  
69      public SimpleResponse(
70              final StatusLine statusline, 
71              final Header[] headers, 
72              final InputStream content) 
73              throws IOException {
74          super();
75          if (statusline == null) {
76              throw new IllegalArgumentException("Status line may not be null");
77          }
78          setStatusLine(HttpVersion.parse(statusline.getHttpVersion()),
79                  statusline.getStatusCode(), statusline.getReasonPhrase());
80          setHeaders(headers);
81          if (content != null) {
82              InputStream in = content;
83              Header contentLength = this.headers.getFirstHeader("Content-Length");
84              Header transferEncoding = this.headers.getFirstHeader("Transfer-Encoding");
85  
86              if (transferEncoding != null) {
87                  if (transferEncoding.getValue().indexOf("chunked") != -1) {
88                      in = new ChunkedInputStream(in);
89                  }
90              } else if (contentLength != null) {
91                  long len = getContentLength();
92                  if (len >= 0) {
93                      in = new ContentLengthInputStream(in, len);
94                  }
95              }
96              this.entity = in;
97          }
98      }
99  
100 
101     public void setStatusLine(final HttpVersion ver, int statuscode, final String phrase) {
102         if (ver == null) {
103             throw new IllegalArgumentException("HTTP version may not be null");
104         }
105         if (statuscode <= 0) {
106             throw new IllegalArgumentException("Status code may not be negative or zero");
107         }
108         this.ver = ver;
109         this.statuscode = statuscode;
110         if (phrase != null) {
111             this.phrase = phrase;
112         } else {
113             this.phrase = HttpStatus.getStatusText(statuscode);
114         }
115     }
116 
117     public void setStatusLine(final HttpVersion ver, int statuscode) {
118         setStatusLine(ver, statuscode, null);
119     }
120 
121     public String getPhrase() {
122         return this.phrase;
123     }
124 
125     public int getStatuscode() {
126         return this.statuscode;
127     }
128 
129     public HttpVersion getHttpVersion() {
130         return this.ver;
131     }
132 
133     public String getStatusLine() {
134         StringBuffer buffer = new StringBuffer();
135         buffer.append(this.ver);
136         buffer.append(' ');
137         buffer.append(this.statuscode);
138         if (this.phrase != null) {
139             buffer.append(' ');
140             buffer.append(this.phrase);
141         }
142         return buffer.toString();
143     }
144 
145     public boolean containsHeader(final String name) {
146         return this.headers.containsHeader(name);
147     }
148 
149     public Header[] getHeaders() {
150         return this.headers.getAllHeaders();
151     }
152 
153     public Header getFirstHeader(final String name) {
154         return this.headers.getFirstHeader(name);
155     }
156 
157     public void removeHeaders(final String s) {
158         if (s == null) {
159             return;
160         }
161         Header[] headers = this.headers.getHeaders(s);
162         for (int i = 0; i < headers.length; i++) {
163             this.headers.removeHeader(headers[i]);
164         }
165     }
166 
167     public void addHeader(final Header header) {
168         if (header == null) {
169             return;
170         }
171         this.headers.addHeader(header);
172     }
173 
174     public void setHeader(final Header header) {
175         if (header == null) {
176             return;
177         }
178         removeHeaders(header.getName());
179         addHeader(header);
180     }
181 
182     public void setHeaders(final Header[] headers) {
183         if (headers == null) {
184             return;
185         }
186         this.headers.setHeaders(headers);
187     }
188 
189     public Iterator getHeaderIterator() {
190         return this.headers.getIterator();
191     }
192     
193     public String getCharset() {
194         String charset = DEFAULT_CONTENT_CHARSET;
195         Header contenttype = this.headers.getFirstHeader("Content-Type");
196         if (contenttype != null) {
197             HeaderElement values[] = contenttype.getElements();
198             if (values.length == 1) {
199                 NameValuePair param = values[0].getParameterByName("charset");
200                 if (param != null) {
201                     charset = param.getValue();
202                 }
203             }
204         }
205         return charset;
206     }
207 
208     public long getContentLength() {
209         Header contentLength = this.headers.getFirstHeader("Content-Length");
210         if (contentLength != null) {
211             try {
212                 return Long.parseLong(contentLength.getValue());
213             } catch (NumberFormatException e) {
214                 return -1;
215             }
216         } else {
217             return -1;
218         }
219     }
220     
221     public void setBodyString(final String string) {
222         if (string != null) {
223             byte[] raw = null;
224             try {
225                 raw = string.getBytes(DEFAULT_CONTENT_CHARSET);
226             } catch (UnsupportedEncodingException e) {
227                 raw = string.getBytes();
228             }
229             this.entity = new ByteArrayInputStream(raw);
230             if (!containsHeader("Content-Type")) {
231                 setHeader(new Header("Content-Type", "text/plain"));
232             }
233             setHeader(new Header("Content-Length", Long.toString(raw.length)));
234         } else {
235             this.entity = null;
236         }
237     }
238     
239     public void setBody(final InputStream instream) {
240         this.entity = instream;
241     }
242     
243     public InputStream getBody() {
244         return this.entity;
245     }
246     
247     public byte[] getBodyBytes() throws IOException {
248         InputStream in = getBody();
249         if (in != null) {
250             byte[] tmp = new byte[4096];
251             int bytesRead = 0;
252             ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024);
253             while ((bytesRead = in.read(tmp)) != -1) {
254                 buffer.write(tmp, 0, bytesRead);
255             }
256             return buffer.toByteArray();
257         } else {
258             return null;
259         }
260     }
261     
262     public String getBodyString() throws IOException {
263         byte[] raw = getBodyBytes();
264         if (raw != null) {
265             return new String(raw, getCharset());
266         } else {
267             return null;
268         }
269     }
270 }