1   /*
2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/server/SimpleHttpServerConnection.java,v 1.21 2004/12/11 22:35:26 olegk Exp $
3    * $Revision: 224451 $
4    * $Date: 2005-07-23 06:23:59 -0400 (Sat, 23 Jul 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.IOException;
33  import java.io.InputStream;
34  import java.io.OutputStream;
35  import java.io.UnsupportedEncodingException;
36  import java.net.Socket;
37  import java.net.SocketException;
38  import java.util.Iterator;
39  
40  import org.apache.commons.httpclient.ChunkedOutputStream;
41  import org.apache.commons.httpclient.Header;
42  import org.apache.commons.httpclient.HttpParser;
43  import org.apache.commons.httpclient.StatusLine;
44  
45  /***
46   * A connection to the SimpleHttpServer.
47   * 
48   * @author Christian Kohlschuetter
49   * @author Oleg Kalnichevski
50   */
51  public class SimpleHttpServerConnection {
52      
53      private static final String HTTP_ELEMENT_CHARSET = "US-ASCII";
54  
55      private Socket socket = null;
56      private InputStream in = null;
57      private OutputStream out = null;
58      private boolean keepAlive = false;
59  
60      public SimpleHttpServerConnection(final Socket socket) 
61      throws IOException {
62          super();
63          if (socket == null) {
64              throw new IllegalArgumentException("Socket may not be null");
65          }
66          this.socket = socket;
67          this.socket.setSoTimeout(500);
68          this.in = socket.getInputStream();
69          this.out = socket.getOutputStream();
70      }
71  
72      public synchronized void close() {
73          try {
74              if (socket != null) {
75                  in.close();
76                  out.close();
77                  socket.close();
78                  socket = null;
79              }
80          } catch (IOException e) {
81          }
82      }
83  
84      public synchronized boolean isOpen() {
85          return this.socket != null;
86      }
87      
88      public void setKeepAlive(boolean b) {
89          this.keepAlive = b;
90      }
91  
92      public boolean isKeepAlive() {
93          return this.keepAlive;
94      }
95  
96      public InputStream getInputStream() {
97          return this.in;
98      }
99  
100     public OutputStream getOutputStream() {
101         return this.out;
102     }
103 
104     /***
105      * Returns the ResponseWriter used to write the output to the socket.
106      * 
107      * @return This connection's ResponseWriter
108      */
109     public ResponseWriter getWriter() throws UnsupportedEncodingException {
110         return new ResponseWriter(out);
111     }
112 
113     public SimpleRequest readRequest() throws IOException {
114         try {
115             String line = null;
116             do {
117                 line = HttpParser.readLine(in, HTTP_ELEMENT_CHARSET);
118             } while (line != null && line.length() == 0);
119 
120             if (line == null) {
121                 setKeepAlive(false);
122                 return null;
123             }
124             SimpleRequest request = new SimpleRequest( 
125                     RequestLine.parseLine(line),
126                     HttpParser.parseHeaders(this.in, HTTP_ELEMENT_CHARSET),
127                     this.in);
128             return request;
129         } catch (IOException e) {
130             close();
131             throw e;
132         }
133     }
134 
135     public SimpleResponse readResponse() throws IOException {
136         try {
137             String line = null;
138             do {
139                 line = HttpParser.readLine(in, HTTP_ELEMENT_CHARSET);
140             } while (line != null && line.length() == 0);
141 
142             if (line == null) {
143                 setKeepAlive(false);
144                 return null;
145             }
146             SimpleResponse response = new SimpleResponse(
147                     new StatusLine(line),
148                     HttpParser.parseHeaders(this.in, HTTP_ELEMENT_CHARSET),
149                     this.in);
150             return response;
151         } catch (IOException e) {
152             close();
153             throw e;
154         }
155     }
156 
157     public void writeRequest(final SimpleRequest request) throws IOException {
158         if (request == null) {
159             return;
160         }
161         ResponseWriter writer = new ResponseWriter(this.out, HTTP_ELEMENT_CHARSET);
162         writer.println(request.getRequestLine().toString());
163         Iterator item = request.getHeaderIterator();
164         while (item.hasNext()) {
165             Header header = (Header) item.next();
166             writer.print(header.toExternalForm());
167         }
168         writer.println();
169         writer.flush();
170         
171         OutputStream outsream = this.out;
172         InputStream content = request.getBody(); 
173         if (content != null) {
174 
175             Header transferenc = request.getFirstHeader("Transfer-Encoding");
176             if (transferenc != null) {
177                 request.removeHeaders("Content-Length");
178                 if (transferenc.getValue().indexOf("chunked") != -1) {
179                     outsream = new ChunkedOutputStream(outsream);
180                 }
181             }
182             byte[] tmp = new byte[4096];
183             int i = 0;
184             while ((i = content.read(tmp)) >= 0) {
185                 outsream.write(tmp, 0, i);
186             }        
187             if (outsream instanceof ChunkedOutputStream) {
188                 ((ChunkedOutputStream)outsream).finish();
189             }
190         }
191         outsream.flush();
192     }
193     
194     public void writeResponse(final SimpleResponse response) throws IOException {
195         if (response == null) {
196             return;
197         }
198         ResponseWriter writer = new ResponseWriter(this.out, HTTP_ELEMENT_CHARSET);
199         writer.println(response.getStatusLine());
200         Iterator item = response.getHeaderIterator();
201         while (item.hasNext()) {
202             Header header = (Header) item.next();
203             writer.print(header.toExternalForm());
204         }
205         writer.println();
206         writer.flush();
207         
208         OutputStream outsream = this.out;
209         InputStream content = response.getBody(); 
210         if (content != null) {
211 
212             Header transferenc = response.getFirstHeader("Transfer-Encoding");
213             if (transferenc != null) {
214                 response.removeHeaders("Content-Length");
215                 if (transferenc.getValue().indexOf("chunked") != -1) {
216                     outsream = new ChunkedOutputStream(outsream);
217                 }
218             }
219                         
220             byte[] tmp = new byte[1024];
221             int i = 0;
222             while ((i = content.read(tmp)) >= 0) {
223                 outsream.write(tmp, 0, i);
224             }        
225             if (outsream instanceof ChunkedOutputStream) {
226                 ((ChunkedOutputStream)outsream).finish();
227             }
228         }
229         outsream.flush();
230     }
231 
232     public int getSocketTimeout() throws SocketException {
233         return this.socket.getSoTimeout();
234     }
235     
236     public void setSocketTimeout(int timeout) throws SocketException {
237         this.socket.setSoTimeout(timeout);
238     }
239         
240 }
241