/*
 *  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 com.google.mockwebserver.Dispatcher;
import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.MockWebServer;
import com.google.mockwebserver.RecordedRequest;
import com.google.mockwebserver.SocketPolicy;

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.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import junit.framework.TestCase;
import libcore.java.security.TestKeyStore;
import libcore.javax.net.ssl.TestTrustManager;

/**
 * Implementation independent test for HttpsURLConnection.
 */
public class HttpsURLConnectionTest extends TestCase {

    private static final String POST_METHOD = "POST";

    private static final String GET_METHOD = "GET";

    /**
     * Data to be posted by client to the server when the method is POST.
     */
    private static final String POST_DATA = "_.-^ Client's Data ^-._";

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

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

    private static File store;

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

    /**
     * Checks that HttpsURLConnection's default SSLSocketFactory is operable.
     */
    public void testGetDefaultSSLSocketFactory() throws Exception {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        SSLSocketFactory defaultSSLSF = HttpsURLConnection.getDefaultSSLSocketFactory();
        ServerSocket ss = new ServerSocket(0);
        Socket s = defaultSSLSF.createSocket("localhost", ss.getLocalPort());
        ss.accept();
        s.close();
        ss.close();
    }

    public void testHttpsConnection() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        SSLContext ctx = getContext();

        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());

        // create a webserver to check and respond to requests
        SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
        MockWebServer webServer = createWebServer(ctx, dispatcher);

        // create url connection to be tested
        URL url = webServer.getUrl("/");
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        connection.setSSLSocketFactory(ctx.getSocketFactory());

        // perform the interaction between the peers
        executeClientRequest(connection, false /* doOutput */);

        checkConnectionStateParameters(connection, dispatcher.getLastRequest());

        // should silently exit
        connection.connect();

        webServer.shutdown();
    }

    /**
     * Tests the behaviour of HTTPS connection in case of unavailability of requested resource.
     */
    public void testHttpsConnection_Not_Found_Response() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        SSLContext ctx = getContext();

        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());

        // create a webserver to check and respond to requests
        SingleRequestDispatcher dispatcher =
                new SingleRequestDispatcher(GET_METHOD, NOT_FOUND_CODE);
        MockWebServer webServer = createWebServer(ctx, dispatcher);

        // create url connection to be tested
        URL url = webServer.getUrl("/");
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        connection.setSSLSocketFactory(ctx.getSocketFactory());

        try {
            executeClientRequest(connection, false /* doOutput */);
            fail("Expected exception was not thrown.");
        } catch (FileNotFoundException e) {
            if (DO_LOG) {
                System.out.println("Expected exception was thrown: " + e.getMessage());
                e.printStackTrace();
            }
        }

        // should silently exit
        connection.connect();

        webServer.shutdown();
    }

    /**
     * Tests possibility to set up the default SSLSocketFactory to be used by HttpsURLConnection.
     */
    public void testSetDefaultSSLSocketFactory() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        SSLContext ctx = getContext();

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

        // set the initial default host name verifier.
        TestHostnameVerifier initialHostnameVerifier = new TestHostnameVerifier();
        HttpsURLConnection.setDefaultHostnameVerifier(initialHostnameVerifier);

        // create a webserver to check and respond to requests
        SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
        MockWebServer webServer = createWebServer(ctx, dispatcher);

        // create HttpsURLConnection to be tested
        URL url = webServer.getUrl("/");
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

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

        // perform the interaction between the peers
        executeClientRequest(connection, false /* doOutput */);
        checkConnectionStateParameters(connection, dispatcher.getLastRequest());

        // check the verification process
        assertTrue("Hostname verification was not done", initialHostnameVerifier.verified);
        assertFalse("Hostname verification should not be done by this verifier",
                lateHostnameVerifier.verified);
        // check the used SSLSocketFactory
        assertSame("Default SSLSocketFactory should be used",
                HttpsURLConnection.getDefaultSSLSocketFactory(),
                connection.getSSLSocketFactory());

        webServer.shutdown();
    }

    /**
     * Tests
     * {@link javax.net.ssl.HttpsURLConnection#setSSLSocketFactory(javax.net.ssl.SSLSocketFactory)}.
     */
    public void testSetSSLSocketFactory() throws Throwable {
        // set up the properties pointing to the key/trust stores
        SSLContext ctx = getContext();

        // set the initial default host name verifier.
        TestHostnameVerifier hostnameVerifier = new TestHostnameVerifier();
        HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

        // create a webserver to check and respond to requests
        SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
        MockWebServer webServer = createWebServer(ctx, dispatcher);

        // create HttpsURLConnection to be tested
        URL url = webServer.getUrl("/");
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

        // late initialization: should not be used for the created connection.
        SSLSocketFactory socketFactory = ctx.getSocketFactory();
        connection.setSSLSocketFactory(socketFactory);

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

        // perform the interaction between the peers
        executeClientRequest(connection, false /* doOutput */);
        checkConnectionStateParameters(connection, dispatcher.getLastRequest());
        // check the verification process
        assertTrue("Hostname verification was not done", hostnameVerifier.verified);
        assertFalse("Hostname verification should not be done by this verifier",
                lateHostnameVerifier.verified);
        // check the used SSLSocketFactory
        assertNotSame("Default SSLSocketFactory should not be used",
                HttpsURLConnection.getDefaultSSLSocketFactory(),
                connection.getSSLSocketFactory());
        assertSame("Result differs from expected", socketFactory, connection.getSSLSocketFactory());

        webServer.shutdown();
    }

    /**
     * Tests the behaviour of HttpsURLConnection in case of retrieving
     * of the connection state parameters before connection has been made.
     */
    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.
     */
    public void testSetHostnameVerifier() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        SSLContext ctx = getContext();

        TestHostnameVerifier defaultHostnameVerifier = new TestHostnameVerifier();
        HttpsURLConnection.setDefaultHostnameVerifier(defaultHostnameVerifier);

        // create a webserver to check and respond to requests
        SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
        MockWebServer webServer = createWebServer(ctx, dispatcher);

        // create HttpsURLConnection to be tested
        URL url = webServer.getUrl("/");
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        connection.setSSLSocketFactory(getContext().getSocketFactory());

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

        // perform the interaction between the peers and check the results
        executeClientRequest(connection, false /* doOutput */);
        assertTrue("Hostname verification was not done", connectionHostnameVerifier.verified);
        assertFalse("Hostname verification should not be done by this verifier",
                defaultHostnameVerifier.verified);

        checkConnectionStateParameters(connection, dispatcher.getLastRequest());

        webServer.shutdown();
    }

    /**
     * Tests the behaviour in case of sending the data to the server.
     */
    public void test_doOutput() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        SSLContext ctx = getContext();

        // create a webserver to check and respond to requests
        SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(POST_METHOD, OK_CODE);
        MockWebServer webServer = createWebServer(ctx, dispatcher);

        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());

        // create HttpsURLConnection to be tested
        URL url = webServer.getUrl("/");
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        connection.setSSLSocketFactory(getContext().getSocketFactory());

        // perform the interaction between the peers and check the results
        executeClientRequest(connection, true /* doOutput */);
        checkConnectionStateParameters(connection, dispatcher.getLastRequest());

        // should silently exit
        connection.connect();

        webServer.shutdown();
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     */
    public void testProxyConnection() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        SSLContext ctx = getContext();

        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());

        // create a server that pretends to be both a proxy and then the webserver
        // request 1: proxy CONNECT, respond with OK
        ProxyConnectDispatcher proxyConnectDispatcher =
                new ProxyConnectDispatcher(false /* authenticationRequired */);
        // request 2: tunnelled GET, respond with OK
        SingleRequestDispatcher getDispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
        DelegatingDispatcher delegatingDispatcher =
                new DelegatingDispatcher(proxyConnectDispatcher, getDispatcher);
        MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);

        // create HttpsURLConnection to be tested
        URL proxyUrl = proxyAndWebServer.getUrl("/");
        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
        URL url = new URL("https://requested.host:55556/requested.data");
        HttpsURLConnection connection = (HttpsURLConnection)
                url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
        connection.setSSLSocketFactory(getContext().getSocketFactory());

        // perform the interaction between the peers and check the results
        executeClientRequest(connection, false /* doOutput */);
        checkConnectionStateParameters(connection, getDispatcher.getLastRequest());

        // should silently exit
        connection.connect();

        proxyAndWebServer.shutdown();
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     * Proxy server needs authentication.
     */
    public void testProxyAuthConnection() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        SSLContext ctx = getContext();

        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());

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

        // create a server that pretends to be both a proxy and then the webserver
        // request 1: proxy CONNECT, respond with auth challenge
        ProxyConnectAuthFailDispatcher authFailDispatcher = new ProxyConnectAuthFailDispatcher();
        // request 2: proxy CONNECT, respond with OK
        ProxyConnectDispatcher proxyConnectDispatcher =
                new ProxyConnectDispatcher(true /* authenticationRequired */);
        // request 3: tunnelled GET, respond with OK
        SingleRequestDispatcher getDispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
        DelegatingDispatcher delegatingDispatcher = new DelegatingDispatcher(
                authFailDispatcher, proxyConnectDispatcher, getDispatcher);
        MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);

        // create HttpsURLConnection to be tested
        URL proxyUrl = proxyAndWebServer.getUrl("/");
        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
        URL url = new URL("https://requested.host:55555/requested.data");
        HttpsURLConnection connection = (HttpsURLConnection)
                url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
        connection.setSSLSocketFactory(getContext().getSocketFactory());

        // perform the interaction between the peers and check the results
        executeClientRequest(connection, false /* doOutput */);
        checkConnectionStateParameters(connection, getDispatcher.getLastRequest());

        // should silently exit
        connection.connect();

        proxyAndWebServer.shutdown();
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     * Two HTTPS connections are opened for one URL: the first time the connection is opened
     * through one proxy, the second time it is opened through another.
     */
    public void testConsequentProxyConnection() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());

        // create a server that pretends to be both a proxy and then the webserver
        SingleRequestDispatcher getDispatcher1 = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
        MockWebServer proxyAndWebServer1 = createProxiedServer(getDispatcher1);

        // create HttpsURLConnection to be tested
        URL proxyUrl1 = proxyAndWebServer1.getUrl("/");
        URL url = new URL("https://requested.host:55555/requested.data");
        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl1.getPort());
        HttpsURLConnection connection = (HttpsURLConnection)
                url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
        connection.setSSLSocketFactory(getContext().getSocketFactory());
         executeClientRequest(connection, false /* doOutput */);
        checkConnectionStateParameters(connection, getDispatcher1.getLastRequest());

        proxyAndWebServer1.shutdown();

        // create another server
        SingleRequestDispatcher getDispatcher2 = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
        MockWebServer proxyAndWebServer2 = createProxiedServer(getDispatcher2);

        // create another HttpsURLConnection to be tested
        URL proxyUrl2 = proxyAndWebServer2.getUrl("/");
        InetSocketAddress proxyAddress2 = new InetSocketAddress("localhost", proxyUrl2.getPort());
        HttpsURLConnection connection2 = (HttpsURLConnection) url.openConnection(
                new Proxy(Proxy.Type.HTTP, proxyAddress2));
        connection2.setSSLSocketFactory(getContext().getSocketFactory());

        // perform the interaction between the peers and check the results
        executeClientRequest(connection2, false /* doOutput */);
        checkConnectionStateParameters(connection2, getDispatcher2.getLastRequest());

        proxyAndWebServer2.shutdown();
    }

    private static MockWebServer createProxiedServer(Dispatcher getDispatcher)
            throws Exception {
        // request 1: proxy CONNECT, respond with OK
        ProxyConnectDispatcher proxyConnectDispatcher =
                new ProxyConnectDispatcher(false /* authenticationRequired */);
        // request 2: The get dispatcher.
        DelegatingDispatcher delegatingDispatcher1 =
                new DelegatingDispatcher(proxyConnectDispatcher, getDispatcher);
        return createProxyAndWebServer(getContext(), delegatingDispatcher1);
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     * Proxy server needs authentication.
     * Client sends data to the server.
     */
    public void testProxyAuthConnection_doOutput() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        SSLContext ctx = getContext();

        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());

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

        // create a server that pretends to be both a proxy and then the webserver
        // request 1: proxy CONNECT, respond with auth challenge
        ProxyConnectAuthFailDispatcher authFailDispatcher = new ProxyConnectAuthFailDispatcher();
        // request 2: proxy CONNECT, respond with OK
        ProxyConnectDispatcher proxyConnectDispatcher =
                new ProxyConnectDispatcher(true /* authenticationRequired */);
        // request 3: tunnelled POST, respond with OK
        SingleRequestDispatcher postDispatcher = new SingleRequestDispatcher(POST_METHOD, OK_CODE);
        DelegatingDispatcher delegatingDispatcher = new DelegatingDispatcher(
                authFailDispatcher, proxyConnectDispatcher, postDispatcher);
        MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);
        URL proxyUrl = proxyAndWebServer.getUrl("/");

        // create HttpsURLConnection to be tested
        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
        HttpsURLConnection connection = (HttpsURLConnection)
                proxyUrl.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
        connection.setSSLSocketFactory(getContext().getSocketFactory());

        // perform the interaction between the peers and check the results
        executeClientRequest(connection, true /* doOutput */);
        checkConnectionStateParameters(connection, postDispatcher.getLastRequest());

        // should silently exit
        connection.connect();

        proxyAndWebServer.shutdown();
    }

    /**
     * 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).
     */
    public void testProxyAuthConnectionFailed() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());

        // create a server that pretends to be both a proxy that requests authentication.
        MockWebServer proxyAndWebServer = new MockWebServer();
        ProxyConnectAuthFailDispatcher authFailDispatcher = new ProxyConnectAuthFailDispatcher();
        proxyAndWebServer.setDispatcher(authFailDispatcher);
        proxyAndWebServer.play();

        // create HttpsURLConnection to be tested
        URL proxyUrl = proxyAndWebServer.getUrl("/");
        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
        URL url = new URL("https://requested.host:55555/requested.data");
        HttpsURLConnection connection = (HttpsURLConnection)
                url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
        connection.setSSLSocketFactory(getContext().getSocketFactory());

        // perform the interaction between the peers and check the results
        try {
            executeClientRequest(connection, false);
        } catch (IOException e) {
            // SSL Tunnelling failed
            if (DO_LOG) {
                System.out.println("Got expected IOException: " + e.getMessage());
            }
        }
    }

    /**
     * Tests the behaviour of HTTPS connection in case of unavailability of requested resource (as
     * reported by the target web server).
     */
    public void testProxyConnection_Not_Found_Response() throws Throwable {
        // set up the properties pointing to the key/trust stores
        setUpStoreProperties();

        SSLContext ctx = getContext();

        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());

        // create a server that pretends to be a proxy
        ProxyConnectDispatcher proxyConnectDispatcher =
                new ProxyConnectDispatcher(false /* authenticationRequired */);
        SingleRequestDispatcher notFoundDispatcher =
                new SingleRequestDispatcher(GET_METHOD, NOT_FOUND_CODE);
        DelegatingDispatcher delegatingDispatcher =
                new DelegatingDispatcher(proxyConnectDispatcher, notFoundDispatcher);
        MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);

        // create HttpsURLConnection to be tested
        URL proxyUrl = proxyAndWebServer.getUrl("/");
        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
        URL url = new URL("https://requested.host:55555/requested.data");
        HttpsURLConnection connection = (HttpsURLConnection)
                url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
        connection.setSSLSocketFactory(getContext().getSocketFactory());

        try {
            executeClientRequest(connection, false /* doOutput */);
            fail("Expected exception was not thrown.");
        } catch (FileNotFoundException e) {
            if (DO_LOG) {
                System.out.println("Expected exception was thrown: " + e.getMessage());
            }
        }
    }

    public void setUp() throws Exception {
        super.setUp();

        if (DO_LOG) {
            // Log the name of the test case to be executed.
            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 = getClass().getClassLoader().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();
        }
    }

    private static void checkConnectionStateParameters(
            HttpsURLConnection connection, RecordedRequest request) throws Exception {
        assertEquals(request.getSslCipherSuite(), connection.getCipherSuite());
        assertEquals(request.getSslLocalPrincipal(), connection.getPeerPrincipal());
        assertEquals(request.getSslPeerPrincipal(), connection.getLocalPrincipal());

        Certificate[] serverCertificates = connection.getServerCertificates();
        Certificate[] localCertificates = request.getSslLocalCertificates();
        assertTrue("Server certificates differ from expected",
                Arrays.equals(serverCertificates, localCertificates));

        localCertificates = connection.getLocalCertificates();
        serverCertificates = request.getSslPeerCertificates();
        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 junit.framework.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();
        String keyStore = getKeyStoreFileName();
        File keyStoreFile = new File(keyStore);
        FileInputStream fis = new FileInputStream(keyStoreFile);

        KeyStore ks = KeyStore.getInstance(type);
        ks.load(fis, KS_PASSWORD.toCharArray());
        fis.close();
        if (DO_LOG && false) {
            TestKeyStore.dump("HttpsURLConnection.getContext", ks, KS_PASSWORD.toCharArray());
        }

        String kmfAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgorithm);
        kmf.init(ks, KS_PASSWORD.toCharArray());
        KeyManager[] keyManagers = kmf.getKeyManagers();

        String tmfAlgorthm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorthm);
        tmf.init(ks);
        TrustManager[] trustManagers = tmf.getTrustManagers();
        if (DO_LOG) {
            trustManagers = TestTrustManager.wrap(trustManagers);
        }

        SSLContext ctx = SSLContext.getInstance("TLSv1");
        ctx.init(keyManagers, trustManagers, 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();

        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);
    }

    /**
     * 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;
        }
    }

    /**
     * Creates a {@link MockWebServer} that acts as both a proxy and then a web server with the
     * supplied {@link SSLContext} and {@link Dispatcher}. The dispatcher provided must handle the
     * CONNECT request/responses and {@link SocketPolicy} needed to simulate the hand-off from proxy
     * to web server. See {@link HttpsURLConnectionTest.ProxyConnectDispatcher}.
     */
    private static MockWebServer createProxyAndWebServer(SSLContext ctx, Dispatcher dispatcher)
            throws IOException {
        return createServer(ctx, dispatcher, true /* handleProxying */);
    }

    /**
     * Creates a {@link MockWebServer} that acts as (only) a web server with the supplied
     * {@link SSLContext} and {@link Dispatcher}.
     */
    private static MockWebServer createWebServer(SSLContext ctx, Dispatcher dispatcher)
            throws IOException {
        return createServer(ctx, dispatcher, false /* handleProxying */);
    }

    private static MockWebServer createServer(
            SSLContext ctx, Dispatcher dispatcher, boolean handleProxying)
            throws IOException {
        MockWebServer webServer = new MockWebServer();
        webServer.useHttps(ctx.getSocketFactory(), handleProxying /* tunnelProxy */);
        webServer.setDispatcher(dispatcher);
        webServer.play();
        return webServer;
    }

    /**
     * A {@link Dispatcher} that has a list of dispatchers to delegate to, each of which will be
     * used for one request and then discarded.
     */
    private static class DelegatingDispatcher extends Dispatcher {
        private LinkedList<Dispatcher> delegates = new LinkedList<Dispatcher>();

        public DelegatingDispatcher(Dispatcher... dispatchers) {
            addAll(dispatchers);
        }

        private void addAll(Dispatcher... dispatchers) {
            Collections.addAll(delegates, dispatchers);
        }

        @Override
        public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
            return delegates.removeFirst().dispatch(request);
        }

        @Override
        public MockResponse peek() {
            return delegates.getFirst().peek();
        }
    }

    /** Handles a request for SSL tunnel: Answers with a request to authenticate. */
    private static class ProxyConnectAuthFailDispatcher extends Dispatcher {

        @Override
        public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
            assertEquals("CONNECT", request.getMethod());

            MockResponse response = new MockResponse();
            response.setResponseCode(AUTHENTICATION_REQUIRED_CODE);
            response.addHeader("Proxy-authenticate: Basic realm=\"localhost\"");
            log("Authentication required. Sending response: " + response);
            return response;
        }

        private void log(String msg) {
            HttpsURLConnectionTest.log("ProxyConnectAuthFailDispatcher", msg);
        }
    }

    /**
     * Handles a request for SSL tunnel: Answers with a success and the socket is upgraded to SSL.
     */
    private static class ProxyConnectDispatcher extends Dispatcher {

        private final boolean authenticationRequired;

        private ProxyConnectDispatcher(boolean authenticationRequired) {
            this.authenticationRequired = authenticationRequired;
        }

        @Override
        public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
            if (authenticationRequired) {
                // check provided authorization credentials
                assertNotNull("no proxy-authorization credentials: " + request,
                        request.getHeader("proxy-authorization"));
                log("Got authenticated request:\n" + request);
                log("------------------");
            }

            assertEquals("CONNECT", request.getMethod());
            log("Send proxy response");
            MockResponse response = new MockResponse();
            response.setResponseCode(200);
            response.setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END);
            return response;
        }

        @Override
        public MockResponse peek() {
            return new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END);
        }

        private void log(String msg) {
            HttpsURLConnectionTest.log("ProxyConnectDispatcher", msg);
        }
    }

    /**
     * Handles a request: Answers with a response with a specified status code.
     * If the {@code expectedMethod} is {@code POST} a hardcoded response body {@link #POST_DATA}
     * will be included in the response.
     */
    private static class SingleRequestDispatcher extends Dispatcher {

        private final String expectedMethod;
        private final int responseCode;

        private RecordedRequest lastRequest;

        private SingleRequestDispatcher(String expectedMethod, int responseCode) {
            this.responseCode = responseCode;
            this.expectedMethod = expectedMethod;
        }

        @Override
        public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
            if (lastRequest != null) {
                fail("More than one request received");
            }
            log("Request received: " + request);
            lastRequest = request;
            assertEquals(expectedMethod, request.getMethod());
            if (POST_METHOD.equals(expectedMethod)) {
                assertEquals(POST_DATA, request.getUtf8Body());
            }

            MockResponse response = new MockResponse();
            response.setResponseCode(responseCode);
            response.setBody(RESPONSE_CONTENT);

            log("Responding with: " + response);
            return response;
        }

        public RecordedRequest getLastRequest() {
            return lastRequest;
        }

        @Override
        public MockResponse peek() {
            return new MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);
        }

        private void log(String msg) {
            HttpsURLConnectionTest.log("SingleRequestDispatcher", msg);
        }
    }

    /**
     * Executes an HTTP request using the supplied connection. If {@code doOutput} is {@code true}
     * the request made is a POST and the request body sent is {@link #POST_DATA}.
     * If {@code doOutput} is {@code false} the request made is a GET. The response must be a
     * success with a body {@link #RESPONSE_CONTENT}.
     */
    private static void executeClientRequest(
            HttpsURLConnection connection, boolean doOutput) throws IOException {

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

        log("Client", "Opening the connection to " + connection.getURL());
        connection.connect();
        log("Client", "Connection has been ESTABLISHED, using proxy: " + connection.usingProxy());
        if (doOutput) {
            log("Client", "Posting data");
            // connection configured to post data, do so
            OutputStream os = connection.getOutputStream();
            os.write(POST_DATA.getBytes());
        }
        // read the content of HTTP(s) response
        InputStream is = connection.getInputStream();
        log("Client", "Input Stream obtained");
        byte[] buff = new byte[2048];
        int num = 0;
        int byt;
        while ((num < buff.length) && ((byt = is.read()) != -1)) {
            buff[num++] = (byte) byt;
        }
        String message = new String(buff, 0, num);
        log("Client", "Got content:\n" + message);
        log("Client", "------------------");
        log("Client", "Response code: " + connection.getResponseCode());
        assertEquals(RESPONSE_CONTENT, message);
    }

    /**
     * Prints log message.
     */
    public static synchronized void log(String origin, String message) {
        if (DO_LOG) {
            System.out.println("[" + origin + "]: " + message);
        }
    }
}
