1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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.HttpException;
41 import org.apache.commons.httpclient.HttpParser;
42 import org.apache.commons.httpclient.HttpStatus;
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45
46 /***
47 * A connection to the SimpleHttpServer.
48 *
49 * @author Christian Kohlschuetter
50 */
51 public class SimpleHttpServerConnection implements Runnable {
52
53 private static final Log LOG = LogFactory.getLog(SimpleHttpServerConnection.class);
54 private static final String HTTP_ELEMENT_CHARSET = "US-ASCII";
55
56 private SimpleHttpServer server;
57 private Socket socket;
58 private InputStream in;
59 private OutputStream out;
60
61 private int requestNo = 0;
62
63 private boolean keepAlive = false;
64
65 public SimpleHttpServerConnection(SimpleHttpServer server, Socket socket) throws IOException {
66 this.server = server;
67 this.socket = socket;
68 this.in = socket.getInputStream();
69 this.out = socket.getOutputStream();
70 }
71
72 public synchronized void destroy() {
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 server.removeConnection(this);
84 }
85
86 public void run() {
87 requestNo = 0;
88 try {
89 do {
90 keepAlive = false;
91
92 ++this.requestNo;
93 readRequest();
94 } while (keepAlive);
95 } catch (IOException e) {
96 LOG.error("I/O error: " + e.getMessage());
97 } finally {
98 destroy();
99 }
100 }
101
102 /***
103 * Requests to close connection after processing this request.
104 */
105 public void connectionClose() {
106 keepAlive = false;
107 }
108
109 /***
110 * Requests to keep the connection alive after processing this request
111 * (must be re-issued for every request if permanent keep-alive is
112 * desired).
113 *
114 */
115 public void connectionKeepAlive() {
116 keepAlive = true;
117 }
118
119 /***
120 * Returns the ResponseWriter used to write the output to the socket.
121 *
122 * @return This connection's ResponseWriter
123 */
124 public ResponseWriter getWriter() {
125 try {
126 return new ResponseWriter(out);
127 } catch (UnsupportedEncodingException e) {
128 throw new RuntimeException(e.toString());
129 }
130 }
131
132 /***
133 * Returns the number of requests processed (including the current one) for
134 * this connection.
135 *
136 * @return
137 */
138 public int getRequestNumber() {
139 return requestNo;
140 }
141
142 private void readRequest() throws IOException {
143 String line;
144 do {
145 line = HttpParser.readLine(in, HTTP_ELEMENT_CHARSET);
146 } while (line != null && line.length() == 0);
147
148 if (line == null) {
149 connectionClose();
150 return;
151 }
152
153 SimpleRequest request = null;
154 try {
155 request = new SimpleRequest(
156 RequestLine.parseLine(line),
157 HttpParser.parseHeaders(in, HTTP_ELEMENT_CHARSET),
158 null);
159 } catch (HttpException e) {
160 connectionClose();
161 SimpleResponse response = ErrorResponse.getInstance().
162 getResponse(HttpStatus.SC_BAD_REQUEST);
163 server.writeResponse(this, response);
164 return;
165 } catch (IOException e) {
166 connectionClose();
167 LOG.error("I/O error processing request", e);
168 return;
169 }
170 server.processRequest(this, request);
171 out.flush();
172 }
173
174 public InputStream getInputStream() {
175 return in;
176 }
177
178 public OutputStream getOutputStream() {
179 return out;
180 }
181
182 public boolean isKeepAlive() {
183 return this.keepAlive;
184 }
185
186 }
187