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