    1   /*
    2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/server/SimpleHttpServerConnection.java,v 1.21 2004/12/11 22:35:26 olegk Exp $
    3    * $Revision: 480424 $
    4    * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
    5    *
    6    * ====================================================================
    7    *
    8    *  Licensed to the Apache Software Foundation (ASF) under one or more
    9    *  contributor license agreements.  See the NOTICE file distributed with
    10   *  this work for additional information regarding copyright ownership.
    11   *  The ASF licenses this file to You under the Apache License, Version 2.0
    12   *  (the "License"); you may not use this file except in compliance with
    13   *  the License.  You may obtain a copy of the License at
    14   *
    15   *      http://www.apache.org/licenses/LICENSE-2.0
    16   *
    17   *  Unless required by applicable law or agreed to in writing, software
    18   *  distributed under the License is distributed on an "AS IS" BASIS,
    19   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    20   *  See the License for the specific language governing permissions and
    21   *  limitations under the License.
    22   * ====================================================================
    23   *
    24   * This software consists of voluntary contributions made by many
    25   * individuals on behalf of the Apache Software Foundation.  For more
    26   * information on the Apache Software Foundation, please see
    27   * <http://www.apache.org/>.
    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