Code example for HttpsURLConnection

Methods: getCipherSuite, getClass, getLocalCertificates, getLocalPrincipal, getPeerPrincipal, getServerCertificates, setConnectTimeout, setDoInput, setDoOutput, setReadTimeout

0
        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.setSSLSocketFactory(getContext().getSocketFactory());
        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);
    } 
 
    /** 
     * 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 { 
        // setting up the properties pointing to the key/trust stores 
        setUpStoreProperties(); 
 
        // 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())));
        connection.setSSLSocketFactory(getContext().getSocketFactory());
 
        // 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());
            } 
        } 
    } 
 
    /** 
     * Tests the behaviour of HTTPS connection in case of unavailability 
     * of requested resource. 
     */ 
    public void testProxyConnection_Not_Found_Response() throws Throwable { 
        // setting up the properties pointing to the key/trust stores 
        setUpStoreProperties(); 
 
        // 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());
        HttpsURLConnection connection = (HttpsURLConnection)
                url.openConnection(new Proxy(Proxy.Type.HTTP,
                                             new InetSocketAddress("localhost",
                                                                   ss.getLocalPort())));
        connection.setSSLSocketFactory(getContext().getSocketFactory());
 
        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());
            } 
        } 
    } 
 
    /** 
     * Log the name of the test case to be executed. 
     */ 
    public void setUp() throws Exception { 
        super.setUp(); 
 
        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 = 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();
        } 
    } 
 
    /** 
     * 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 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();
 
        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);
    } 
 
    /** 
     * Performs interaction between client's HttpsURLConnection and 
     * servers side (ServerSocket). 
     */ 
    public static Socket doInteraction(final HttpsURLConnection clientConnection,
                                       final ServerSocket serverSocket)
            throws Throwable { 
        return doInteraction(clientConnection, serverSocket, OK_CODE, false);
    } 
 
    /** 
     * Performs interaction between client's HttpsURLConnection and 
     * servers side (ServerSocket). Server will response with specified 
     * response code. 
     */ 
    public static Socket doInteraction(final HttpsURLConnection clientConnection,
                                       final ServerSocket serverSocket,
                                       final int responseCode)
            throws Throwable { 
        return doInteraction(clientConnection, serverSocket, responseCode, false);
    } 
 
    /** 
     * Performs interaction between client's HttpsURLConnection 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 HttpsURLConnection 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);
 
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        try { 
            Future<Void> serverFuture = executorService.submit(server);
            Future<Void> clientFuture = executorService.submit(client);
 
            Throwable t = null;
            try { 
                serverFuture.get(30, TimeUnit.SECONDS);
            } catch (ExecutionException e) {
                t = e.getCause();
            } 
            try { 
                clientFuture.get(30, TimeUnit.SECONDS);
            } catch (ExecutionException e) {
                // two problems? log the first before overwriting 
                if (t != null) {
                    t.printStackTrace();
                } 
                t = e.getCause();
            } 
            if (t != null) {
                throw t;
            } 
        } catch (ExecutionException e) {
            throw e.getCause();
        } finally { 
            executorService.shutdown();
        } 
 
        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 { 
 
        /** 
         * The header of OK HTTP response. 
         */ 
        static final String responseHead = "HTTP/1.1 200 OK\r\n";
 
        /** 
         * The response message to be sent to the proxy CONNECT request. 
         */ 
        static final String proxyResponse = responseHead + "\r\n";
 
        /** 
         * 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\r\n" 
                + "Content-length: " + httpsResponseContent.length() + "\r\n"
                + "\r\n" 
                + httpsResponseContent;
 
        /** 
         * The response requiring client's proxy authentication. 
         */ 
        static final String respAuthenticationRequired
                = "HTTP/1.0 407 Proxy authentication required\r\n" 
                + "Proxy-authenticate: Basic realm=\"localhost\"\r\n" 
                + "\r\n"; 
 
        /** 
         * The data to be posted by client to the server. 
         */ 
        static final String clientsData = "_.-^ Client's Data ^-._";
 
        /** 
         * The print stream used for debug log. 
         * If it is null debug info will not be printed. 
         */ 
        private PrintStream out = System.out;
 
        /** 
         * Prints log message. 
         */ 
        public synchronized void log(String message) {
            if (DO_LOG && (out != null)) {
                out.println("[" + this + "]: " + message);
            } 
        } 
    } 
 
    /** 
     * The class used for server side works. 
     */ 
    static class ServerWork extends Work implements Callable<Void> {
 
        // the server socket used for connection 
        private final ServerSocket serverSocket;
 
        // indicates if the server acts as proxy server 
        private final boolean actAsProxy;
 
        // indicates if the server needs proxy authentication 
        private final boolean needProxyAuthentication;
 
        // response code to be send to the client peer 
        private final int responseCode;
 
        // the socket connected with client peer 
        private Socket peerSocket;
 
        /** 
         * 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 
            this.actAsProxy = !(serverSocket instanceof SSLServerSocket);
            if (!actAsProxy) {
                // demand client to send its certificate 
                ((SSLServerSocket) serverSocket).setNeedClientAuth(true);
            } 
        } 
 
        /** 
         * Closes the connection. 
         */ 
        public void closeSocket(Socket socket) {
            if (socket == null) {
                return; 
            } 
            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 call() throws Exception {
            // the buffer used for reading the messages 
            byte[] buff = new byte[2048];
            // the number of bytes read into the buffer 
            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();
 
                int num = is.read(buff);
                if (num == -1) {
                    log("Unexpected EOF"); 
                    return null; 
                } 
 
                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"); 
                        String data = message.substring(message.indexOf("\r\n\r\n")+4);
                        int dataNum = is.read(buff);
                        if (dataNum != -1) {
                            data += new String(buff, 0, dataNum);
                        } 
                        log("client's data: '" + data + "'");
                        // check the received data 
                        assertEquals(clientsData, data);
                    } 
                } else { 
                    if (needProxyAuthentication) {
                        // Do proxy work 
                        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);
                    } 
 
                    assertTrue(message.startsWith("CONNECT"));
                    // request for SSL tunnel 
                    log("Send proxy response"); 
                    os.write(proxyResponse.getBytes());
 
                    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"); 
                        String data = message.substring(message.indexOf("\r\n\r\n")+4);
                        int dataNum = is.read(buff);
                        if (dataNum != -1) {
                            data += new String(buff, 0, dataNum);
                        } 
                        log("[Remote Server] client's data: '" + message + "'");
                        // check the received data 
                        assertEquals(clientsData, data);
                    } 
 
                    log("[Remote Server] Sending the response by SSL tunnel..."); 
                } 
 
                // send the response with specified response code 
                os.write(("HTTP/1.1 " + responseCode
                          + " Message\r\n" + httpsResponseTail).getBytes());
                os.flush();
                os.close();
                log("Work is DONE actAsProxy=" + actAsProxy);
                return null; 
            } finally { 
                closeSocket(peerSocket);
                try { 
                    serverSocket.close();
                } catch (IOException e) {}
            } 
        } 
 
        @Override public String toString() {
            return actAsProxy ? "Proxy Server" : "Server";
        } 
    } 
 
    /** 
     * The class used for client side work. 
     */ 
    static class ClientConnectionWork extends Work implements Callable<Void> {
 
        // connection to be used to contact the server side 
        private HttpsURLConnection connection;
 
        /** 
         * Creates the thread acting as a client side. 
         * @param connection connection to be used to contact the server side 
         */ 
        public ClientConnectionWork(HttpsURLConnection connection) {
            this.connection = connection;
            log("Created over connection: " + connection.getClass());
        } 
 
        /** 
         * Performs the actual client work. 
         * If some exception occurs during the work it will be