/*
 *  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.luni.tests.internal.net.www.protocol.https;

import dalvik.annotation.AndroidOnly;
import dalvik.annotation.KnownFailure;
import dalvik.annotation.TestTargetClass; 
import dalvik.annotation.TestTargets;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetNew;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.Arrays;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import junit.framework.TestCase;

/**
 * Implementation independent test for HttpsURLConnection.
 * The test needs certstore file placed in system classpath 
 * and named as "key_store." + the type of the
 * default KeyStore installed in the system in lower case.
 * <br>
 * For example: if default KeyStore type in the system is BKS
 * (i.e. java.security file sets up the property keystore.type=BKS),
 * thus classpath should point to the directory with "key_store.bks"
 * file.
 * <br>
 * This certstore file should contain self-signed certificate
 * generated by keytool utility in a usual way.
 * <br>
 * The password to the certstore should be "password" (without quotes).
 */
@TestTargetClass(HttpsURLConnection.class)
public class HttpsURLConnectionTest extends TestCase {

    // the password to the store
    private static final String KS_PASSWORD = "password";

    // turn on/off logging
    private static final boolean DO_LOG = false;

    // read/connection timeout value
    private static final int TIMEOUT = 5000;

    // OK response code
    private static final int OK_CODE = 200;

    // Not Found response code
    private static final int NOT_FOUND_CODE = 404;

    // Proxy authentication required response code
    private static final int AUTHENTICATION_REQUIRED_CODE = 407;

    // fields keeping the system values of corresponding properties
    private static String systemKeyStoreType;

    private static String systemKeyStore;

    private static String systemKeyStorePassword;

    private static String systemTrustStoreType;

    private static String systemTrustStore;

    private static String systemTrustStorePassword;
    
    private static File store;
    
    static {
        try {
            store = File.createTempFile("key_store", "bks");
        } catch (Exception e) {
            // ignore
        }
    }

    /**
     * Checks that HttpsURLConnection's default SSLSocketFactory is operable.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "Verifies that HttpsURLConnection's default SSLSocketFactory is operable.",
        method = "getDefaultSSLSocketFactory",
        args = {}
    )
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testGetDefaultSSLSocketFactory() throws Exception {
        // set up the properties defining the default values needed by SSL stuff
        setUpStoreProperties();

        try {
            SSLSocketFactory defaultSSLSF = HttpsURLConnection
                    .getDefaultSSLSocketFactory();
            ServerSocket ss = new ServerSocket(0);
            Socket s = defaultSSLSF
                    .createSocket("localhost", ss.getLocalPort());
            ss.accept();
            s.close();
            ss.close();
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Checks if HTTPS connection performs initial SSL handshake with the
     * server working over SSL, sends encrypted HTTP request,
     * and receives expected HTTP response. After HTTPS session if finished
     * test checks connection state parameters established by
     * HttpsURLConnection.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "Verifies  if HTTPS connection performs initial SSL handshake with the server working over SSL, sends encrypted HTTP request, and receives expected HTTP response.",
        method = "setDefaultHostnameVerifier",
        args = {javax.net.ssl.HostnameVerifier.class}
    )
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testHttpsConnection() 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) doInteraction(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.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setReadTimeout",
            args = {int.class}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testHttpsConnection_Not_Found_Response() 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();

            try {
                doInteraction(connection, ss, NOT_FOUND_CODE);
                fail("Expected exception was not thrown.");
            } catch (FileNotFoundException e) {
                if (DO_LOG) {
                    System.out.println("Expected exception was thrown: "
                            + e.getMessage());
                }
            }

            // should silently exit
            connection.connect();
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests possibility to set up the default SSLSocketFactory
     * to be used by HttpsURLConnection.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "Verifies possibility to set up the default SSLSocketFactory to be used by HttpsURLConnection.",
        method = "setDefaultSSLSocketFactory",
        args = {javax.net.ssl.SSLSocketFactory.class}
    )
    @AndroidOnly("we only have a .bks key store in the test resources")
    @KnownFailure("End to end test fails. No response data is transferred from server to client")
    public void testSetDefaultSSLSocketFactory() throws Throwable {
        // create the SSLServerSocket which will be used by server side
        SSLContext ctx = getContext();
        SSLServerSocket ss = (SSLServerSocket) ctx.getServerSocketFactory()
                .createServerSocket(0);

        SSLSocketFactory socketFactory = (SSLSocketFactory) ctx
                .getSocketFactory();
        // set up the factory as default
        HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
        // check the result
        assertSame("Default SSLSocketFactory differs from expected",
                socketFactory, HttpsURLConnection.getDefaultSSLSocketFactory());

        // create the HostnameVerifier to check hostname verification
        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();

        TestHostnameVerifier hnv_late = new TestHostnameVerifier();
        // late initialization: should not be used for created connection
        HttpsURLConnection.setDefaultHostnameVerifier(hnv_late);

        // perform the interaction between the peers
        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
        // check the connection state
        checkConnectionStateParameters(connection, peerSocket);
        // check the verification process
        assertTrue("Hostname verification was not done", hnv.verified);
        assertFalse(
                "Hostname verification should not be done by this verifier",
                hnv_late.verified);
        // check the used SSLSocketFactory
        assertSame("Default SSLSocketFactory should be used",
                HttpsURLConnection.getDefaultSSLSocketFactory(), connection
                        .getSSLSocketFactory());

        // should silently exit
        connection.connect();
    }

    /**
     * Tests possibility to set up the SSLSocketFactory
     * to be used by HttpsURLConnection.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "Verifies possibility to set up the SSLSocketFactory to be used by HttpsURLConnection.",
        method = "setSSLSocketFactory",
        args = {javax.net.ssl.SSLSocketFactory.class}
    )
    @AndroidOnly("we only have a .bks key store in the test resources")
    @KnownFailure("End to end test fails. No response data is transferred from server to client")
    public void testSetSSLSocketFactory() throws Throwable {
        // create the SSLServerSocket which will be used by server side
        SSLContext ctx = getContext();
        SSLServerSocket ss = (SSLServerSocket) ctx.getServerSocketFactory()
                .createServerSocket(0);

        // create the HostnameVerifier to check hostname verification
        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();

        SSLSocketFactory socketFactory = (SSLSocketFactory) ctx
                .getSocketFactory();
        connection.setSSLSocketFactory(socketFactory);

        TestHostnameVerifier hnv_late = new TestHostnameVerifier();
        // late initialization: should not be used for created connection
        HttpsURLConnection.setDefaultHostnameVerifier(hnv_late);

        // perform the interaction between the peers
        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
        // check the connection state
        checkConnectionStateParameters(connection, peerSocket);
        // check the verification process
        assertTrue("Hostname verification was not done", hnv.verified);
        assertFalse(
                "Hostname verification should not be done by this verifier",
                hnv_late.verified);
        // check the used SSLSocketFactory
        assertNotSame("Default SSLSocketFactory should not be used",
                HttpsURLConnection.getDefaultSSLSocketFactory(), connection
                        .getSSLSocketFactory());
        assertSame("Result differs from expected", socketFactory, connection
                .getSSLSocketFactory());

        // should silently exit
        connection.connect();
    }

    /**
     * Tests the behaviour of HttpsURLConnection in case of retrieving
     * of the connection state parameters before connection has been made.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies the behaviour of HttpsURLConnection in case of retrieving of the connection state parameters before connection has been made.",
            method = "getCipherSuite",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies the behaviour of HttpsURLConnection in case of retrieving of the connection state parameters before connection has been made.",
            method = "getPeerPrincipal",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies the behaviour of HttpsURLConnection in case of retrieving of the connection state parameters before connection has been made.",
            method = "getLocalPrincipal",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies the behaviour of HttpsURLConnection in case of retrieving of the connection state parameters before connection has been made.",
            method = "getServerCertificates",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies the behaviour of HttpsURLConnection in case of retrieving of the connection state parameters before connection has been made.",
            method = "getLocalCertificates",
            args = {}
        )
    })
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testUnconnectedStateParameters() throws Throwable {
        // create HttpsURLConnection to be tested
        URL url = new URL("https://localhost:55555");
        HttpsURLConnection connection = (HttpsURLConnection) url
                .openConnection();

        try {
            connection.getCipherSuite();
            fail("Expected IllegalStateException was not thrown");
        } catch (IllegalStateException e) {}
        try {
            connection.getPeerPrincipal();
            fail("Expected IllegalStateException was not thrown");
        } catch (IllegalStateException e) {}
        try {
            connection.getLocalPrincipal();
            fail("Expected IllegalStateException was not thrown");
        } catch (IllegalStateException e) {}

        try {
            connection.getServerCertificates();
            fail("Expected IllegalStateException was not thrown");
        } catch (IllegalStateException e) {}
        try {
            connection.getLocalCertificates();
            fail("Expected IllegalStateException was not thrown");
        } catch (IllegalStateException e) {}
    }

    /**
     * Tests if setHostnameVerifier() method replaces default verifier.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "Verifies if setHostnameVerifier() method replaces default verifier.",
        method = "setHostnameVerifier",
        args = {javax.net.ssl.HostnameVerifier.class}
    )
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testSetHostnameVerifier() 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();

            TestHostnameVerifier hnv_late = new TestHostnameVerifier();
            // replace default verifier
            connection.setHostnameVerifier(hnv_late);

            // perform the interaction between the peers and check the results
            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
            assertTrue("Hostname verification was not done", hnv_late.verified);
            assertFalse(
                    "Hostname verification should not be done by this verifier",
                    hnv.verified);
            checkConnectionStateParameters(connection, peerSocket);

            // should silently exit
            connection.connect();
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests the behaviour in case of sending the data to the server.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL,
        notes = "Verifies the behaviour in case of sending the data to the server.",
        method = "setDoOutput",
        args = {boolean.class}
    )
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void test_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) doInteraction(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.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "setReadTimeout",
            args = {int.class}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testProxyConnection() 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) doInteraction(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.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication.",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication.",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication.",
            method = "setReadTimeout",
            args = {int.class}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testProxyAuthConnection() 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);

            Authenticator.setDefault(new Authenticator() {

                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("user", "password"
                            .toCharArray());
                }
            });

            // create HttpsURLConnection to be tested
            URL url = new URL("https://requested.host:55555/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) doInteraction(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.
     * 2 HTTPS connections are opened for one URL. For the first time
     * the connection is opened through one proxy,
     * for the second time through another.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "getCipherSuite",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "getLocalPrincipal",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "getPeerPrincipal",
            args = {}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testConsequentProxyConnection() 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:55555/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) doInteraction(connection, ss);
            checkConnectionStateParameters(connection, peerSocket);

            // create another SSLServerSocket which will be used by server side
            ss = new ServerSocket(0);

            connection = (HttpsURLConnection) url.openConnection(new Proxy(
                    Proxy.Type.HTTP, new InetSocketAddress("localhost", ss
                            .getLocalPort())));

            // perform the interaction between the peers and check the results
            peerSocket = (SSLSocket) doInteraction(connection, ss);
            checkConnectionStateParameters(connection, peerSocket);
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     * Proxy server needs authentication.
     * Client sends data to the server.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication. Client sends data to the server.",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication. Client sends data to the server.",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication. Client sends data to the server.",
            method = "setReadTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication. Client sends data to the server.",
            method = "setDoOutput",
            args = {boolean.class}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testProxyAuthConnection_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
            ServerSocket ss = new ServerSocket(0);

            // create the HostnameVerifier to check that Hostname verification
            // is done
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            Authenticator.setDefault(new Authenticator() {

                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("user", "password"
                            .toCharArray());
                }
            });

            // create HttpsURLConnection to be tested
            URL url = new URL("https://requested.host:55554/requested.data");
            HttpsURLConnection connection = (HttpsURLConnection) url
                    .openConnection(new Proxy(Proxy.Type.HTTP,
                            new InetSocketAddress("localhost", ss
                                    .getLocalPort())));
            connection.setDoOutput(true);

            // perform the interaction between the peers and check the results
            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss,
                    OK_CODE, true);
            checkConnectionStateParameters(connection, peerSocket);
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     * Proxy server needs authentication but client fails to authenticate
     * (Authenticator was not set up in the system).
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication but client fails to authenticate (Authenticator was not set up in the system).",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication but client fails to authenticate (Authenticator was not set up in the system).",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication but client fails to authenticate (Authenticator was not set up in the system).",
            method = "setReadTimeout",
            args = {int.class}
        )
    })
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testProxyAuthConnectionFailed() 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:55555/requested.data");
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection(new Proxy(Proxy.Type.HTTP,
                            new InetSocketAddress("localhost", ss
                                    .getLocalPort())));

            // perform the interaction between the peers and check the results
            try {
                doInteraction(connection, ss, AUTHENTICATION_REQUIRED_CODE,
                        true);
            } catch (IOException e) {
                // SSL Tunnelling failed
                if (DO_LOG) {
                    System.out.println("Got expected IOException: "
                            + e.getMessage());
                }
            }
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests the behaviour of HTTPS connection in case of unavailability
     * of requested resource.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setReadTimeout",
            args = {int.class}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testProxyConnection_Not_Found_Response() 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://localhost:" + ss.getLocalPort());
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection(new Proxy(Proxy.Type.HTTP,
                            new InetSocketAddress("localhost", ss
                                    .getLocalPort())));

            try {
                doInteraction(connection, ss, NOT_FOUND_CODE); // NOT FOUND
                fail("Expected exception was not thrown.");
            } catch (FileNotFoundException e) {
                if (DO_LOG) {
                    System.out.println("Expected exception was thrown: "
                            + e.getMessage());
                }
            }
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    // ---------------------------------------------------------------------
    // ------------------------ Staff Methods ------------------------------
    // ---------------------------------------------------------------------

    /**
     * Log the name of the test case to be executed.
     */
    public void setUp() throws Exception {
        if (DO_LOG) {
            System.out.println();
            System.out.println("------------------------");
            System.out.println("------ " + getName());
            System.out.println("------------------------");
        }
        
        if (store != null) {
            String ksFileName = "org/apache/harmony/luni/tests/key_store."
                    + KeyStore.getDefaultType().toLowerCase();
            InputStream in = ClassLoader.getSystemClassLoader()
                    .getResourceAsStream(ksFileName);
            FileOutputStream out = new FileOutputStream(store);
            BufferedInputStream bufIn = new BufferedInputStream(in, 8192);
            while (bufIn.available() > 0) {
                byte[] buf = new byte[128];
                int read = bufIn.read(buf);
                out.write(buf, 0, read);
            }
            bufIn.close();
            out.close();
        } else {
            fail("couldn't set up key store");
        }
    }

    public void tearDown() {
        if (store != null) {
            store.delete();
        }
    }
    
    /**
     * Checks the HttpsURLConnection getter's values and compares
     * them with actual corresponding values of remote peer.
     */
    public static void checkConnectionStateParameters(
            HttpsURLConnection clientConnection, SSLSocket serverPeer)
            throws Exception {
        SSLSession session = serverPeer.getSession();

        assertEquals(session.getCipherSuite(), clientConnection
                .getCipherSuite());

        assertEquals(session.getLocalPrincipal(), clientConnection
                .getPeerPrincipal());

        assertEquals(session.getPeerPrincipal(), clientConnection
                .getLocalPrincipal());

        Certificate[] serverCertificates = clientConnection
                .getServerCertificates();
        Certificate[] localCertificates = session.getLocalCertificates();
        assertTrue("Server certificates differ from expected", Arrays.equals(
                serverCertificates, localCertificates));

        localCertificates = clientConnection.getLocalCertificates();
        serverCertificates = session.getPeerCertificates();
        assertTrue("Local certificates differ from expected", Arrays.equals(
                serverCertificates, localCertificates));
    }

    /**
     * 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 
     * or file does not exist.
     */
    private static String getKeyStoreFileName() {
        return store.getAbsolutePath();
    }

    /**
     * Builds and returns the context used for secure socket creation.
     */
    private static SSLContext getContext() throws Exception {
        String type = KeyStore.getDefaultType();
        SSLContext ctx;

        String keyStore = getKeyStoreFileName();
        File keyStoreFile = new File(keyStore);

        FileInputStream fis = new FileInputStream(keyStoreFile);

        KeyStore ks = KeyStore.getInstance(type);
        ks.load(fis, KS_PASSWORD.toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
                .getDefaultAlgorithm());
        kmf.init(ks, KS_PASSWORD.toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(ks);

        ctx = SSLContext.getInstance("TLSv1");
        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        return ctx;
    }

    /**
     * Sets up the properties pointing to the key store and trust store
     * and used as default values by JSSE staff. This is needed to test
     * HTTPS behaviour in the case of default SSL Socket Factories.
     */
    private static void setUpStoreProperties() throws Exception {
        String type = KeyStore.getDefaultType();

        systemKeyStoreType = System.getProperty("javax.net.ssl.keyStoreType");
        systemKeyStore = System.getProperty("javax.net.ssl.keyStore");
        systemKeyStorePassword = System
                .getProperty("javax.net.ssl.keyStorePassword");

        systemTrustStoreType = System
                .getProperty("javax.net.ssl.trustStoreType");
        systemTrustStore = System.getProperty("javax.net.ssl.trustStore");
        systemTrustStorePassword = System
                .getProperty("javax.net.ssl.trustStorePassword");

        System.setProperty("javax.net.ssl.keyStoreType", type);
        System.setProperty("javax.net.ssl.keyStore", getKeyStoreFileName());
        System.setProperty("javax.net.ssl.keyStorePassword", KS_PASSWORD);

        System.setProperty("javax.net.ssl.trustStoreType", type);
        System.setProperty("javax.net.ssl.trustStore", getKeyStoreFileName());
        System.setProperty("javax.net.ssl.trustStorePassword", KS_PASSWORD);
    }

    /**
     * Rolls back the values of system properties.
     */
    private static void tearDownStoreProperties() {
        if (systemKeyStoreType == null) {
            System.clearProperty("javax.net.ssl.keyStoreType");
        } else {
            System
                    .setProperty("javax.net.ssl.keyStoreType",
                            systemKeyStoreType);
        }
        if (systemKeyStore == null) {
            System.clearProperty("javax.net.ssl.keyStore");
        } else {
            System.setProperty("javax.net.ssl.keyStore", systemKeyStore);
        }
        if (systemKeyStorePassword == null) {
            System.clearProperty("javax.net.ssl.keyStorePassword");
        } else {
            System.setProperty("javax.net.ssl.keyStorePassword",
                    systemKeyStorePassword);
        }

        if (systemTrustStoreType == null) {
            System.clearProperty("javax.net.ssl.trustStoreType");
        } else {
            System.setProperty("javax.net.ssl.trustStoreType",
                    systemTrustStoreType);
        }
        if (systemTrustStore == null) {
            System.clearProperty("javax.net.ssl.trustStore");
        } else {
            System.setProperty("javax.net.ssl.trustStore", systemTrustStore);
        }
        if (systemTrustStorePassword == null) {
            System.clearProperty("javax.net.ssl.trustStorePassword");
        } else {
            System.setProperty("javax.net.ssl.trustStorePassword",
                    systemTrustStorePassword);
        }
    }

    /**
     * Performs interaction between client's HttpURLConnection and
     * servers side (ServerSocket).
     */
    public static Socket doInteraction(
            final HttpURLConnection clientConnection,
            final ServerSocket serverSocket) throws Throwable {
        return doInteraction(clientConnection, serverSocket, OK_CODE, false);
    }

    /**
     * Performs interaction between client's HttpURLConnection and
     * servers side (ServerSocket). Server will response with specified
     * response code.
     */
    public static Socket doInteraction(
            final HttpURLConnection clientConnection,
            final ServerSocket serverSocket, final int responseCode)
            throws Throwable {
        return doInteraction(clientConnection, serverSocket, responseCode,
                false);
    }

    /**
     * Performs interaction between client's HttpURLConnection and
     * servers side (ServerSocket). Server will response with specified
     * response code.
     * @param doAuthentication specifies 
     * if the server needs client authentication.
     */
    public static Socket doInteraction(
            final HttpURLConnection clientConnection,
            final ServerSocket serverSocket, final int responseCode,
            final boolean doAuthentication) throws Throwable {

        // set up the connection
        clientConnection.setDoInput(true);
        clientConnection.setConnectTimeout(TIMEOUT);
        clientConnection.setReadTimeout(TIMEOUT);

        ServerWork server = new ServerWork(serverSocket, responseCode,
                doAuthentication);

        ClientConnectionWork client = new ClientConnectionWork(clientConnection);

        server.start();
        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
                throw client.thrown;
            }
            if ((client.thrown instanceof SocketTimeoutException)
                    && (server.thrown != null)) {
                // server's exception is more informative in this case
                throw new Exception(server.thrown);
            } else {
                throw new Exception(client.thrown);
            }
        }
        if (server.thrown != null) {
            throw server.thrown;
        }
        return server.peerSocket;
    }

    /**
     * The host name verifier used in test.
     */
    static class TestHostnameVerifier implements HostnameVerifier {

        boolean verified = false;

        public boolean verify(String hostname, SSLSession session) {
            if (DO_LOG) {
                System.out.println("***> verification " + hostname + " "
                        + session.getPeerHost());
            }
            verified = true;
            return true;
        }
    }

    /**
     * The base class for mock Client and Server.
     */
    static class Work extends Thread {

        /**
         * The header of OK HTTP response.
         */
        static final String responseHead = "HTTP/1.1 200 OK\n";

        /**
         * The content of the response.
         */
        static final String plainResponseContent = "<HTML>\n"
                + "<HEAD><TITLE>Plain Response Content</TITLE></HEAD>\n"
                + "</HTML>";

        /**
         * The tail of the response.
         */
        static final String plainResponseTail = "Content-type: text/html\n"
                + "Content-length: " + plainResponseContent.length() + "\n\n"
                + plainResponseContent;

        /**
         * The response message to be sent in plain (HTTP) format.
         */
        static final String plainResponse = responseHead + plainResponseTail;

        /**
         * The content of the response to be sent during HTTPS session.
         */
        static final String httpsResponseContent = "<HTML>\n"
                + "<HEAD><TITLE>HTTPS Response Content</TITLE></HEAD>\n"
                + "</HTML>";

        /**
         * The tail of the response to be sent during HTTPS session.
         */
        static final String httpsResponseTail = "Content-type: text/html\n"
                + "Content-length: " + httpsResponseContent.length() + "\n\n"
                + httpsResponseContent;

        /**
         * The response requiring client's proxy authentication.
         */
        static final String respAuthenticationRequired = "HTTP/1.0 407 Proxy authentication required\n"
                + "Proxy-authenticate: Basic realm=\"localhost\"\n\n";

        /**
         * The data to be posted by client to the server.
         */
        static final String clientsData = "_.-^ Client's Data ^-._";

        /**
         * The exception thrown during peers interaction.
         */
        protected Throwable thrown;

        /**
         * The print stream used for debug log.
         * If it is null debug info will not be printed.
         */
        private PrintStream out = new PrintStream(System.out);

        /**
         * Prints log message.
         */
        public synchronized void log(String message) {
            if (DO_LOG && (out != null)) {
                System.out.println("[" + getName() + "]: " + message);
            }
        }
    }

    /**
     * The class used for server side works.
     */
    static class ServerWork extends Work {

        // the server socket used for connection
        private ServerSocket serverSocket;

        // the socket connected with client peer
        private Socket peerSocket;

        // indicates if the server acts as proxy server
        private boolean actAsProxy;

        // indicates if the server needs proxy authentication
        private boolean needProxyAuthentication;

        // response code to be send to the client peer
        private int responseCode;

        /**
         * Creates the thread acting as a server side.
         */
        public ServerWork(ServerSocket serverSocket) {
            // the server does not require proxy authentication
            // and sends OK_CODE (OK) response code
            this(serverSocket, OK_CODE, false);
        }

        /**
         * Creates the thread acting as a server side.
         * @param serverSocket the server socket to be used during connection
         * @param responseCode the response code to be sent to the client
         * @param needProxyAuthentication
         * indicates if the server needs proxy authentication
         */
        public ServerWork(ServerSocket serverSocket, int responseCode,
                boolean needProxyAuthentication) {
            this.serverSocket = serverSocket;
            this.responseCode = responseCode;
            this.needProxyAuthentication = needProxyAuthentication;
            // will act as a proxy server if the specified server socket
            // is not a secure server socket
            if (serverSocket instanceof SSLServerSocket) {
                // demand client to send its certificate
                ((SSLServerSocket) serverSocket).setNeedClientAuth(true);
                // work as a HTTPS server, not as HTTP proxy
                this.actAsProxy = false;
            } else {
                this.actAsProxy = true;
            }
            this.actAsProxy = !(serverSocket instanceof SSLServerSocket);
            setName(this.actAsProxy ? "Proxy Server" : "Server");
        }

        /**
         * Closes the connection.
         */
        public void closeSocket(Socket socket) {
            try {
                socket.getInputStream().close();
            } catch (IOException e) {}
            try {
                socket.getOutputStream().close();
            } catch (IOException e) {}
            try {
                socket.close();
            } catch (IOException e) {}
        }

        /**
         * Performs the actual server work.
         * If some exception occurs during the work it will be
         * stored in the <code>thrown</code> field.
         */
        public void run() {
            // the buffer used for reading the messages
            byte[] buff = new byte[2048];
            // the number of bytes read into the buffer
            int num;
            try {
                // configure the server socket to avoid blocking
                serverSocket.setSoTimeout(TIMEOUT);
                // accept client connection
                peerSocket = serverSocket.accept();
                // configure the client connection to avoid blocking
                peerSocket.setSoTimeout(TIMEOUT);
                log("Client connection ACCEPTED");

                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);
                    }
                    // just send the response
                    os
                            .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail)
                                    .getBytes());
                    os.flush();
                    os.close();
                    // and return
                    log("Work is DONE !actAsProxy");
                    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();
                        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);
                }

                // 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();

                    // 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("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 actAsProxy");
            } catch (Throwable e) {
                if (DO_LOG) {
                    e.printStackTrace();
                }
                thrown = e;
            } finally {
                closeSocket(peerSocket);
                try {
                    serverSocket.close();
                } catch (IOException e) {}
            }
        }
    }

    /**
     * The class used for client side works. It could be used to test
     * both HttpURLConnection and HttpsURLConnection.
     */
    static class ClientConnectionWork extends Work {

        // connection to be used to contact the server side
        private HttpURLConnection connection;

        /**
         * Creates the thread acting as a client side.
         * @param connection connection to be used to contact the server side
         */
        public ClientConnectionWork(HttpURLConnection connection) {
            this.connection = connection;
            setName("Client Connection");
            log("Created over connection: " + connection.getClass());
        }

        /**
         * Performs the actual client work.
         * If some exception occurs during the work it will be
         * stored in the <code>thrown<code> field.
         */
        public void run() {
            try {
                log("Opening the connection..");
                connection.connect();
                log("Connection has been ESTABLISHED, using proxy: "
                        + connection.usingProxy());
                if (connection.getDoOutput()) {
                    // connection configured to post data, do so
                    connection.getOutputStream().write(clientsData.getBytes());
                }
                // read the content of HTTP(s) response
                InputStream is = connection.getInputStream();
                log("Input Stream obtained");
                byte[] buff = new byte[2048];
                int num = 0;
                int byt = 0;
                while ((num < buff.length) && (is.available() > 0)
                        && ((byt = is.read()) != -1)) {
                    buff[num++] = (byte) byt;
                }
                String message = new String(buff, 0, num);
                log("Got content:\n" + message);
                log("------------------");
                log("Response code: " + connection.getResponseCode());

                if (connection instanceof HttpsURLConnection) {
                    assertEquals(httpsResponseContent, message);
                } else {
                    assertEquals(plainResponseContent, message);
                }
            } catch (Throwable e) {
                if (DO_LOG) {
                    e.printStackTrace();
                }
                thrown = e;
            }
        }
    }
}
