View Javadoc

1   /*
2    * $Id: HttpServerConnection.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
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   * A connection to the SimpleHttpServer.
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      * Returns the ResponseWriter used to write the output to the socket.
119      * 
120      * @return This connection's ResponseWriter
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 }