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