1
2
3
4
5
6
7
8
9
10
11 package org.mule.providers.http;
12
13 import org.mule.MuleManager;
14
15 import java.io.DataOutputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19 import java.io.UnsupportedEncodingException;
20 import java.net.Socket;
21 import java.net.SocketException;
22 import java.util.Iterator;
23
24 import org.apache.commons.httpclient.ChunkedOutputStream;
25 import org.apache.commons.httpclient.Header;
26 import org.apache.commons.httpclient.HttpParser;
27 import org.apache.commons.httpclient.StatusLine;
28 import org.apache.commons.io.IOUtils;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31
32
33
34
35 public class HttpServerConnection
36 {
37 private static final Log logger = LogFactory.getLog(HttpServerConnection.class);
38
39 private Socket socket;
40 private final InputStream in;
41 private final OutputStream out;
42 private boolean keepAlive = false;
43 private final String encoding;
44
45 public HttpServerConnection(final Socket socket) throws IOException
46 {
47 this(socket, MuleManager.getConfiguration().getEncoding());
48 }
49
50 public HttpServerConnection(final Socket socket, String encoding) throws IOException
51 {
52 super();
53
54 if (socket == null)
55 {
56 throw new IllegalArgumentException("Socket may not be null");
57 }
58
59 this.socket = socket;
60 this.socket.setTcpNoDelay(true);
61 this.in = socket.getInputStream();
62 this.out = new DataOutputStream(socket.getOutputStream());
63 this.encoding = encoding;
64 }
65
66 public void close()
67 {
68 try
69 {
70 if (socket != null)
71 {
72 if (logger.isDebugEnabled())
73 {
74 logger.debug("Closing: " + socket);
75 }
76 socket.close();
77 }
78 }
79 catch (IOException e)
80 {
81 if (logger.isDebugEnabled())
82 {
83 logger.debug("(Ignored) Error closing the socket: " + e.getMessage());
84 }
85 }
86 finally
87 {
88 socket = null;
89 }
90 }
91
92 public synchronized boolean isOpen()
93 {
94 return this.socket != null;
95 }
96
97 public void setKeepAlive(boolean b)
98 {
99 this.keepAlive = b;
100 }
101
102 public boolean isKeepAlive()
103 {
104 return this.keepAlive;
105 }
106
107 public InputStream getInputStream()
108 {
109 return this.in;
110 }
111
112 public OutputStream getOutputStream()
113 {
114 return this.out;
115 }
116
117
118
119
120
121
122 public ResponseWriter getWriter() throws UnsupportedEncodingException
123 {
124 return new ResponseWriter(out);
125 }
126
127 public HttpRequest readRequest() throws IOException
128 {
129 try
130 {
131 String line = readLine();
132 if (line == null)
133 {
134 return null;
135 }
136 return new HttpRequest(RequestLine.parseLine(line), HttpParser.parseHeaders(this.in, encoding), this.in);
137 }
138 catch (IOException e)
139 {
140 close();
141 throw e;
142 }
143 }
144
145 public HttpResponse readResponse() throws IOException
146 {
147 try
148 {
149 String line = readLine();
150 return new HttpResponse(new StatusLine(line), HttpParser.parseHeaders(this.in, encoding), this.in);
151 }
152 catch (IOException e)
153 {
154 close();
155 throw e;
156 }
157 }
158
159 private String readLine() throws IOException
160 {
161 String line;
162
163 do
164 {
165 line = HttpParser.readLine(in, encoding);
166 }
167 while (line != null && line.length() == 0);
168
169 if (line == null)
170 {
171 setKeepAlive(false);
172 return null;
173 }
174
175 return line;
176 }
177
178 public void writeRequest(final HttpRequest request) throws IOException
179 {
180 if (request == null)
181 {
182 return;
183 }
184 ResponseWriter writer = new ResponseWriter(this.out, encoding);
185 writer.println(request.getRequestLine().toString());
186 Iterator item = request.getHeaderIterator();
187 while (item.hasNext())
188 {
189 Header header = (Header) item.next();
190 writer.print(header.toExternalForm());
191 }
192 writer.println();
193 writer.flush();
194
195 OutputStream outstream = this.out;
196 InputStream content = request.getBody();
197 if (content != null)
198 {
199 Header transferenc = request.getFirstHeader(HttpConstants.HEADER_TRANSFER_ENCODING);
200 if (transferenc != null)
201 {
202 request.removeHeaders(HttpConstants.HEADER_CONTENT_LENGTH);
203 if (transferenc.getValue().indexOf(HttpConstants.TRANSFER_ENCODING_CHUNKED) != -1)
204 {
205 outstream = new ChunkedOutputStream(outstream);
206 }
207 }
208
209 IOUtils.copy(content, outstream);
210
211 if (outstream instanceof ChunkedOutputStream)
212 {
213 ((ChunkedOutputStream) outstream).finish();
214 }
215 }
216
217 outstream.flush();
218 }
219
220 public void writeResponse(final HttpResponse response) throws IOException
221 {
222 if (response == null)
223 {
224 return;
225 }
226
227 setKeepAlive(response.isKeepAlive());
228 ResponseWriter writer = new ResponseWriter(this.out, encoding);
229 OutputStream outstream = this.out;
230
231 writer.println(response.getStatusLine());
232 Iterator item = response.getHeaderIterator();
233 while (item.hasNext())
234 {
235 Header header = (Header) item.next();
236 writer.print(header.toExternalForm());
237 }
238
239 writer.println();
240 writer.flush();
241
242 InputStream content = response.getBody();
243 if (content != null)
244 {
245 Header transferenc = response.getFirstHeader(HttpConstants.HEADER_TRANSFER_ENCODING);
246 if (transferenc != null)
247 {
248 response.removeHeaders(HttpConstants.HEADER_CONTENT_LENGTH);
249 if (transferenc.getValue().indexOf(HttpConstants.TRANSFER_ENCODING_CHUNKED) != -1)
250 {
251 outstream = new ChunkedOutputStream(outstream);
252 }
253 }
254
255 IOUtils.copy(content, outstream);
256
257 if (outstream instanceof ChunkedOutputStream)
258 {
259 ((ChunkedOutputStream) outstream).finish();
260 }
261 }
262
263 outstream.flush();
264 }
265
266 public int getSocketTimeout() throws SocketException
267 {
268 return this.socket.getSoTimeout();
269 }
270
271 public void setSocketTimeout(int timeout) throws SocketException
272 {
273 this.socket.setSoTimeout(timeout);
274 }
275 }