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