/*
 * Copyright (c) 2017, 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
 */

/*
 * TestJSR88Concurrency.java
 *
 * Created on September 19, 2006, 3:52 PM
 *
 */

package devtests.deployment.jsr88.apitests;

import com.sun.enterprise.deployapi.SunDeploymentFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.enterprise.deploy.shared.ModuleType;
import javax.enterprise.deploy.spi.DeploymentManager;
import javax.enterprise.deploy.spi.Target;
import javax.enterprise.deploy.spi.TargetModuleID;
import javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException;
import javax.enterprise.deploy.spi.exceptions.TargetException;
import javax.enterprise.deploy.spi.factories.DeploymentFactory;

/**
 *Tests concurrent use of the same deployment connection to the back-end.
 *<p>
 *You can use this program to create multiple threads in the same JVM (all
 *running the same task) or to run multiple copies of the program in different
 *JVMs but synchronized.
 *<p>
 *arguments:
 * --host <host>
 * --port <port>
 * --username <username>
 * --password <password>
 * --operation <operation>[*<n>]
 * --startTime <testStartTime> (as H:mm:ss)
 * --delay <delayTime) (in ms)
 * --secure <true or false>
 *<p>
 *where <operation> can be getTargets, getApps, loopGetTargets");
 *  n (default=1) is the number of concurrent threads to share the connection at once
 *  testStartTime is a time in the current day, specified as [H]H:mm:ss  default is to start immediately
 *<p>
 *The getTargets and getApps tasks invoke the corresponding back-end method only
 *once in each thread.  The loopGetTargets is more likely to induce problems if
 *there are race conditions somewhere in the code path, since it invokes the
 *getTargets method multiple times from each thread.
 *<p>
 *The system property sleep.time, if set, is used as the delay between when
 *multiple threads are started.  This is normally not needed but could be used
 *to stagger the requests from the threads that are started to see if doing
 *so avoids any race conditon that is revealed by starting the threads
 *without delay.
 *
 *The classpath must include:
 *  javaee.jar
 *  appserv-deployment-client.jar
 *  appserv-admin.jar
 *
 * @author tjquinn
 */
public class TestJSR88Concurrency {

    private DeploymentFactory factory;

    private DeploymentManager manager;

    private static final String HOST = "--host";
    private static final String PORT = "--port";
    private static final String USERNAME = "--username";
    private static final String PASSWORD = "--password";
    private static final String OPERATION = "--operation";
    private static final String START_TIME = "--startTime";
    private static final String DELAY = "--delay";
    private static final String SECURE = "--secure";
    private static final String TIMEOUT = "--timeout";

    /** initialization info for the command-line option names and defaults, if any */
    private static final String[][] optionsAndDefaults = new String[][]
        { {HOST, "localhost"},
          {PORT, "4848"},
          {USERNAME, "admin"},
          {PASSWORD, "adminadmin"},
          {OPERATION, null}, // no default value
          {START_TIME, null}, // no default value
          {DELAY, "0"},
          {SECURE, "false"},
          {TIMEOUT, "10000"} // 10 seconds
    };

    /* command-line option names and values */
    private HashMap<String,String> options;

    /* used to control how many iterations of the loopGetTargets will run */
    private static final int LOOP_MAX = 100;

    /**
     * Creates a new instance of TestJSR88Concurrency
     */
    public TestJSR88Concurrency() {
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            new TestJSR88Concurrency().run(args);
        } catch (Throwable thr) {
            thr.printStackTrace();
            System.exit(1);
        }
    }

    private void run(String[] args) throws DeploymentManagerCreationException, TargetException, InterruptedException, ParseException, UserException {
        try {
            prepareArgs(args);
            factory = initFactory();
            manager = initManager(
                    getHost(),
                    getPort(),
                    getUsername(),
                    getPassword(),
                    options.get(SECURE).equalsIgnoreCase("true"));

            waitForTargetTime();

            processFunction(getOperation());
        } catch (UserException ue) {
            System.err.println("User error: " + ue.getMessage());
            System.exit(1);
        }

    }

    private void waitForTargetTime() throws ParseException, InterruptedException {
        if (getTargetTimeText() == null) {
            System.out.println("No start delay specified; continuing immediately");
            return;
        }
        SimpleDateFormat targetTimeFormat = new SimpleDateFormat("H:mm:ss");
        Calendar targetTime = Calendar.getInstance();
        targetTime.setTime(targetTimeFormat.parse(getTargetTimeText()));

        Calendar now = Calendar.getInstance();
        targetTime.set(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH));
        System.out.println("Currently it is " + now.getTime().toString());
        System.out.println("Waiting until   " + targetTime.getTime().toString());
        Thread.sleep(targetTime.getTimeInMillis() - System.currentTimeMillis());
        System.out.println("Proceeding");
    }

    private void prepareArgs(String[] args) throws UserException {
        options = initOptionsMap();

        int i = 0;
        while (i < args.length) {
            if (options.containsKey(args[i])) {
                options.put(args[i], getRequiredOptionValue(args, ++i));
            } else if (args[i].startsWith("--")) {
                throw new UserException("Unrecognized option " + args[i]);
            }
            i++;
        }

        ensureRequiredInfoSupplied();
    }

    private void ensureRequiredInfoSupplied() throws UserException {
        if (getOperation() == null) {
            throw new UserException("Expected --operation <operation[*n]> but none was found");
        }
    }

    private HashMap<String,String> initOptionsMap() {
        HashMap<String,String> result = new HashMap<String,String>();
        for (String[] optionAndValue : optionsAndDefaults) {
            result.put(optionAndValue[0], optionAndValue[1]);
        }
        return result;
    }

    private String getRequiredOptionValue(String[] args, int valuePosition) throws UserException {
        if ((valuePosition >= args.length) || (args[valuePosition].startsWith("--"))) {
            throw new UserException("No value available for " + args[valuePosition - 1]);
        }
        return args[valuePosition];
    }

    private void usage() {
        System.out.println("devtests.deployment.jsr88.apitests.TestJSR88Concurrency --host <host> --port <port> --username <username> --password <password> --operation <operation>[*<n>] --startTime testStartTime (as H:mm:ss) --delay <delay-in-ms> --secure true/false");
        System.out.println("  where <operation> can be getTargets, getApps, loopGetTargets");
        System.out.println("  n (default=1) is the number of concurrent threads to share the connection at once");
        System.out.println("  testStartTime is a time in the current day, specified as [H]H:mm:ss  default is to start immediately");
        System.out.println("  delay is the number of milliseconds to wait between starting threads");
    }

    private DeploymentFactory initFactory() {
        /*
         *We know we are testing our factory, so just instantiate it.
         */
        return new SunDeploymentFactory();
    }

    private DeploymentManager initManager(
            String host,
            String port,
            String username,
            String password,
            boolean secure) throws DeploymentManagerCreationException {
        String url = "deployer:Sun:AppServer::" + host + ":" + port + getConnectionStringSuffix(secure);
        return factory.getDeploymentManager(url, username, password);
    }

    private void processFunction(String function) throws TargetException, InterruptedException {
        /*
         *The star, if present, separates the operation name from the number of
         *threads on which to run that operation.
         */
        String[] pieces = function.split("\\*");
        long delay = getDelay();
        int parallelThreadCount = 1;
        if (pieces.length > 1) {
            parallelThreadCount = Integer.parseInt(pieces[1]);
        }
        if (parallelThreadCount == 1) {
            performFunction(pieces[0], 1);
        } else {
            Thread[] threads = new Thread[parallelThreadCount];
            AtomicBoolean[] threadOK = new AtomicBoolean[parallelThreadCount];
            for (int i = 0; i < parallelThreadCount; i++) {
                threadOK[i] = new AtomicBoolean();
                threads[i] = new Thread(new Runner(pieces[0], i, threadOK[i]));
                threads[i].start();
                /*
                 *No need to wait if we just started the last thread.
                 */
                if (delay != 0 && i < parallelThreadCount - 1) {
                    Thread.currentThread().sleep(delay);
                }
            }
            boolean allThreadsOK = true;
            for (int i = 0; i < parallelThreadCount; i++) {
                Thread t = threads[i];
                t.join(getTimeout());
                allThreadsOK &= threadOK[i].get();
            }

            if ( ! allThreadsOK) {
                throw new RuntimeException("At least one thread failed");
            }
        }
    }

    private void printTargets(int threadID) {

        System.out.println("[" + threadID + "]Targets:");
        for (Target t : getTargets()) {
            System.out.println("[" + threadID + "]  " + t.getName());
        }
        System.out.println();
    }

    private Target[] getTargets() {
        return manager.getTargets();
    }

    private TargetModuleID[] getApps() throws TargetException {
        Target[] targets = getTargets();
        ModuleType[] types = new ModuleType[] {ModuleType.EJB, ModuleType.EAR, ModuleType.CAR, ModuleType.RAR};
        List<TargetModuleID> result = new ArrayList<TargetModuleID>();
        for (ModuleType mt : types) {
            result.addAll(Arrays.asList(manager.getAvailableModules(mt, targets)));
        }
        return result.toArray(new TargetModuleID[result.size()]);
    }

    private void printApps(int threadID) throws TargetException {
        System.out.println("[" + threadID + "]Applications:");
        for (TargetModuleID id : getApps()) {
            System.out.println("[" + threadID + "]  " + id.getModuleID());
        }
        System.out.println("[" + threadID + "]");
    }

    private void loopGetTargets() {
        getTargets(); // to warm up the connection
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < LOOP_MAX; i++) {
            getTargets();
        }
        System.out.println((System.currentTimeMillis() - startTime));
    }

    private void performFunction(String function, int threadID) throws TargetException {
        if (function.equals("getTargets")) {
            printTargets(threadID);
        } else if (function.equals("getApps")) {
            printApps(threadID);
        } else if (function.equals("loopGetTargets")) {
            loopGetTargets();
        } else {
            System.err.println("No recognized function in thread " + threadID);
        }
    }

    private void multiGetApps() {

    }

    private String getStartTimeText() {
        return options.get(START_TIME);
    }

    private String getHost() {
        return options.get(HOST);
    }

    private String getPort() {
        return options.get(PORT);
    }

    private String getUsername() {
        return options.get(USERNAME);
    }

    private String getPassword() {
        return options.get(PASSWORD);
    }

    private String getOperation() {
        return options.get(OPERATION);
    }

    private String getTargetTimeText() {
        return options.get(START_TIME);
    }

    private long getDelay() {
        return Long.parseLong(options.get(DELAY));
    }

    private String getConnectionStringSuffix(boolean secure) {
        return secure ? ":https" : "";
    }

    private long getTimeout() {
        return Long.parseLong(options.get(TIMEOUT));
    }

    private class Runner implements Runnable {

        private String function;
        private int threadID;
        private AtomicBoolean result;

        public Runner(String function, int threadID, AtomicBoolean result) {
            Runner.this.function = function;
            this.threadID = threadID;
            this.result = result;
        }

        public void run() {
            try {
                performFunction(function, threadID);
                result.set(true);
            } catch (Throwable thr) {
                result.set(false);
                synchronized (TestJSR88Concurrency.this) {
                    System.err.println(Thread.currentThread().getName());
                    thr.printStackTrace();
                }
            }

        }
    }

    /**
     *Indicates a user error, such as a missing command-line value, that should
     *be displayed without a stack trace.
     */
    public class UserException extends Exception {
        public UserException(String msg) {
            super(msg);
        }
    }
}
