/*
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

import java.io.*;
import java.net.*;
import com.sun.ejte.ccl.reporter.*;

/**
 * Unit test to ensure that the state of a virtual server may be
 * changed without requiring a server restart.
 *
 * This test:
 *
 * 1. Creates a virtual-server myvs and deploys a webapp to it
 *
 * 2. Makes sure that the webapp may be accessed
 *
 * 3. Disables the virtual server and ensures that a 403 response is
 *    returned when the webapp is accessed
 *
 * 4. Turns off the virtual server and ensures that a 404 response is
 *    returned when the webapp is accessed
 *
 * 5. Re-enables the virtual server and makes sure that the webapp may be
 *    accessed again.
 */
public class WebTest {

    private static SimpleReporterAdapter stat
        = new SimpleReporterAdapter("appserv-tests");

    private static String TEST_NAME = null;

    private static final String TEST_ROOT_NAME
        = "virtual-server-state-dynamic-reconfig";

    private static final String ON_RESPONSE = "Success!";

    private static final String DISABLED_RESPONSE
        = "HTTP/1.1 403 Virtual server myvs has been disabled";

    private static final String OFF_RESPONSE
        = "HTTP/1.1 404 Virtual server myvs has been turned off";

    private String host;
    private String port;
    private String contextRoot;
    private String run;

    public WebTest(String[] args) {
        host = args[0];
        port = args[1];
        contextRoot = args[2];
        run = args[3];
    }

    public static void main(String[] args) {
        stat.addDescription("Unit test for disabling a virtual server");
        WebTest webTest = new WebTest(args);

        try {
            if ("on".equals(webTest.run)) {
                TEST_NAME = TEST_ROOT_NAME + "-on";
                webTest.onRun();
            } else if ("disabled".equals(webTest.run)) {
                TEST_NAME = TEST_ROOT_NAME + "-disabled";
                webTest.disabledRun();
            } else if ("off".equals(webTest.run)) {
                TEST_NAME = TEST_ROOT_NAME + "-off";
                webTest.offRun();
            }
            stat.addStatus(TEST_NAME, stat.PASS);
        } catch (Exception ex) {
            stat.addStatus(TEST_NAME, stat.FAIL);
            ex.printStackTrace();
        }

        stat.printSummary(TEST_NAME);
    }

    /**
     * Make sure the webapp may be accessed on the newly created virtual
     * server.
     */
    private void onRun() throws Exception {

        Socket sock = new Socket(host, new Integer(port).intValue());
        OutputStream os = sock.getOutputStream();
        String get = "GET " + contextRoot + "/test.txt HTTP/1.1\n";
        System.out.println(get);
        os.write(get.getBytes());
        os.write("Host: myvs\n".getBytes());
        os.write("Connnection: Close\n".getBytes());
        os.write("\n".getBytes());

        InputStream is = sock.getInputStream();
        BufferedReader bis = new BufferedReader(new InputStreamReader(is));

        String line = null;
        while ((line = bis.readLine()) != null) {
            System.out.println(line);
            if (line.equals(ON_RESPONSE)) {
                break;
            }
        }

        if (line == null) {
            throw new Exception("Missing expected response: " +
                                ON_RESPONSE);
        }
    }

    /**
     * Make sure that a 403 response is returned when trying to access the
     * webapp after the virtual server on which it is deployed has been
     * disabled.
     */
    private void disabledRun() throws Exception {

        Socket sock = new Socket(host, new Integer(port).intValue());
        OutputStream os = sock.getOutputStream();
        String get = "GET " + contextRoot + "/test.txt HTTP/1.1\n";
        System.out.println(get);
        os.write(get.getBytes());
        os.write("Host: myvs\n".getBytes());
        os.write("Connnection: Close\n".getBytes());
        os.write("\n".getBytes());

        InputStream is = sock.getInputStream();
        BufferedReader bis = new BufferedReader(new InputStreamReader(is));

        String line = null;
        while ((line = bis.readLine()) != null) {
            System.out.println(line);
            if (line.contains(DISABLED_RESPONSE)) {
                break;
            }
        }

        if (line == null) {
            throw new Exception("Missing expected response: " +
                                DISABLED_RESPONSE);
        }
    }

    /**
     * Make sure that a 404 response is returned when trying to access the
     * webapp after the virtual server on which it is deployed has been
     * turned off.
     */
    private void offRun() throws Exception {

        Socket sock = new Socket(host, new Integer(port).intValue());
        OutputStream os = sock.getOutputStream();
        String get = "GET " + contextRoot + "/test.txt HTTP/1.1\n";
        System.out.println(get);
        os.write(get.getBytes());
        os.write("Host: myvs\n".getBytes());
        os.write("Connnection: Close\n".getBytes());
        os.write("\n".getBytes());

        InputStream is = sock.getInputStream();
        BufferedReader bis = new BufferedReader(new InputStreamReader(is));

        String line = null;
        while ((line = bis.readLine()) != null) {
            System.out.println(line);
            if (line.contains(OFF_RESPONSE)) {
                break;
            }
        }

        if (line == null) {
            throw new Exception("Missing expected response: " +
                                OFF_RESPONSE);
        }
    }

}
