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 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