You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by py...@apache.org on 2007/07/03 08:08:25 UTC

svn commit: r552679 [2/2] - in /harmony/enhanced/classlib/trunk/modules/luni: ./ src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/ src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/ src/test/api/common/org/apache...

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java?view=diff&rev=552679&r1=552678&r2=552679
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java Mon Jul  2 23:08:23 2007
@@ -161,6 +161,48 @@
     }
 
     /**
+     * Checks if HTTPS connection performs initial SSL handshake with the
+     * server working over SSL, sends encrypted HTTP request,
+     * and receives expected HTTP response. After that it checks that the
+     * established connection is persistent.
+     * After HTTPS session if finished
+     * test checks connection state parameters established by
+     * HttpsURLConnection.
+     */
+    public void testHttpsPersistentConnection() throws Throwable {
+        // set up the properties defining the default values needed by SSL stuff
+        setUpStoreProperties();
+
+        try {
+            // create the SSL server socket acting as a server
+            SSLContext ctx = getContext();
+            ServerSocket ss = ctx.getServerSocketFactory()
+                    .createServerSocket(0);
+
+            // create the HostnameVerifier to check hostname verification
+            TestHostnameVerifier hnv = new TestHostnameVerifier();
+            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+
+            // create url connection to be tested
+            URL url = new URL("https://localhost:" + ss.getLocalPort());
+            HttpsURLConnection connection = (HttpsURLConnection) url
+                    .openConnection();
+
+            // perform the interaction between the peers
+            SSLSocket peerSocket = (SSLSocket) doPersistentInteraction(connection, ss);
+
+            // check the connection state
+            checkConnectionStateParameters(connection, peerSocket);
+
+            // should silently exit
+            connection.connect();
+        } finally {
+            // roll the properties back to system values
+            tearDownStoreProperties();
+        }
+    }
+
+    /**
      * Tests the behaviour of HTTPS connection in case of unavailability
      * of requested resource.
      */
@@ -408,6 +450,43 @@
     }
 
     /**
+     * Tests the behaviour in case of sending the data to the server 
+     * over persistent connection.
+     */
+    public void testPersistence_doOutput() throws Throwable {
+        // setting up the properties pointing to the key/trust stores
+        setUpStoreProperties();
+
+        try {
+            // create the SSLServerSocket which will be used by server side
+            SSLServerSocket ss = (SSLServerSocket) getContext()
+                    .getServerSocketFactory().createServerSocket(0);
+
+            // create the HostnameVerifier to check that Hostname verification
+            // is done
+            TestHostnameVerifier hnv = new TestHostnameVerifier();
+            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+
+            // create HttpsURLConnection to be tested
+            URL url = new URL("https://localhost:" + ss.getLocalPort());
+            HttpsURLConnection connection = (HttpsURLConnection) url
+                    .openConnection();
+            connection.setDoOutput(true);
+
+            // perform the interaction between the peers and check the results
+            SSLSocket peerSocket = (SSLSocket) 
+                doPersistentInteraction(connection, ss);
+            checkConnectionStateParameters(connection, peerSocket);
+
+            // should silently exit
+            connection.connect();
+        } finally {
+            // roll the properties back to system values
+            tearDownStoreProperties();
+        }
+    }
+
+    /**
      * Tests HTTPS connection process made through the proxy server.
      */
     public void testProxyConnection() throws Throwable {
@@ -444,6 +523,43 @@
 
     /**
      * Tests HTTPS connection process made through the proxy server.
+     * Checks that persistent connection to the host exists and can
+     * be used no in spite of explicit Proxy specifying.
+     */
+    public void testPersistentProxyConnection() throws Throwable {
+        // setting up the properties pointing to the key/trust stores
+        setUpStoreProperties();
+
+        try {
+            // create the SSLServerSocket which will be used by server side
+            ServerSocket ss = new ServerSocket(0);
+
+            // create the HostnameVerifier to check that Hostname verification
+            // is done
+            TestHostnameVerifier hnv = new TestHostnameVerifier();
+            HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+
+            // create HttpsURLConnection to be tested
+            URL url = new URL("https://requested.host:55556/requested.data");
+            HttpsURLConnection connection = (HttpsURLConnection) url
+                    .openConnection(new Proxy(Proxy.Type.HTTP,
+                            new InetSocketAddress("localhost", ss
+                                    .getLocalPort())));
+
+            // perform the interaction between the peers and check the results
+            SSLSocket peerSocket = (SSLSocket) doPersistentInteraction(connection, ss);
+            checkConnectionStateParameters(connection, peerSocket);
+
+            // should silently exit
+            connection.connect();
+        } finally {
+            // roll the properties back to system values
+            tearDownStoreProperties();
+        }
+    }
+
+    /**
+     * Tests HTTPS connection process made through the proxy server.
      * Proxy server needs authentication.
      */
     public void testProxyAuthConnection() throws Throwable {
@@ -568,7 +684,7 @@
 
             // perform the interaction between the peers and check the results
             SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss,
-                    OK_CODE, true);
+                    OK_CODE);
             checkConnectionStateParameters(connection, peerSocket);
         } finally {
             // roll the properties back to system values
@@ -603,8 +719,7 @@
 
             // perform the interaction between the peers and check the results
             try {
-                doInteraction(connection, ss, AUTHENTICATION_REQUIRED_CODE,
-                        true);
+                doInteraction(connection, ss, AUTHENTICATION_REQUIRED_CODE);
             } catch (IOException e) {
                 // SSL Tunnelling failed
                 if (DO_LOG) {
@@ -704,10 +819,10 @@
     }
 
     /**
-     * Returns the file name of the key/trust store. The key store file 
+     * Returns the file name of the key/trust store. The key store file
      * (named as "key_store." + extension equals to the default KeyStore
      * type installed in the system in lower case) is searched in classpath.
-     * @throws AssertionFailedError if property was not set 
+     * @throws AssertionFailedError if property was not set
      * or file does not exist.
      */
     private static String getKeyStoreFileName() throws Exception {
@@ -826,7 +941,7 @@
     public static Socket doInteraction(
             final HttpURLConnection clientConnection,
             final ServerSocket serverSocket) throws Throwable {
-        return doInteraction(clientConnection, serverSocket, OK_CODE, false);
+        return doInteraction(clientConnection, serverSocket, OK_CODE, false, false);
     }
 
     /**
@@ -839,7 +954,31 @@
             final ServerSocket serverSocket, final int responseCode)
             throws Throwable {
         return doInteraction(clientConnection, serverSocket, responseCode,
-                false);
+                false, false);
+    }
+
+    /**
+     * Performs interaction between client's HttpURLConnection and
+     * servers side (ServerSocket) over persistent connection.
+     */
+    public static Socket doPersistentInteraction(
+            final HttpURLConnection clientConnection,
+            final ServerSocket serverSocket) throws Throwable {
+        return doInteraction(clientConnection, serverSocket, OK_CODE,
+                false, true);
+    }
+
+    /**
+     * Performs interaction between client's HttpURLConnection and
+     * servers side (ServerSocket) over persistent connection.
+     * Server will response with specified response code.
+     */
+    public static Socket doPersistentInteraction(
+            final HttpURLConnection clientConnection,
+            final ServerSocket serverSocket, final int responseCode)
+            throws Throwable {
+        return doInteraction(clientConnection, serverSocket, responseCode,
+                false, true);
     }
 
     /**
@@ -852,7 +991,8 @@
     public static Socket doInteraction(
             final HttpURLConnection clientConnection,
             final ServerSocket serverSocket, final int responseCode,
-            final boolean doAuthentication) throws Throwable {
+            final boolean doAuthentication, 
+            final boolean checkPersistence) throws Throwable {
 
         // set up the connection
         clientConnection.setDoInput(true);
@@ -860,7 +1000,7 @@
         clientConnection.setReadTimeout(TIMEOUT);
 
         ServerWork server = new ServerWork(serverSocket, responseCode,
-                doAuthentication);
+                doAuthentication, checkPersistence);
 
         ClientConnectionWork client = new ClientConnectionWork(clientConnection);
 
@@ -868,8 +1008,6 @@
         client.start();
 
         client.join();
-        server.join();
-
         if (client.thrown != null) {
             if (responseCode != OK_CODE) { // not OK response expected
                 // it is probably expected exception, keep it as is
@@ -883,6 +1021,30 @@
                 throw new Exception(client.thrown);
             }
         }
+
+        if (checkPersistence) {
+            ClientConnectionWork client2 =
+                new ClientConnectionWork((HttpURLConnection)
+                        clientConnection.getURL().openConnection());
+            client2.start();
+            client2.join();
+            if (client2.thrown != null) {
+                if (responseCode != OK_CODE) { // not OK response expected
+                    // it is probably expected exception, keep it as is
+                    throw client2.thrown;
+                }
+                if ((client2.thrown instanceof SocketTimeoutException)
+                        && (server.thrown != null)) {
+                    // server's exception is more informative in this case
+                    throw new Exception(server.thrown);
+                } else {
+                    throw new Exception(client2.thrown);
+                }
+            }
+        }
+
+        server.join();
+
         if (server.thrown != null) {
             throw server.thrown;
         }
@@ -998,6 +1160,9 @@
         // indicates if the server needs proxy authentication
         private boolean needProxyAuthentication;
 
+        // do we check for connection persistence
+        private boolean checkPersistence;
+
         // response code to be send to the client peer
         private int responseCode;
 
@@ -1007,7 +1172,7 @@
         public ServerWork(ServerSocket serverSocket) {
             // the server does not require proxy authentication
             // and sends OK_CODE (OK) response code
-            this(serverSocket, OK_CODE, false);
+            this(serverSocket, OK_CODE, false, false);
         }
 
         /**
@@ -1018,10 +1183,11 @@
          * indicates if the server needs proxy authentication
          */
         public ServerWork(ServerSocket serverSocket, int responseCode,
-                boolean needProxyAuthentication) {
+                boolean needProxyAuthentication, boolean checkPersistence) {
             this.serverSocket = serverSocket;
             this.responseCode = responseCode;
             this.needProxyAuthentication = needProxyAuthentication;
+            this.checkPersistence = checkPersistence;
             // will act as a proxy server if the specified server socket
             // is not a secure server socket
             if (serverSocket instanceof SSLServerSocket) {
@@ -1073,105 +1239,120 @@
                 InputStream is = peerSocket.getInputStream();
                 OutputStream os = peerSocket.getOutputStream();
 
-                num = is.read(buff);
-                String message = new String(buff, 0, num);
-                log("Got request:\n" + message);
-                log("------------------");
-
-                if (!actAsProxy) {
-                    // Act as Server (not Proxy) side
-                    if (message.startsWith("POST")) {
-                        // client connection sent some data
-                        log("try to read client data");
-                        num = is.read(buff);
-                        message = new String(buff, 0, num);
-                        log("client's data: '" + message + "'");
-                        // check the received data
-                        assertEquals(clientsData, message);
+                // how many times established connection will be used
+                int number_of_uses = checkPersistence ? 2 : 1;
+                for (int it=0; it<number_of_uses; it++) {
+                    if (checkPersistence) {
+                        log("==========================================");
+                        log("Use established connection for "+(it+1)+" time");
                     }
-                    // just send the response
-                    os
-                            .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail)
-                                    .getBytes());
-                    // and return
-                    log("Work is DONE");
-                    return;
-                }
 
-                // Do proxy work
-                if (needProxyAuthentication) {
-                    log("Authentication required ...");
-                    // send Authentication Request
-                    os.write(respAuthenticationRequired.getBytes());
-                    // read response
                     num = is.read(buff);
-                    if (num == -1) {
-                        // this connection was closed, 
-                        // do clean up and create new one:
-                        closeSocket(peerSocket);
-                        peerSocket = serverSocket.accept();
-                        peerSocket.setSoTimeout(TIMEOUT);
-                        log("New client connection ACCEPTED");
-                        is = peerSocket.getInputStream();
-                        os = peerSocket.getOutputStream();
+                    String message = new String(buff, 0, num);
+                    log("Got request:\n" + message);
+                    log("------------------");
+
+                    if (!actAsProxy) {
+                        // Act as Server (not Proxy) side
+                        if (message.startsWith("POST")) {
+                            // client connection sent some data
+                            log("try to read client data");
+                            num = is.read(buff);
+                            message = new String(buff, 0, num);
+                            log("client's data: '" + message + "'");
+                            // check the received data
+                            assertEquals(clientsData, message);
+                        }
+                        // just send the response
+                        os.write(("HTTP/1.1 " + responseCode + "\n" 
+                                    + httpsResponseTail).getBytes());
+                        log("Simple NON-Proxy work is DONE");
+                        continue;
+                    }
+
+                    // Do proxy work
+                    if (needProxyAuthentication) {
+                        log("Authentication required ...");
+                        // send Authentication Request
+                        os.write(respAuthenticationRequired.getBytes());
+                        // read response
                         num = is.read(buff);
+                        if (num == -1) {
+                            // this connection was closed, 
+                            // do clean up and create new one:
+                            closeSocket(peerSocket);
+                            peerSocket = serverSocket.accept();
+                            peerSocket.setSoTimeout(TIMEOUT);
+                            log("New client connection ACCEPTED");
+                            is = peerSocket.getInputStream();
+                            os = peerSocket.getOutputStream();
+                            num = is.read(buff);
+                        }
+                        message = new String(buff, 0, num);
+                        log("Got authenticated request:\n" + message);
+                        log("------------------");
+                        // check provided authorization credentials
+                        assertTrue("Received message does not contain "
+                                + "authorization credentials", message
+                                .toLowerCase().indexOf("proxy-authorization:") > 0);
                     }
-                    message = new String(buff, 0, num);
-                    log("Got authenticated request:\n" + message);
-                    log("------------------");
-                    // check provided authorization credentials
-                    assertTrue("Received message does not contain "
-                            + "authorization credentials", message
-                            .toLowerCase().indexOf("proxy-authorization:") > 0);
-                }
 
-                // The content of this response will reach proxied HTTPUC
-                // but will not reach proxied HTTPSUC
-                // In case of HTTP connection it will be the final message,
-                // in case of HTTPS connection this message will just indicate
-                // that connection with remote host has been done
-                // (i.e. SSL tunnel has been established).
-                os.write(plainResponse.getBytes());
-                log("Sent OK RESPONSE");
-
-                if (message.startsWith("CONNECT")) { // request for SSL tunnel
-                    log("Perform SSL Handshake...");
-                    // create sslSocket acting as a remote server peer
-                    SSLSocket sslSocket = (SSLSocket) getContext()
-                            .getSocketFactory().createSocket(peerSocket,
-                                    "localhost", peerSocket.getPort(), true); // do autoclose
-                    sslSocket.setUseClientMode(false);
-                    // demand client authentication
-                    sslSocket.setNeedClientAuth(true);
-                    sslSocket.startHandshake();
-                    peerSocket = sslSocket;
-                    is = peerSocket.getInputStream();
-                    os = peerSocket.getOutputStream();
+                    if (peerSocket instanceof SSLSocket) {
+                        // it will be so if we are have second iteration 
+                        // over persistent connection
+                        os.write(("HTTP/1.1 " + OK_CODE
+                                    + "\n" + httpsResponseTail).getBytes());
+                        log("Sent OK RESPONSE over SSL");
+                    } else {
+                        // The content of this response will reach proxied
+                        // HTTPUC but will not reach proxied HTTPSUC
+                        // In case of HTTP connection it will be the final 
+                        // message, in case of HTTPS connection this message
+                        // will just indicate that connection with remote
+                        // host has been done
+                        // (i.e. SSL tunnel has been established).
+                        os.write(plainResponse.getBytes());
+                        log("Sent OK RESPONSE");
+                    }
 
-                    // read the HTTP request sent by secure connection
-                    // (HTTPS request)
-                    num = is.read(buff);
-                    message = new String(buff, 0, num);
-                    log("[Remote Server] Request from SSL tunnel:\n" + message);
-                    log("------------------");
+                    if (message.startsWith("CONNECT")) { // request for SSL tunnel
+                        log("Perform SSL Handshake...");
+                        // create sslSocket acting as a remote server peer
+                        SSLSocket sslSocket = (SSLSocket) getContext()
+                                .getSocketFactory().createSocket(peerSocket,
+                                        "localhost", peerSocket.getPort(), true); // do autoclose
+                        sslSocket.setUseClientMode(false);
+                        // demand client authentication
+                        sslSocket.setNeedClientAuth(true);
+                        sslSocket.startHandshake();
+                        peerSocket = sslSocket;
+                        is = peerSocket.getInputStream();
+                        os = peerSocket.getOutputStream();
 
-                    if (message.startsWith("POST")) {
-                        // client connection sent some data
-                        log("[Remote Server] try to read client data");
+                        // read the HTTP request sent by secure connection
+                        // (HTTPS request)
                         num = is.read(buff);
                         message = new String(buff, 0, num);
-                        log("[Remote Server] client's data: '" + message + "'");
-                        // check the received data
-                        assertEquals(clientsData, message);
-                    }
+                        log("[Remote Server] Request from SSL tunnel:\n" + message);
+                        log("------------------");
 
-                    log("[Remote Server] Sending the response by SSL tunnel..");
-                    // send the response with specified response code
-                    os
-                            .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail)
-                                    .getBytes());
-                }
-                log("Work is DONE");
+                        if (message.startsWith("POST")) {
+                            // client connection sent some data
+                            log("[Remote Server] try to read client data");
+                            num = is.read(buff);
+                            message = new String(buff, 0, num);
+                            log("[Remote Server] client's data: '" + message + "'");
+                            // check the received data
+                            assertEquals(clientsData, message);
+                        }
+
+                        log("[Remote Server] Sending the response by SSL tunnel..");
+                        // send the response with specified response code
+                        os.write(("HTTP/1.1 " + responseCode 
+                                    + "\n" + httpsResponseTail).getBytes());
+                    }
+                    log("Work is DONE");
+                };
             } catch (Throwable e) {
                 if (DO_LOG) {
                     e.printStackTrace();
@@ -1222,7 +1403,7 @@
                 }
                 // read the content of HTTP(s) response
                 InputStream is = connection.getInputStream();
-                log("Input Stream obtained");
+                log("Input Stream obtained: "+is.getClass());
                 byte[] buff = new byte[2048];
                 int num = 0;
                 int byt = 0;

Added: harmony/enhanced/classlib/trunk/modules/luni/src/test/impl/org/apache/harmony/tests/internal/net/www/protocol/http/PersistenceTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/impl/org/apache/harmony/tests/internal/net/www/protocol/http/PersistenceTest.java?view=auto&rev=552679
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/test/impl/org/apache/harmony/tests/internal/net/www/protocol/http/PersistenceTest.java (added)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/test/impl/org/apache/harmony/tests/internal/net/www/protocol/http/PersistenceTest.java Mon Jul  2 23:08:23 2007
@@ -0,0 +1,549 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.tests.internal.net.www.protocol.http;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.HttpURLConnection;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection;
+import org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionManager;
+
+import tests.support.Support_HttpServer;
+import tests.support.Support_HttpServerSocket;
+import tests.support.Support_Jetty;
+import tests.support.Support_PortManager;
+import tests.support.Support_URLConnector;
+
+/**
+ * Tests for <code>HttpURLConnection</code> persistence.
+ * These tests depends on internal implementation.
+ */
+public class PersistenceTest extends TestCase {
+
+    private static final boolean DEBUG = false;
+
+    private final static Object bound = new Object();
+
+    private static int port;
+
+    static {
+        // run-once set up
+        try {
+            port = Support_Jetty.startDefaultHttpServer();
+        } catch (Exception e) {
+            fail("Exception during setup jetty : " + e.getMessage());
+        }
+    }
+
+    static class MockServer extends Thread {
+        ServerSocket serverSocket;
+        boolean accepted = false;
+        boolean started = false;
+
+        public MockServer(String name) throws IOException {
+            super(name);
+            serverSocket = new ServerSocket(0);
+            serverSocket.setSoTimeout(5000);
+        }
+
+        public int port() {
+            return serverSocket.getLocalPort();
+        }
+
+        @Override
+        public void run() {
+            try {
+                synchronized (bound) {
+                    started = true;
+                    bound.notify();
+                }
+                try {
+                    serverSocket.accept().close();
+                    accepted = true;
+                } catch (SocketTimeoutException ignore) {
+                }
+                serverSocket.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    static class MockHTTPServer extends MockServer {
+        // HTTP response codes
+        static final int OK_CODE = 200;
+        static final int NOT_FOUND_CODE = 404;
+        // how many times persistent connection will be used
+        // by server
+        int persUses;
+        // result code to be sent to client
+        int responseCode;
+        // response content to be sent to client
+        String response = "<html></html>";
+        // client's POST message
+        String clientPost = "Hello from client!";
+
+        public MockHTTPServer(String name, int persUses) throws IOException {
+            this(name, persUses, OK_CODE);
+        }
+
+        public MockHTTPServer(String name, int persUses,
+                int responseCode) throws IOException {
+            super(name);
+            this.persUses = persUses;
+            this.responseCode = responseCode;
+        }
+
+        public int port() {
+            return serverSocket.getLocalPort();
+        }
+
+        @Override
+        public void run() {
+            try {
+                synchronized (bound) {
+                    started = true;
+                    bound.notify();
+                }
+                InputStream is = null;
+                Socket client = null;
+                try {
+                    client = serverSocket.accept();
+                    accepted = true;
+                    for (int i=0; i<persUses; i++) {
+                        if (DEBUG) {
+                            System.out.println("*** Using connection for "
+                                    + (i+1) + " time ***");
+                        }
+                        byte[] buff = new byte[1024];
+                        is = client.getInputStream();
+                        int num = 0; // number of read bytes
+                        int bytik; // read byte value
+                        boolean wasEOL = false;
+                        // read header (until empty string)
+                        while (((bytik = is.read()) > 0)) {
+                            if (bytik == '\r') {
+                                bytik = is.read();
+                            }
+                            if (wasEOL && (bytik == '\n')) {
+                                break;
+                            }
+                            wasEOL = (bytik == '\n');
+                            buff[num++] = (byte) bytik;
+                        }
+                        //int num = is.read(buff);
+                        String message = new String(buff, 0, num);
+                        if (DEBUG) {
+                            System.out.println("---- Server got request: ----\n"
+                                + message + "-----------------------------");
+                        }
+
+                        // Act as Server (not Proxy) side
+                        if (message.startsWith("POST")) {
+                            // client connection sent some data
+                            // if the data was not read with header
+                            if (DEBUG) {
+                                System.out.println(
+                                        "---- Server read client's data: ----");
+                            }
+                            num = is.read(buff);
+                            message = new String(buff, 0, num);
+                            if (DEBUG) {
+                                System.out.println("'" + message + "'");
+                                System.out.println(
+                                        "------------------------------------");
+                            }
+                            // check the received data
+                            assertEquals(clientPost, message);
+                        }
+
+                        client.getOutputStream().write((
+                            "HTTP/1.1 " + responseCode + " OK\n"
+                            + "Content-type: text/html\n"
+                            + "Content-length: " 
+                            + response.length() + "\n\n"
+                            + response).getBytes());
+
+                        if (responseCode != OK_CODE) {
+                            // wait while test case check closed connection
+                            // and interrupt this thread
+                            try {
+                                while (!isInterrupted()) {
+                                    Thread.sleep(1000);
+                                }
+                            } catch (Exception ignore) { }
+                        }
+                    }
+                } catch (SocketTimeoutException ignore) {
+                    ignore.printStackTrace();
+                } finally {
+                    if (is != null) {
+                        is.close();
+                    }
+                    if (client != null) {
+                        client.close();
+                    }
+                    serverSocket.close();
+                }
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public void setUp() {
+        if (DEBUG) {
+            System.out.println("\n==============================");
+            System.out.println("===== Execution: "+getName());
+            System.out.println("==============================");
+        }
+    }
+
+    /**
+     * Test that an HTTP connection persists
+     */
+    public void testConnectionsPersist() throws IOException, InterruptedException {
+        int initialFreeConnections = HttpConnectionManager.getDefault().numFreeConnections();
+        MockServer httpServer =
+                new MockServer("ServerSocket for HttpURLConnectionTest");
+        httpServer.start();
+        synchronized(bound) {
+            if (!httpServer.started) {
+                bound.wait(5000);
+            }
+        }
+        HttpURLConnection c = (HttpURLConnection)
+            new URL("http://127.0.0.1:" + httpServer.port()).openConnection();
+        c.setDoOutput(true);
+        c.setRequestMethod("POST");
+        c.getOutputStream().close();
+        assertEquals(initialFreeConnections + 1, HttpConnectionManager.getDefault().numFreeConnections());
+        c = (HttpURLConnection)
+            new URL("http://127.0.0.1:" + httpServer.port()).openConnection();
+        c.setDoOutput(true);
+        c.setRequestMethod("POST");
+        OutputStream os = c.getOutputStream();
+        assertEquals(initialFreeConnections, HttpConnectionManager.getDefault().numFreeConnections());
+        os.close();
+        assertEquals(initialFreeConnections + 1, HttpConnectionManager.getDefault().numFreeConnections());
+        httpServer.join();
+    }
+
+    /**
+     * Test that multiple HTTP connections persist
+     */
+    public void testMultipleConnectionsPersist() throws IOException, InterruptedException {
+        int initialFreeConnections = HttpConnectionManager.getDefault().numFreeConnections();
+        MockServer httpServer =
+                new MockServer("ServerSocket for HttpURLConnectionTest");
+       httpServer.start();
+       synchronized(bound) {
+           if (!httpServer.started) {
+               bound.wait(5000);
+           }
+       }
+       MockServer httpServer2 =
+           new MockServer("ServerSocket for HttpURLConnectionTest");
+       httpServer2.start();
+       synchronized(bound) {
+           if (!httpServer2.started) {
+              bound.wait(5000);
+           }
+       }
+       HttpURLConnection c = (HttpURLConnection)
+           new URL("http://127.0.0.1:" + httpServer.port()).openConnection();
+       c.setDoOutput(true);
+       c.setRequestMethod("POST");
+       OutputStream os = c.getOutputStream();
+       HttpURLConnection c2 = (HttpURLConnection)
+       new URL("http://127.0.0.1:" + httpServer2.port()).openConnection();
+       c2.setDoOutput(true);
+       c2.setRequestMethod("POST");
+       OutputStream os2 = c2.getOutputStream();
+       os.close();
+       os2.close();
+       assertEquals(initialFreeConnections + 2, HttpConnectionManager.getDefault().numFreeConnections());
+
+       c = (HttpURLConnection)
+           new URL("http://127.0.0.1:" + httpServer.port()).openConnection();
+       c.setDoOutput(true);
+       c.setRequestMethod("POST");
+       os = c.getOutputStream();
+       assertEquals(initialFreeConnections + 1, HttpConnectionManager.getDefault().numFreeConnections());
+       c2 = (HttpURLConnection)
+       new URL("http://127.0.0.1:" + httpServer2.port()).openConnection();
+       c2.setDoOutput(true);
+       c2.setRequestMethod("POST");
+       os2 = c2.getOutputStream();
+       assertEquals(initialFreeConnections, HttpConnectionManager.getDefault().numFreeConnections());
+       os.close();
+       os2.close();
+       assertEquals(initialFreeConnections + 2, HttpConnectionManager.getDefault().numFreeConnections());
+       httpServer.join();
+       httpServer2.join();
+    }
+
+    /**
+     * Test that a closed HTTP connection is not kept in the pool of live connections
+     * @throws URISyntaxException
+     */
+    public void testForcedClosure() throws Exception {
+        int initialFreeConnections = HttpConnectionManager.getDefault().numFreeConnections();
+        MockServer httpServer =
+                new MockServer("ServerSocket for HttpURLConnectionTest");
+        httpServer.start();
+        synchronized(bound) {
+            if (!httpServer.started) {
+                bound.wait(5000);
+            }
+        }
+        HttpConnection connection = HttpConnectionManager.getDefault().getConnection(new URI("http://127.0.0.1:" + httpServer.port()), 1000);
+        HttpConnectionManager.getDefault().returnConnectionToPool(connection);
+        assertEquals(initialFreeConnections + 1, HttpConnectionManager.getDefault().numFreeConnections());
+        HttpURLConnection c = (HttpURLConnection)
+            new URL("http://127.0.0.1:" + httpServer.port()).openConnection();
+        c.setDoOutput(true);
+        c.setRequestMethod("POST");
+        c.getOutputStream();
+        assertEquals(initialFreeConnections, HttpConnectionManager.getDefault().numFreeConnections());
+        c.disconnect();
+        assertEquals(initialFreeConnections, HttpConnectionManager.getDefault().numFreeConnections());
+    }
+
+    /**
+     * Test that a connection is closed if the client does not read all the data
+     * @throws Exception
+     */
+    public void testIncorrectUsage() throws Exception {
+        int initialFreeConnections = HttpConnectionManager.getDefault().numFreeConnections();
+        HttpURLConnection c = (HttpURLConnection)
+            new URL("http://localhost:" + port).openConnection();
+        c.setDoOutput(true);
+        c.setRequestMethod("GET");
+        InputStream is = c.getInputStream(); // get the input stream but don't finish reading it
+        is.close();
+        assertEquals(initialFreeConnections, HttpConnectionManager.getDefault().numFreeConnections());
+    }
+
+    /**
+     * Test that a connection is closed in case of unsuccessful connection.
+     * Here client gets NOT_FOUND response.
+     */
+    public void testConnectionNonPersistence() throws Exception {
+        MockHTTPServer httpServer =
+            new MockHTTPServer("HTTP Server for NOT FOUND checking", 1,
+                    MockHTTPServer.NOT_FOUND_CODE);
+        httpServer.start();
+        synchronized(bound) {
+            if (!httpServer.started) {
+                bound.wait(5000);
+            }
+        }
+
+        int initialFreeConnections
+            = HttpConnectionManager.getDefault().numFreeConnections();
+
+        HttpURLConnection c = (HttpURLConnection)
+            new URL("http://localhost:"+httpServer.port()).openConnection();
+        if (DEBUG) {
+            System.out.println("Actual connection class: "+c.getClass());
+        }
+
+        c.setDoInput(true);
+        c.setConnectTimeout(5000);
+        c.setReadTimeout(5000);
+        try {
+            c.getInputStream();
+            fail("Expected IOException was not thrown");
+        } catch (IOException expected) {
+            // expected
+        } finally {
+            httpServer.interrupt();
+        }
+        assertEquals("Unsuccessful connection was not closed",
+                initialFreeConnections,
+                HttpConnectionManager.getDefault().numFreeConnections());
+    }
+
+    /**
+     * Test that a connection is not closed if the client does read all the data
+     * @throws Exception 
+     */
+    public void testCorrectUsage() throws Exception {
+        int initialFreeConnections = HttpConnectionManager.getDefault().numFreeConnections();
+        HttpURLConnection c = (HttpURLConnection)
+            new URL("http://localhost:" + port).openConnection();
+        c.setDoOutput(true);
+        c.setRequestMethod("GET");
+        InputStream is = c.getInputStream();
+        byte[] buffer = new byte[128];
+        int totalBytes = 0;
+        int bytesRead = 0;
+        while((bytesRead = is.read(buffer)) > 0){
+            totalBytes += bytesRead;
+        }
+        is.close();
+        assertEquals(initialFreeConnections + 1, HttpConnectionManager.getDefault().numFreeConnections());
+
+        HttpURLConnection c2 = (HttpURLConnection)
+            new URL("http://localhost:" + port).openConnection();
+        c2.setDoOutput(true);
+        c2.setRequestMethod("GET");
+        InputStream is2 = c2.getInputStream();
+        byte[] buffer2 = new byte[128];
+        int totalBytes2 = 0;
+        int bytesRead2 = 0;
+        while((bytesRead2 = is2.read(buffer2)) > 0){
+            totalBytes2 += bytesRead2;
+        }
+        is2.close();
+        assertEquals(initialFreeConnections + 1, HttpConnectionManager.getDefault().numFreeConnections());
+        assertEquals(totalBytes, totalBytes2);
+    }
+
+    /**
+     * Test that the http.keepAlive system property has the required effect on persistent connections
+     */
+    public void testKeepAliveSystemProperty() throws IOException, InterruptedException {
+        System.setProperty("http.keepAlive", "false");
+        MockServer httpServer =
+                new MockServer("ServerSocket for HttpURLConnectionTest");
+        httpServer.start();
+        synchronized(bound) {
+            if (!httpServer.started) {
+                bound.wait(5000);
+            }
+        }
+        HttpURLConnection c = (HttpURLConnection)
+            new URL("http://127.0.0.1:" + httpServer.port()).openConnection();
+        c.setDoOutput(true);
+        c.setRequestMethod("POST");
+        OutputStream os = c.getOutputStream();
+        os.close();
+        assertEquals(0, HttpConnectionManager.getDefault().numFreeConnections());
+        httpServer.join();
+        System.setProperty("http.keepAlive", "true");
+    }
+
+    /**
+     * Test that the http.maxConnections system property has the required effect on persistent connections
+     * @throws Exception
+     */
+    public void testMaxConnectionsSystemProperty() throws Exception {
+        int initialFreeConnections = HttpConnectionManager.getDefault().numFreeConnections();
+        System.setProperty("http.maxConnections", "2");
+        HttpURLConnection c = (HttpURLConnection)
+            new URL("http://localhost:" + port).openConnection();
+        c.setDoOutput(true);
+        c.setRequestMethod("GET");
+        InputStream is = c.getInputStream();
+        c = (HttpURLConnection)
+            new URL("http://localhost:" + port).openConnection();
+        c.setDoOutput(true);
+        c.setRequestMethod("GET");
+        InputStream is2 = c.getInputStream();
+        c = (HttpURLConnection)
+            new URL("http://localhost:" + port).openConnection();
+        c.setDoOutput(true);
+        c.setRequestMethod("GET");
+        InputStream is3 = c.getInputStream();
+        byte[] buffer = new byte[128];
+        while(is.read(buffer) > 0){
+        }
+        while(is2.read(buffer) > 0){
+        }
+        while(is3.read(buffer) > 0){
+        }
+        is.close();
+        is2.close();
+        is3.close();
+        assertEquals(initialFreeConnections + 2, HttpConnectionManager.getDefault().numFreeConnections());
+    }
+    
+    public void testClosingOutputStream() throws IOException {
+//      create a serversocket
+        Support_HttpServerSocket serversocket = new Support_HttpServerSocket();
+        int portNumber = Support_PortManager.getNextPort();
+        // create a client connector
+        Support_URLConnector connector = new Support_URLConnector();
+        Support_HttpServer server = new Support_HttpServer(serversocket, this);
+        
+        server.startServer(portNumber);
+
+
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        InputStream is;
+        int c;
+        final String postTestUrl = "http://localhost:" + portNumber
+            + Support_HttpServer.POSTTEST;
+
+        String toWrite = "abcdef";
+        connector.open(postTestUrl);
+        OutputStream out = connector.getOutputStream();
+        System.out.println("Output stream = " + out.hashCode());
+        out.write(toWrite.getBytes("ISO8859_1"));
+        out.close();
+        is = connector.getInputStream();
+        bout.reset();
+        do {
+            c = is.read();
+            if (c != -1) {
+                bout.write(c);
+            }
+        } while (c != -1);
+        is.close();
+        connector.close();
+        String result = new String(bout.toByteArray(), "ISO8859_1");
+        assertTrue("Error sending data 1: " + result, toWrite
+                .equals(result));   
+        
+        toWrite = "zyxwvuts";
+        connector.open(postTestUrl);
+        connector.setRequestProperty("Transfer-encoding", "chunked");
+        out = connector.getOutputStream();
+        System.out.println("Output stream = " + out.hashCode());
+        out.write(toWrite.getBytes("ISO8859_1"));
+        out.close();
+        is = connector.getInputStream();
+        bout.reset();
+        do {
+            c = is.read();
+            if (c != -1) {
+                bout.write(c);
+            }
+        } while (c != -1);
+        is.close();
+        connector.close();
+        result = new String(bout.toByteArray(), "ISO8859_1");
+        assertEquals(toWrite, result);
+        
+    }
+
+}
\ No newline at end of file