/*
 * 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.sling.testing.serversetup.jarexec;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Properties;
import java.util.regex.Pattern;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.ExecuteResultHandler;
import org.apache.commons.exec.Executor;
import org.apache.commons.exec.PumpStreamHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Start a runnable jar by forking a JVM process,
 *  and terminate the process when this VM exits.
 */
public class JarExecutor {
    private final File jarToExecute;
    private final String jvmFullPath;
    private final int serverPort;
    private final Properties config;
    private Executor executor;

    private final Logger log = LoggerFactory.getLogger(getClass());

    public static final int DEFAULT_PORT = 8765;
    public static final int DEFAULT_EXIT_TIMEOUT = 30;

    public static final String DEFAULT_JAR_FOLDER = "target/dependency";
    public static final String DEFAULT_JAR_NAME_REGEXP = "org.apache.sling.*jar$";
    public static final String PROP_PREFIX = "jar.executor.";
    public static final String PROP_SERVER_PORT = PROP_PREFIX + "server.port";
    public static final String PROP_JAR_FOLDER = PROP_PREFIX + "jar.folder";
    public static final String PROP_JAR_NAME_REGEXP = PROP_PREFIX + "jar.name.regexp";
    public static final String PROP_VM_OPTIONS = PROP_PREFIX + "vm.options";
    public static final String PROP_WORK_FOLDER = PROP_PREFIX + "work.folder";
    public static final String PROP_JAR_OPTIONS = PROP_PREFIX + "jar.options";
    public static final String PROP_EXIT_TIMEOUT_SECONDS = PROP_PREFIX + "exit.timeout.seconds";
    public static final String PROP_WAIT_ONSHUTDOWN = PROP_PREFIX + "wait.on.shutdown";
    public static final String PROP_JAVA_PATH = PROP_PREFIX + "java.executable.path";
    public static final String PROP_SYNC_EXEC = PROP_PREFIX + "synchronous.exec";
    public static final String PROP_SYNC_EXEC_EXPECTED = PROP_PREFIX + "synchronous.exec.expected.result";

    @SuppressWarnings("serial")
    public static class ExecutorException extends Exception {
        ExecutorException(String reason) {
            super(reason);
        }
        ExecutorException(String reason, Throwable cause) {
            super(reason, cause);
        }
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + ": " + jarToExecute.getName() + " (port " + serverPort + ")";
    }

    public int getServerPort() {
        return serverPort;
    }

    /** Build a JarExecutor, locate the jar to run, etc */
    public JarExecutor(Properties config) throws ExecutorException {
        this.config = config;
        final boolean isWindows = System.getProperty("os.name").toLowerCase().contains("windows");

        String portStr = config.getProperty(PROP_SERVER_PORT);
        serverPort = portStr == null ? DEFAULT_PORT : Integer.valueOf(portStr);

        final String configJvmPath = config.getProperty(PROP_JAVA_PATH);
        if(configJvmPath == null) {
            final String javaExecutable = isWindows ? "java.exe" : "java";
            jvmFullPath = System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + javaExecutable;
        } else {
            jvmFullPath = configJvmPath;
        }

        String jarFolderPath = config.getProperty(PROP_JAR_FOLDER);
        jarFolderPath = jarFolderPath == null ? DEFAULT_JAR_FOLDER : jarFolderPath;
        final File jarFolder = new File(jarFolderPath);

        String jarNameRegexp = config.getProperty(PROP_JAR_NAME_REGEXP);
        jarNameRegexp = jarNameRegexp == null ? DEFAULT_JAR_NAME_REGEXP : jarNameRegexp;
        final Pattern jarPattern = Pattern.compile(jarNameRegexp);

        // Find executable jar
        final String [] candidates = jarFolder.list();
        if(candidates == null) {
            throw new ExecutorException(
                    "No files found in jar folder specified by "
                    + PROP_JAR_FOLDER + " property: " + jarFolder.getAbsolutePath());
        }
        File f = null;
        for(String filename : candidates) {
            if(jarPattern.matcher(filename).matches()) {
                f = new File(jarFolder, filename);
                break;
            }
        }

        if(f == null) {
            throw new ExecutorException("Executable jar matching '" + jarPattern
                    + "' not found in " + jarFolder.getAbsolutePath()
                    + ", candidates are " + Arrays.asList(candidates));
        }
        jarToExecute = f;
    }

    /** Start the jar if not done yet, and setup runtime hook
     *  to stop it.
     */
    public void start() throws Exception {
        final ExecuteResultHandler h = new ExecuteResultHandler() {
            public void onProcessFailed(ExecuteException ex) {
                log.error("Process execution failed:" + ex, ex);
            }

            public void onProcessComplete(int result) {
                log.info("Process execution complete, exit code=" + result);
            }
        };

        final String vmOptions = config.getProperty(PROP_VM_OPTIONS);
        executor = new DefaultExecutor();
        final CommandLine cl = new CommandLine(jvmFullPath);
        if (vmOptions != null && vmOptions.length() > 0) {
            cl.addArguments(vmOptions);
        }
        cl.addArgument("-jar");
        cl.addArgument(jarToExecute.getAbsolutePath());

        // Additional options for the jar that's executed.
        // $JAREXEC_SERVER_PORT$ is replaced our serverPort value
        String jarOptions = config.getProperty(PROP_JAR_OPTIONS);
        if(jarOptions != null && jarOptions.length() > 0) {
            jarOptions = jarOptions.replaceAll("\\$JAREXEC_SERVER_PORT\\$", String.valueOf(serverPort));
            log.info("Executable jar options: {}", jarOptions);
            cl.addArguments(jarOptions);
        }

        final String workFolderOption = config.getProperty(PROP_WORK_FOLDER);
        if(workFolderOption != null && workFolderOption.length() > 0) {
            final File workFolder = new File(workFolderOption);
            if(!workFolder.isDirectory()) {
                throw new IOException("Work dir set by " + PROP_WORK_FOLDER + " option does not exist: "
                        + workFolder.getAbsolutePath());
            }
            log.info("Setting working directory for executable jar: {}", workFolder.getAbsolutePath());
            executor.setWorkingDirectory(workFolder);
        }

        String tmStr = config.getProperty(PROP_EXIT_TIMEOUT_SECONDS);
        final int exitTimeoutSeconds = tmStr == null ? DEFAULT_EXIT_TIMEOUT : Integer.valueOf(tmStr);

        if("true".equals(config.getProperty(PROP_SYNC_EXEC, ""))) {
            final long start = System.currentTimeMillis();
            log.info("Executing and waiting for result: " + cl);
            final int result = executor.execute(cl);
            final int expected = Integer.valueOf(config.getProperty(PROP_SYNC_EXEC_EXPECTED, "0"));
            log.info("Execution took " + (System.currentTimeMillis() - start) + " msec");
            if(result != expected) {
                throw new ExecutorException("Expected result code " + expected + ", got " + result);
            }
        } else {
            log.info("Executing asynchronously: " + cl);
            executor.setStreamHandler(new PumpStreamHandler());
            final ShutdownHookSingleProcessDestroyer pd = new ShutdownHookSingleProcessDestroyer("java -jar " + jarToExecute.getName(), exitTimeoutSeconds);
            final boolean waitOnShutdown = Boolean.valueOf(config.getProperty(PROP_WAIT_ONSHUTDOWN, "false"));
            log.info("Setting up ProcessDestroyer with waitOnShutdown=" + waitOnShutdown);
            pd.setWaitOnShutdown(waitOnShutdown);
            executor.setProcessDestroyer(pd);
            executor.execute(cl, h);
        }
    }

    /** Stop the process that we started, if any, and wait for it to exit before returning */
    public void stop() {
        if(executor == null) {
            throw new IllegalStateException("Process not started, no Executor set");
        }
        final Object d = executor.getProcessDestroyer();
        if(d instanceof ShutdownHookSingleProcessDestroyer) {
            ((ShutdownHookSingleProcessDestroyer)d).destroyProcess(true);
            log.info("Process destroyed");
        } else {
            throw new IllegalStateException(d + " is not a Runnable, cannot destroy process");
        }
    }
}
