1   /*
2    * $Header: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/server/SimpleHttpServerConnection.java,v 1.8 2004/05/11 20:43:55 olegk Exp $
3    * $Revision: 1.8 $
4    * $Date: 2004/05/11 20:43:55 $
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   * [Additional notices, if required by prior licensing conditions]
29   *
30   */
31  
32  package org.apache.commons.httpclient.server;
33  
34  import java.io.IOException;
35  import java.io.InputStream;
36  import java.io.OutputStream;
37  import java.io.UnsupportedEncodingException;
38  import java.net.Socket;
39  
40  import org.apache.commons.httpclient.HttpParser;
41  import org.apache.commons.httpclient.HttpStatus;
42  import org.apache.commons.logging.Log;
43  import org.apache.commons.logging.LogFactory;
44  
45  /***
46   * A connection to the SimpleHttpServer.
47   * 
48   * @author Christian Kohlschuetter
49   */
50  public class SimpleHttpServerConnection implements Runnable {
51  
52      private static final Log LOG = LogFactory.getLog(SimpleHttpServerConnection.class);
53      private static final String HTTP_ELEMENT_CHARSET = "US-ASCII";
54  
55      private SimpleHttpServer server;
56      private Socket socket;
57      private InputStream in;
58      private OutputStream out;
59  
60      private int requestNo = 0;
61  
62      private boolean keepAlive = false;
63  
64      public SimpleHttpServerConnection(SimpleHttpServer server, Socket socket) throws IOException {
65          this.server = server;
66          this.socket = socket;
67          this.in = socket.getInputStream();
68          this.out = socket.getOutputStream();
69      }
70  
71      public void destroy() {
72          try {
73              if (socket != null) {
74                  in.close();
75                  out.close();
76                  socket.close();
77                  socket = null;
78              }
79          } catch (IOException e) {
80              // fail("Unexpected exception: " + e);
81          }
82          server.removeConnection(this);
83      }
84  
85      public void run() {
86          requestNo = 0;
87          try {
88              do {
89                  keepAlive = false;
90  
91                  ++this.requestNo;
92                  readRequest();
93              } while (keepAlive);
94          } catch (IOException e) {
95              LOG.error("I/O error: " + e.getMessage());
96          } finally {
97              destroy();
98          }
99      }
100 
101     /***
102      * Requests to close connection after processing this request.
103      */
104     public void connectionClose() {
105         keepAlive = false;
106     }
107 
108     /***
109      * Requests to keep the connection alive after processing this request
110      * (must be re-issued for every request if permanent keep-alive is
111      * desired).
112      *  
113      */
114     public void connectionKeepAlive() {
115         keepAlive = true;
116     }
117 
118     /***
119      * Returns the ResponseWriter used to write the output to the socket.
120      * 
121      * @return This connection's ResponseWriter
122      */
123     public ResponseWriter getWriter() {
124         try {
125             return new ResponseWriter(out);
126         } catch (UnsupportedEncodingException e) {
127             throw new RuntimeException(e.toString());
128         }
129     }
130 
131     /***
132      * Returns the number of requests processed (including the current one) for
133      * this connection.
134      * 
135      * @return
136      */
137     public int getRequestNumber() {
138         return requestNo;
139     }
140 
141     private void readRequest() throws IOException {
142         String line;
143         do {
144             line = HttpParser.readLine(in, HTTP_ELEMENT_CHARSET);
145         } while (line != null && line.length() == 0);
146 
147         if (line == null) {
148             connectionClose();
149             return;
150         }
151 
152         SimpleRequest request = null;
153         try {
154             request = new SimpleRequest( 
155                 RequestLine.parseLine(line),
156                 HttpParser.parseHeaders(in, HTTP_ELEMENT_CHARSET),
157                 null);
158         } catch (IOException e) {
159             connectionClose();
160             SimpleResponse response = ErrorResponse.getInstance().
161                 getResponse(HttpStatus.SC_BAD_REQUEST);
162             server.writeResponse(this, response);
163             return;
164         }
165         server.processRequest(this, request);
166         out.flush();
167     }
168 
169     public InputStream getInputStream() {
170         return in;
171     }
172 
173     public OutputStream getOutputStream() {
174         return out;
175     }
176 
177     public boolean isKeepAlive() {
178         return this.keepAlive;
179     }
180 
181 }
182