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 import java.net.SocketException;
40
41 import org.apache.commons.httpclient.Header;
42 import org.apache.commons.httpclient.HttpParser;
43 import org.apache.commons.httpclient.HttpStatus;
44 import org.apache.commons.logging.Log;
45 import org.apache.commons.logging.LogFactory;
46
47 /***
48 * A connection to the SimpleHttpServer.
49 *
50 * @author Christian Kohlschuetter
51 */
52 public class SimpleHttpServerConnection implements Runnable {
53
54 private static final Log LOG = LogFactory.getLog(SimpleHttpServerConnection.class);
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 private RequestLine requestLine;
66
67 private Header[] headers;
68
69 public SimpleHttpServerConnection(SimpleHttpServer server, Socket socket) throws IOException {
70 this.server = server;
71 this.socket = socket;
72 this.in = socket.getInputStream();
73 this.out = socket.getOutputStream();
74 }
75
76 public void destroy() {
77 try {
78 if(socket != null) {
79 in.close();
80 out.close();
81 socket.close();
82 socket = null;
83 }
84 } catch(IOException e) {
85
86 }
87 server.removeConnection(this);
88 }
89
90 public void run() {
91 requestNo = 0;
92 try {
93 do {
94 keepAlive = false;
95
96 ++this.requestNo;
97 readRequest();
98 } while(keepAlive);
99 } catch (SocketException ignore) {
100 } catch (IOException e) {
101 LOG.error("ServerConnection read error", e);
102 throw new RuntimeException(e.getMessage());
103 } finally {
104 destroy();
105 }
106 }
107
108 /***
109 * Requests to close connection after processing this request.
110 */
111 public void connectionClose() {
112 keepAlive = false;
113 }
114
115 /***
116 * Requests to keep the connection alive after processing this request
117 * (must be re-issued for every request if permanent keep-alive is desired).
118 *
119 */
120 public void connectionKeepAlive() {
121 keepAlive = true;
122 }
123
124 /***
125 * Returns the ResponseWriter used to write the output to the socket.
126 *
127 * @return This connection's ResponseWriter
128 */
129 public ResponseWriter getWriter() {
130 try {
131 return new ResponseWriter(out);
132 } catch (UnsupportedEncodingException e) {
133 throw new RuntimeException(e.toString());
134 }
135 }
136
137 /***
138 * Returns the number of requests processed (including the current one)
139 * for this connection.
140 *
141 * @return
142 */
143 public int getRequestNumber() {
144 return requestNo;
145 }
146
147 private void readRequest() throws IOException {
148 String line;
149 do {
150 line = HttpParser.readLine(in);
151 } while(line != null && line.length() == 0);
152
153 if(line == null) {
154 connectionClose();
155 return;
156 }
157
158 try {
159 requestLine = RequestLine.parseLine(line);
160 headers = HttpParser.parseHeaders(in);
161 } catch(IOException e) {
162 connectionClose();
163 ErrorResponse.getInstance().getResponse(HttpStatus.SC_BAD_REQUEST).processRequest(this);
164 return;
165 }
166 server.processRequest(this);
167 out.flush();
168 }
169
170 public Header[] getHeaders() {
171 Header[] copy = new Header[headers.length];
172 System.arraycopy(headers, 0, copy, 0, headers.length);
173 return copy;
174 }
175
176 public RequestLine getRequestLine() {
177 return requestLine;
178 }
179
180 public InputStream getInputStream() {
181 return in;
182 }
183
184 public OutputStream getOutputStream() {
185 return out;
186 }
187 }