Coverage Report - org.mule.transport.http.HttpServerConnection
 
Classes in this File Line Coverage Branch Coverage Complexity
HttpServerConnection
0%
0/121
0%
0/62
3.562
 
 1  
 /*
 2  
  * $Id: HttpServerConnection.java 19191 2010-08-25 21:05:23Z tcarlson $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.transport.http;
 12  
 
 13  
 import org.mule.RequestContext;
 14  
 import org.mule.api.transformer.TransformerException;
 15  
 import org.mule.api.transport.Connector;
 16  
 import org.mule.api.transport.OutputHandler;
 17  
 import org.mule.util.SystemUtils;
 18  
 
 19  
 import java.io.DataOutputStream;
 20  
 import java.io.IOException;
 21  
 import java.io.InputStream;
 22  
 import java.io.OutputStream;
 23  
 import java.io.UnsupportedEncodingException;
 24  
 import java.net.Socket;
 25  
 import java.net.SocketException;
 26  
 import java.util.Iterator;
 27  
 
 28  
 import org.apache.commons.httpclient.ChunkedOutputStream;
 29  
 import org.apache.commons.httpclient.Header;
 30  
 import org.apache.commons.httpclient.HttpParser;
 31  
 import org.apache.commons.httpclient.StatusLine;
 32  
 import org.apache.commons.io.IOUtils;
 33  
 import org.apache.commons.logging.Log;
 34  
 import org.apache.commons.logging.LogFactory;
 35  
 
 36  
 /** A connection to the SimpleHttpServer. */
 37  
 public class HttpServerConnection
 38  
 {
 39  0
     private static final Log logger = LogFactory.getLog(HttpServerConnection.class);
 40  
 
 41  
     private Socket socket;
 42  
     private final InputStream in;
 43  
     private final OutputStream out;
 44  
     // this should rather be isKeepSocketOpen as this is the main purpose of this flag
 45  0
     private boolean keepAlive = false;
 46  
     private final String encoding;
 47  
 
 48  
     public HttpServerConnection(final Socket socket, String encoding, HttpConnector connector) throws IOException
 49  
     {
 50  0
         super();
 51  
 
 52  0
         if (socket == null)
 53  
         {
 54  0
             throw new IllegalArgumentException("Socket may not be null");
 55  
         }
 56  
 
 57  0
         this.socket = socket;
 58  0
         setSocketTcpNoDelay();
 59  0
         this.socket.setKeepAlive(connector.isKeepAlive());
 60  
         
 61  0
         if (connector.getReceiveBufferSize() != Connector.INT_VALUE_NOT_SET
 62  
             && socket.getReceiveBufferSize() != connector.getReceiveBufferSize())
 63  
         {
 64  0
             socket.setReceiveBufferSize(connector.getReceiveBufferSize());            
 65  
         }
 66  0
         if (connector.getServerSoTimeout() != Connector.INT_VALUE_NOT_SET
 67  
             && socket.getSoTimeout() != connector.getServerSoTimeout())
 68  
         {
 69  0
             socket.setSoTimeout(connector.getServerSoTimeout());
 70  
         }
 71  
         
 72  0
         this.in = socket.getInputStream();
 73  0
         this.out = new DataOutputStream(socket.getOutputStream());
 74  0
         this.encoding = encoding;
 75  0
     }
 76  
 
 77  
     private void setSocketTcpNoDelay() throws IOException
 78  
     {
 79  
         try
 80  
         {
 81  0
             socket.setTcpNoDelay(true);
 82  
         }
 83  0
         catch (SocketException se)
 84  
         {
 85  0
             if (SystemUtils.IS_OS_SOLARIS || SystemUtils.IS_OS_SUN_OS)
 86  
             {
 87  
                 // this is a known Solaris bug, see
 88  
                 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6378870
 89  
                 
 90  0
                 if (logger.isDebugEnabled())
 91  
                 {
 92  0
                     logger.debug("Failed to set tcpNoDelay on socket", se);
 93  
                 }
 94  
             }
 95  
             else
 96  
             {
 97  0
                 throw se;
 98  
             }
 99  0
         }
 100  0
     }
 101  
 
 102  
     public synchronized void close()
 103  
     {
 104  
         try
 105  
         {
 106  0
             if (socket != null)
 107  
             {
 108  0
                 if (logger.isDebugEnabled())
 109  
                 {
 110  0
                     logger.debug("Closing: " + socket);
 111  
                 }
 112  
                 
 113  
                 try
 114  
                 {
 115  0
                     socket.shutdownOutput();
 116  
                 }
 117  0
                 catch (UnsupportedOperationException e)
 118  
                 {
 119  
                     //Can't shutdown in/output on SSL sockets
 120  0
                 }
 121  
                 
 122  0
                 if (in != null)
 123  
                 {
 124  0
                     in.close();
 125  
                 }
 126  0
                 if (out != null)
 127  
                 {
 128  0
                     out.close();
 129  
                 }
 130  0
                 socket.close();
 131  
             }
 132  
         }
 133  0
         catch (IOException e)
 134  
         {
 135  0
             if (logger.isDebugEnabled())
 136  
             {
 137  0
                 logger.debug("(Ignored) Error closing the socket: " + e.getMessage());
 138  
             }
 139  
         }
 140  
         finally
 141  
         {
 142  0
             socket = null;
 143  0
         }
 144  0
     }
 145  
 
 146  
     public synchronized boolean isOpen()
 147  
     {
 148  0
         return this.socket != null;
 149  
     }
 150  
 
 151  
     public void setKeepAlive(boolean b)
 152  
     {
 153  0
         this.keepAlive = b;
 154  0
     }
 155  
 
 156  
     public boolean isKeepAlive()
 157  
     {
 158  0
         return this.keepAlive;
 159  
     }
 160  
 
 161  
     public InputStream getInputStream()
 162  
     {
 163  0
         return this.in;
 164  
     }
 165  
 
 166  
     public OutputStream getOutputStream()
 167  
     {
 168  0
         return this.out;
 169  
     }
 170  
 
 171  
     /**
 172  
      * Returns the ResponseWriter used to write the output to the socket.
 173  
      *
 174  
      * @return This connection's ResponseWriter
 175  
      */
 176  
     public ResponseWriter getWriter() throws UnsupportedEncodingException
 177  
     {
 178  0
         return new ResponseWriter(out);
 179  
     }
 180  
 
 181  
     public HttpRequest readRequest() throws IOException
 182  
     {
 183  
         try
 184  
         {
 185  0
             String line = readLine();
 186  0
             if (line == null)
 187  
             {
 188  0
                 return null;
 189  
             }
 190  0
             return new HttpRequest(RequestLine.parseLine(line), HttpParser.parseHeaders(this.in, encoding), this.in, encoding);
 191  
         }
 192  0
         catch (IOException e)
 193  
         {
 194  0
             close();
 195  0
             throw e;
 196  
         }
 197  
     }
 198  
 
 199  
     public HttpResponse readResponse() throws IOException
 200  
     {
 201  
         try
 202  
         {
 203  0
             String line = readLine();
 204  0
             return new HttpResponse(new StatusLine(line), HttpParser.parseHeaders(this.in, encoding), this.in);
 205  
         }
 206  0
         catch (IOException e)
 207  
         {
 208  0
             close();
 209  0
             throw e;
 210  
         }
 211  
     }
 212  
 
 213  
     private String readLine() throws IOException
 214  
     {
 215  
         String line;
 216  
 
 217  
         do
 218  
         {
 219  0
             line = HttpParser.readLine(in, encoding);
 220  
         }
 221  0
         while (line != null && line.length() == 0);
 222  
 
 223  0
         if (line == null)
 224  
         {
 225  0
             setKeepAlive(false);
 226  0
             return null;
 227  
         }
 228  
 
 229  0
         return line;
 230  
     }
 231  
 
 232  
     public void writeRequest(final HttpRequest request) throws IOException
 233  
     {
 234  0
         if (request == null)
 235  
         {
 236  0
             return;
 237  
         }
 238  0
         ResponseWriter writer = new ResponseWriter(this.out, encoding);
 239  0
         writer.println(request.getRequestLine().toString());
 240  0
         Iterator item = request.getHeaderIterator();
 241  0
         while (item.hasNext())
 242  
         {
 243  0
             Header header = (Header) item.next();
 244  0
             writer.print(header.toExternalForm());
 245  0
         }
 246  0
         writer.println();
 247  0
         writer.flush();
 248  
 
 249  0
         OutputStream outstream = this.out;
 250  0
         InputStream content = request.getBody();
 251  0
         if (content != null)
 252  
         {
 253  0
             Header transferenc = request.getFirstHeader(HttpConstants.HEADER_TRANSFER_ENCODING);
 254  0
             if (transferenc != null)
 255  
             {
 256  0
                 request.removeHeaders(HttpConstants.HEADER_CONTENT_LENGTH);
 257  0
                 if (transferenc.getValue().indexOf(HttpConstants.TRANSFER_ENCODING_CHUNKED) != -1)
 258  
                 {
 259  0
                     outstream = new ChunkedOutputStream(outstream);
 260  
                 }
 261  
             }
 262  
 
 263  0
             IOUtils.copy(content, outstream);
 264  
 
 265  0
             if (outstream instanceof ChunkedOutputStream)
 266  
             {
 267  0
                 ((ChunkedOutputStream) outstream).finish();
 268  
             }
 269  
         }
 270  
 
 271  0
         outstream.flush();
 272  0
     }
 273  
 
 274  
     public void writeResponse(final HttpResponse response) throws IOException, TransformerException
 275  
     {
 276  0
         if (response == null)
 277  
         {
 278  0
             return;
 279  
         }
 280  
         
 281  0
         if (!response.isKeepAlive()) 
 282  
         {
 283  0
             Header header = new Header(HttpConstants.HEADER_CONNECTION, "close");
 284  0
             response.setHeader(header);
 285  
         }
 286  
         
 287  0
         setKeepAlive(response.isKeepAlive());
 288  
         
 289  0
         ResponseWriter writer = new ResponseWriter(this.out, encoding);
 290  0
         OutputStream outstream = this.out;
 291  
 
 292  0
         writer.println(response.getStatusLine());
 293  0
         Iterator item = response.getHeaderIterator();
 294  0
         while (item.hasNext())
 295  
         {
 296  0
             Header header = (Header) item.next();
 297  0
             writer.print(header.toExternalForm());
 298  0
         }
 299  0
         writer.println();
 300  0
         writer.flush();
 301  
 
 302  0
         OutputHandler content = response.getBody();
 303  0
         if (content != null)
 304  
         {
 305  0
             Header transferenc = response.getFirstHeader(HttpConstants.HEADER_TRANSFER_ENCODING);
 306  0
             if (transferenc != null)
 307  
             {
 308  0
                 response.removeHeaders(HttpConstants.HEADER_CONTENT_LENGTH);
 309  0
                 if (transferenc.getValue().indexOf(HttpConstants.TRANSFER_ENCODING_CHUNKED) != -1)
 310  
                 {
 311  0
                     outstream = new ChunkedOutputStream(outstream);
 312  
                 }
 313  
             }
 314  
 
 315  0
             content.write(RequestContext.getEvent(), outstream);
 316  
 
 317  0
             if (outstream instanceof ChunkedOutputStream)
 318  
             {
 319  0
                 ((ChunkedOutputStream) outstream).finish();
 320  
             }
 321  
         }
 322  
 
 323  0
         outstream.flush();
 324  0
     }
 325  
 
 326  
     public int getSocketTimeout() throws SocketException
 327  
     {
 328  0
         return this.socket.getSoTimeout();
 329  
     }
 330  
 
 331  
     public void setSocketTimeout(int timeout) throws SocketException
 332  
     {
 333  0
         this.socket.setSoTimeout(timeout);
 334  0
     }
 335  
 }