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

package com.sun.enterprise.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.util.ArrayList;


/**
 * @author Kedar
 * @version 1.0
 * @deprecated Use ProcessManager instead
 */
@Deprecated
public class ProcessExecutor {
    public static final long kDefaultTimeoutMillis = 600000;
    public static final long kSleepTime = 2000;
    private static final long DEFAULT_TIMEOUT_SEC = 600;
    private static final String NEWLINE = System.getProperty("line.separator");
    private long mTimeoutMilliseconds = 0;
    protected String[] mCmdStrings = null;
    protected File mOutFile = null;
    protected File mErrFile = null;
    private OutputStream mOutStream = null;
    private OutputStream mErrStream = null;
    private File mWorkingDir = null; //working directory
    private String[] mEnv = null; //environment
    private String[] mInputLines = null; // strings to set in process's InputStream (like from redirection)
    private int mExitValue = -1;
    private Process mSubProcess = null; // used to get handle to child process for ProcessManager funtionality
    private boolean mVerboseMode = false;
    private boolean retainExecutionLogs = false;
    private String lastExecutionOutputString = null;
    private String lastExecutionErrorString = null;
    private boolean bDebug = false;

    /**
     * Creates new ProcessExecutor
     */
    public ProcessExecutor(String[] cmd) {
        this(cmd, DEFAULT_TIMEOUT_SEC, null);
    }

    /**
     * Creates new ProcessExecutor
     */
    public ProcessExecutor(String[] cmd, String[] inputLines) {
        this(cmd, DEFAULT_TIMEOUT_SEC, inputLines);
    }

    /**
     * Creates new ProcessExecutor
     */
    public ProcessExecutor(String[] cmd, long timeoutSeconds) {
        this(cmd, timeoutSeconds, null);
    }

    public ProcessExecutor(String[] cmd, long timeoutSeconds, String[] inputLines) {
        this(cmd, timeoutSeconds, inputLines, null, null);
    }

    /**
     * Creates a new
     * <code> ProcessExecutor </code> that executes the given command.
     *
     * @param cmd String that has command name and its command line arguments
     * @param timeoutSeconds long integer timeout to be applied in seconds.
     * After this time if the process to execute does not end, it will be
     * destroyed.
     */
    public ProcessExecutor(String[] cmd, long timeoutSeconds, String[] inputLines,
            String[] env, File workingDir) {
        mCmdStrings = cmd;
        mInputLines = inputLines;
        mEnv = env;
        mWorkingDir = workingDir;
        char fwdSlashChar = '/';
        char backSlashChar = '\\';

        if (System.getProperty("Debug") != null) {
            // turn on debug, this option was added to help developers
            // debug the their code
            bDebug = true;
        }

        for (int i = 0; i < mCmdStrings.length; i++) {
            if (OS.isUnix()) {
                mCmdStrings[i] = mCmdStrings[i].replace(backSlashChar, fwdSlashChar);
            }
            else {
                mCmdStrings[i] = mCmdStrings[i].replace(fwdSlashChar, backSlashChar);
            }
        }
        mTimeoutMilliseconds = timeoutSeconds * 1000;
    }

    /**
     * This is the setting after the fact that an instance of ProcessExecutor is
     * created. This is to be used in case the output and error of the last
     * execute call has to be retained for latter analysis.
     *
     * @param s boolean representing whether to retain, true means the buffers
     * will be retained, false otherwise.
     */
    public void setExecutionRetentionFlag(final boolean s) {
        this.retainExecutionLogs = s;
    }

    public boolean getExecutionRetentionFlag() {
        return (this.retainExecutionLogs);
    }

    /**
     * Returns the last LAST_BYTES bytes in the error stream of last execution
     * as a String, if the ProcessExecutor was configured properly. It may
     * return null if the retentionFlag is set to false.
     */
    public String getLastExecutionError() {
        return (this.lastExecutionErrorString);
    }

    /**
     * Returns the last LAST_BYTES bytes in the output stream of last execution
     * as a String, if the ProcessExecutor was configured properly. It may
     * return null if the retentionFlag is set to false.
     */
    public String getLastExecutionOutput() {
        return (this.lastExecutionOutputString);
    }

    private void init() throws ExecException {
        try {
            mOutFile = File.createTempFile("stdout", null);
            mOutFile.deleteOnExit();
            mErrFile = File.createTempFile("stderr", null);
            mErrFile.deleteOnExit();
        }
        catch (IllegalArgumentException iae) {
            deleteTempFiles();
            throw new ExecException("Internal error (util.ProcessExecutor.init()): " + iae.getMessage());
        }
        catch (IOException ioe) {
            deleteTempFiles();
            throw new ExecException(cannotCreateTempFiles());
        }
    }

    private final static String cannotCreateTempFiles() {
        return "Could not create temporary files - check "
                + System.getProperty("java.io.tmpdir")
                + " to see if its writeable and not-full";
    }

    private void deleteTempFiles() {
        if (mOutStream != null) {
            try {
                mOutStream.flush();
                mOutStream.close();
            }
            catch (IOException ioe) {
                // Ignore
            }
        }

        if (mErrStream != null) {
            try {
                mErrStream.flush();
                mErrStream.close();
            }
            catch (IOException ioe) {
                // Ignore
            }
        }
        if (mOutFile != null)
            delete(mOutFile);
        if (mErrFile != null)
            delete(mErrFile);
    }

    public void execute() throws ExecException {
        execute(false);
    }

    /*
     * Executes the command. Redirects the standard output and error streams
     * safely to files. This makes the subprocess NOT block or wait on buffers
     * getting flushed. This is done in a threaded manner. Note that the
     * subprocess will be killed if it does not end in given timeout.
     *
     * @throws ExecException if anything goes wrong in subprocess, or subprocess
     * terminates abruptly.
     */
    public String[] execute(boolean bReturnOutputLines) throws ExecException {
        return execute(bReturnOutputLines, true);
    }

    /**
     * Allows a subclass to control the error message returned when a non-zero
     * exit code is returned from a failed execution
     *
     * @return
     */
    protected String getExceptionMessage() {
        /*
         * read the error message from error file
         */
        String errorMessage = getFileBuffer(mErrFile);
        if (errorMessage.length() == 0) {
            errorMessage = "The Process Output: " + getLatestOutput(mOutFile);
        }
        return "abnormal subprocess termination: Detailed Message:" + errorMessage;
    }

    /*
     * Executes the command. Redirects the standard output and error streams
     * safely to files. This makes the subprocess NOT block or wait on buffers
     * getting flushed. This is done in a threaded manner. Note that the
     * subprocess will be killed if it does not end in given timeout.
     *
     * @throws ExecException if anything goes wrong in subprocess, or subprocess
     * terminates abruptly.
     */
    public String[] execute(boolean bReturnOutputLines, boolean bStartUpTimeLimit) throws ExecException {
        init();
        InputStream inputStream = null;
        try {

            if (bDebug) {
                System.out.println("\n**** Executing command:");
                for (int ii = 0; ii < mCmdStrings.length; ii++) {
                    System.out.println(mCmdStrings[ii]);
                }
            }

            mSubProcess = Runtime.getRuntime().exec(mCmdStrings, mEnv, mWorkingDir);
            if (mInputLines != null)
                addInputLinesToProcessInput(mSubProcess);
            if (!bReturnOutputLines)
                mOutStream = redirectProcessOutput(mSubProcess);
            else
                inputStream = mSubProcess.getInputStream(); //attach to input stream for later reading
            mErrStream = redirectProcessError(mSubProcess);

            // see if process should startup in a limited ammount of time
            // processes used by ProcessManager don't return
            if (bStartUpTimeLimit) {
                long timeBefore = System.currentTimeMillis();
                boolean timeoutReached = false;
                boolean isSubProcessFinished = false;
                boolean shouldBeDone = false;
                while (!shouldBeDone) {
                    sleep(kSleepTime);
                    long timeAfter = System.currentTimeMillis();
                    timeoutReached = (timeAfter - timeBefore) >= mTimeoutMilliseconds;
                    try {
                        mExitValue = mSubProcess.exitValue();
                        isSubProcessFinished = true;
                    }
                    catch (IllegalThreadStateException itse) {
                        isSubProcessFinished = false;
                        //ignore exception
                    }
                    shouldBeDone = timeoutReached || isSubProcessFinished;
                }
                if (!isSubProcessFinished) {
                    mSubProcess.destroy();
                    mExitValue = -255;
                    throw new ExecException("Subprocess timed out after " + mTimeoutMilliseconds + "mS");
                }
                else {
                    mExitValue = mSubProcess.exitValue();
                    if (debug()) {
                        System.out.println("Subprocess command line = " + a2s(mCmdStrings));
                        System.out.println("Subprocess exit value = " + mExitValue);
                    }
                    if (mExitValue != 0) {
                        mExitValue = mSubProcess.exitValue();
                        if (mExitValue != 0) {
                            throw new ExecException(getExceptionMessage());
                        }
                    }
                }
            }
        }
        catch (SecurityException se) {
            throw new ExecException(se.getMessage());
        }
        catch (IOException ioe) {
            throw new ExecException(ioe.getMessage());
        }
        finally {

            // retain buffers before deleting them
            retainBuffers();

            // only delete files if the time is limited
            // for processes that don't return, the temp files will remain
            if (bStartUpTimeLimit) {
                deleteTempFiles();
            }
        }

        if (bReturnOutputLines) {
            return getInputStrings(inputStream);
        }
        else {
            return null;
        }

    }

    /**
     * Get the exit value of the process executed. If this method is called
     * before process execution is complete (i.e. before execute() method has
     * returned, it will return -1. If sub process is terminated at timeout, the
     * method will return -255
     */
    public int getProcessExitValue() {
        return mExitValue;
    }

    private void addInputLinesToProcessInput(Process subProcess) throws ExecException {
        if (mInputLines == null)
            return;

        PrintWriter out = null;
        try {
            out = new PrintWriter(new BufferedWriter(
                    new OutputStreamWriter(subProcess.getOutputStream())));

            for (int i = 0; i < mInputLines.length; i++) {
                if (bDebug) {
                    System.out.println("InputLine ->" + mInputLines[i] + "<-");
                }
                out.println(mInputLines[i]);
            }
            out.flush();
        }
        catch (Exception e) {
            throw new ExecException(e.getMessage());
        }
        finally {
            try {
                out.close();
            }
            catch (Throwable t) {
            }
        }
    }

    private String[] getInputStrings(InputStream inputStream) throws ExecException {
        if (inputStream == null)
            return null;
        BufferedReader in = null;
        ArrayList list = new ArrayList();
        String str;
        try {
            in = new BufferedReader(new InputStreamReader(inputStream));
            while ((str = in.readLine()) != null)
                list.add(str);
            if (list.size() < 1)
                return null;
            return (String[]) list.toArray(new String[list.size()]);

        }
        catch (Exception e) {
            throw new ExecException(e.getMessage());
        }
        finally {
            try {
                in.close();
            }
            catch (Throwable t) {
            }
        }
    }

    private OutputStream redirectProcessOutput(Process subProcess) throws ExecException {
        OutputStream out = null;
        try {
            InputStream in = subProcess.getInputStream();
            // Redirect stderr for verbose mode
            if (mVerboseMode) {
                // send output to stderr
                out = System.err;
            }
            else {
                // send to temp file
                out = new FileOutputStream(mOutFile);
            }

            new FlusherThread(in, out).start();
        }
        catch (Exception e) {
            throw new ExecException(e.getMessage());
        }
        return out;
    }

    private OutputStream redirectProcessError(Process subProcess) throws ExecException {
        OutputStream out = null;
        try {
            InputStream in = subProcess.getErrorStream();
            // Redirect stderr for verbose mode
            if (mVerboseMode) {
                // send output to stderr
                out = System.err;
            }
            else {
                // send to temp file
                out = new FileOutputStream(mErrFile);
            }
            new FlusherThread(in, out).start();
        }
        catch (Exception e) {
            throw new ExecException(e.getMessage());
        }
        return out;
    }

    public void setVerbose(boolean verbose) {
        mVerboseMode = verbose;
    }

    private void sleep(long millis) {
        try {
            Thread.sleep(millis);
        }
        catch (InterruptedException ie) {
            //ignore exception
        }
    }

    /**
     * Returns the contents of a file as a String. It never returns a null. If
     * the file is empty, an empty string is returned.
     *
     * @param file the file to read
     */
    protected String getFileBuffer(File file) {
        final StringBuffer sb = new StringBuffer();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
                sb.append(NEWLINE);
            }
        }
        catch (Exception e) {
            //squelch the exception
        }
        finally {
            try {
                reader.close();
            }
            catch (Exception e) {
            }
        }
        return (sb.toString());
    }

    protected String getLatestOutput(final File f) {
        return (new RAFileReader(f).readLastBytesAsString());
    }

    public void retainBuffers() {
        if (this.retainExecutionLogs) {
            this.lastExecutionErrorString = this.getLatestOutput(this.mErrFile);
            this.lastExecutionOutputString = this.getLatestOutput(this.mOutFile);
        }
    }

    private boolean debug() {
        final String td = System.getProperty("java.io.tmpdir");
        final String n = "as_debug_process_executor"; // a debug hook
        final File f = new File(td, n);
        return (f.exists());
    }

    private String a2s(String[] a) {
        final StringBuffer s = new StringBuffer();
        if (a != null) {
            for (int i = 0; i < a.length; i++) {
                s.append(a[i]);
                s.append(" ");
            }
        }
        return (s.toString());
    }

    /*
     * bnevins, April 2012
     * I added this method to solve a FindBugs low-level issue about ignoring the
     * return value.
     */
    private static void delete(File f) {
        if(f != null && !f.delete()) {
            f.deleteOnExit();
        }
    }

    private static class RAFileReader {
        final File file;
        final static int LAST_BYTES = 16384;
        final static String RMODE = "r"; //read

        RAFileReader(final File file) {
            this.file = file;
        }

        String readLastBytesAsString() {
            final int n = getNumberOfBytes(LAST_BYTES);
            final StringBuffer sb = new StringBuffer();
            final long ln = file.length(); //if SecurityManager is not present, this is safe.
            if (ln == 0)
                return (sb.toString()); //nothing to read, file may not exist, is protected, is a directory etc.
            assert (n <= ln) : ("Asked to read number of bytes more than size of file");
            final long s = ln - n;
            return (readWithoutCheck(s));
        }

        private String readWithoutCheck(final long seekPos) {
            final StringBuffer sb = new StringBuffer();
            RandomAccessFile rf = null;
            int lines = 0;
            try {
                rf = new RandomAccessFile(file, RMODE);
                rf.seek(seekPos);
                String tmp = rf.readLine();
                while (tmp != null) {
                    lines++;
                    sb.append(tmp);
                    //sb.append(Character.LINE_SEPARATOR);
                    sb.append('\n'); // adding a newline character is going to add one extra byte
                    tmp = rf.readLine();
                }
            }
            catch (Exception e) {
                //e.printStackTrace(); //ignore
            }
            finally {
                try {
                    if (rf != null)
                        rf.close();
                }
                catch (Exception e) {
                }//ignore;
            }
            //System.out.println("ln-seekPos = " + (ln - seekPos) );
            //System.out.println("bytes = " + sb.toString().getBytes().length);
            //System.out.println("lines = " + lines);
            //assert ((ln - seekPos) == (sb.toString().getBytes().length + lines)) : "Wrong number of bytes read";
            return (sb.toString());
        }

        private int getNumberOfBytes(final int max) {
            final long ln = file.length();
            return (max >= ln ? (int) ln : max);
        }
    }

    // used for ProcessManager to watchdog subProcess
    public Process getSubProcess() {
        return mSubProcess;
    }

    public static void main(String args[]) {
        testProcessError();
    }

    /*
     * This method tests the condition of process throwing an error. On Unixlike
     * systems this throws an error in error file. On non-unixlike Systems it
     * will throw IOException for CreateProcess, which is desired
     */
    private static void testProcessError() {
        ProcessExecutor executor = new ProcessExecutor(
                new String[]{"/usr/bin/ls", "-wrongPARAMS123"});
        try {
            executor.execute();
        }
        catch (ExecException ee) {
            System.out.println(ee.getMessage());
        }
    }
}
/**
 * inner class to flush runtime.exec process so it doesn't hang
 */
class FlusherThread extends Thread {
    InputStream mInStream = null;
    OutputStream mOutStream = null;
    public static final int kSize = 1024;

    FlusherThread(InputStream in, OutputStream out) {
        mInStream = in;
        mOutStream = out;
    }

    @Override
    public void run() {
        // check for null stream
        if (mInStream == null)
            return;

        // transfer bytes from input to output stream
        try {
            int byteCnt = 0;
            byte[] buffer = new byte[4096];
            while ((byteCnt = mInStream.read(buffer)) != -1) {
                if (mOutStream != null && byteCnt > 0) {
                    mOutStream.write(buffer, 0, byteCnt);
                    mOutStream.flush();
                }
                Thread.yield();
            }
        }
        catch (IOException e) {
            // ignore
        }
        finally {
            try {
                mOutStream.close();
            }
            catch (IOException ioe) {
                // ignore
            }
        }
    }
}
