/*
 * 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.geode.internal;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.zip.GZIPOutputStream;

import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.io.TeePrintStream;
import org.apache.geode.internal.logging.LogService;

/**
 * Used to interact with operating system processes. Use <code>exec</code> to create a new process
 * by executing a command. Use <code>kill</code> to kill a process.
 *
 */
// TODO: In the next major release, we should remove the variables and logic related to the system
// properties used to determine whether output redirection is allowed or not
// (DISABLE_OUTPUT_REDIRECTION_PROPERTY, ENABLE_OUTPUT_REDIRECTION_PROPERTY,
// DISABLE_REDIRECTION_CONFIGURATION_PROPERTY, ENABLE_OUTPUT_REDIRECTION, DISABLE_OUTPUT_REDIRECTION
// and DISABLE_REDIRECTION_CONFIGURATION). GFSH should always use the new redirect-output flag.
public class OSProcess {
  private static final Logger logger = LogService.getLogger();

  /**
   * @deprecated use GFSH redirect-output flag instead.
   */
  @Deprecated
  public static final String DISABLE_OUTPUT_REDIRECTION_PROPERTY =
      DistributionConfig.GEMFIRE_PREFIX + "OSProcess.DISABLE_OUTPUT_REDIRECTION";

  /**
   * @deprecated use GFSH redirect-output flag instead.
   */
  @Deprecated
  public static final String ENABLE_OUTPUT_REDIRECTION_PROPERTY =
      DistributionConfig.GEMFIRE_PREFIX + "OSProcess.ENABLE_OUTPUT_REDIRECTION";

  /**
   * @deprecated use GFSH redirect-output flag instead.
   */
  @Deprecated
  public static final String DISABLE_REDIRECTION_CONFIGURATION_PROPERTY =
      DistributionConfig.GEMFIRE_PREFIX + "OSProcess.DISABLE_REDIRECTION_CONFIGURATION";

  /**
   * @deprecated use GFSH redirect-output flag instead.
   */
  @Deprecated
  private static final boolean ENABLE_OUTPUT_REDIRECTION =
      Boolean.getBoolean(ENABLE_OUTPUT_REDIRECTION_PROPERTY);

  /**
   * @deprecated use GFSH redirect-output flag instead.
   */
  @Deprecated
  private static final boolean DISABLE_OUTPUT_REDIRECTION =
      Boolean.getBoolean(DISABLE_OUTPUT_REDIRECTION_PROPERTY);

  /**
   * @deprecated use GFSH redirect-output flag instead.
   */
  @Deprecated
  private static final boolean DISABLE_REDIRECTION_CONFIGURATION =
      Boolean.getBoolean(DISABLE_REDIRECTION_CONFIGURATION_PROPERTY);

  /**
   * Starts a background command writing its stdout and stderr to the specified log file.
   *
   * @param cmdarray An array of strings that specify the command to run. The first element must be
   *        the executable. Each additional command line argument should have its own entry in the
   *        array.
   * @param workdir the current directory of the created process
   * @param logfile the file the created process will write stdout and stderr to.
   * @param inheritLogfile can be set to false if the child process is willing to create its own log
   *        file. Setting to false can help on Windows because it keeps the child process from
   *        inheriting handles from the parent.
   * @return the process id of the created process; -1 on failure
   * @exception IOException if a child process could not be created.
   */
  private static native int bgexecInternal(String[] cmdarray, String workdir, String logfile,
      boolean inheritLogfile) throws IOException;

  /**
   * Starts execution of the specified command and arguments in a separate detached process in the
   * specified working directory writing output to the specified log file.
   * <p>
   * If there is a security manager, its <code>checkExec</code> method is called with the first
   * component of the array <code>cmdarray</code> as its argument. This may result in a security
   * exception.
   * <p>
   * Given an array of strings <code>cmdarray</code>, representing the tokens of a command line,
   * this method creates a new process in which to execute the specified command.
   *
   * @param cmdarray array containing the command to call and its arguments.
   * @param workdir the current directory of the created process; null causes working directory to
   *        default to the current directory.
   * @param logfile the file the created process will write stdout and stderr to; null causes a
   *        default log file name to be used.
   * @param inheritLogfile can be set to false if the child process is willing to create its own log
   *        file. Setting to false can help on Windows because it keeps the child process from
   *        inheriting handles from the parent.
   * @param env any extra environment variables as key,value map; these will be in addition to those
   *        inherited from the parent process and will overwrite same keys
   * @return the process id of the created process; -1 on failure
   * @exception SecurityException if the current thread cannot create a subprocess.
   * @see java.lang.SecurityException
   * @see java.lang.SecurityManager#checkExec(java.lang.String)
   */
  public static int bgexec(String cmdarray[], File workdir, File logfile, boolean inheritLogfile,
      Map<String, String> env) throws IOException {
    String commandShell =
        System.getProperty(DistributionConfig.GEMFIRE_PREFIX + "commandShell", "bash");
    if (cmdarray.length == 0) {
      throw new java.lang.IndexOutOfBoundsException();
    }
    boolean isWindows = false;
    String os = System.getProperty("os.name");
    if (os != null) {
      if (os.indexOf("Windows") != -1) {
        isWindows = true;
      }
    }
    for (int i = 0; i < cmdarray.length; i++) {
      if (cmdarray[i] == null) {
        throw new NullPointerException();
      }
      if (isWindows) {
        if (i == 0) {
          // do the following before quotes get added.
          File cmd = new File(cmdarray[0]);
          if (!cmd.exists()) {
            cmd = new File(cmdarray[0] + ".exe");
            if (cmd.exists()) {
              cmdarray[0] = cmd.getPath();
            }
          }
        }
        String s = cmdarray[i];
        if (i != 0) {
          if (s.length() == 0) {
            cmdarray[i] = "\"\""; // fix for bug 22207
          } else if ((s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0)) {
            String unquotedS = s;
            if (s.indexOf('\"') != -1) {
              // Note that Windows provides no way to embed a double
              // quote in a double quoted string so need to remove
              // any internal quotes and let the outer quotes
              // preserve the whitespace.
              StringBuffer b = new StringBuffer(s);
              int quoteIdx = s.lastIndexOf('\"');
              while (quoteIdx != -1) {
                b.deleteCharAt(quoteIdx);
                quoteIdx = s.lastIndexOf('\"', quoteIdx - 1);
              }
              unquotedS = b.toString();
            }
            // It has whitespace and its not quoted
            cmdarray[i] = '"' + unquotedS + '"';
          }
        }
      }
    }
    File cmd = new File(cmdarray[0]);
    if (!cmd.exists()) {
      throw new IOException(String.format("the executable %s does not exist",
          cmd.getPath()));
    }
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
      security.checkExec(cmdarray[0]);
    }
    if (workdir != null && !workdir.isDirectory()) {
      String curDir = new File("").getAbsolutePath();
      System.out.println(
          String.format("WARNING: %s is not a directory. Defaulting to current directory %s.",
              new Object[] {workdir, curDir}));
      workdir = null;
    }
    if (workdir == null) {
      workdir = new File("").getAbsoluteFile();
    }
    if (logfile == null) {
      logfile = File.createTempFile("bgexec", ".log", workdir);
    }
    if (!logfile.isAbsolute()) {
      // put it in the working directory
      logfile = new File(workdir, logfile.getPath());
    }
    // fix for bug 24575
    if (logfile.exists()) {
      // it already exists so make sure its a file and can be written
      if (!logfile.isFile()) {
        throw new IOException(String.format("The log file %s was not a normal file.",
            logfile.getPath()));
      }
      if (!logfile.canWrite()) {
        throw new IOException(String.format("Need write access for the log file %s.",
            logfile.getPath()));
      }
    } else {
      try {
        logfile.createNewFile();
      } catch (IOException io) {
        throw new IOException(String.format("Could not create log file %s because: %s.",
            new Object[] {logfile.getPath(), io.getMessage()}));
      }
    }
    String trace = System.getProperty("org.apache.geode.internal.OSProcess.trace");
    if (trace != null && trace.length() > 0) {
      for (int i = 0; i < cmdarray.length; i++) {
        System.out.println("cmdarray[" + i + "] = " + cmdarray[i]);
      }
      System.out.println("workdir=" + workdir.getPath());
      System.out.println("logfile=" + logfile.getPath());
    }
    int result = 0;

    StringBuffer sb = new StringBuffer();
    Vector cmdVec = new Vector();
    // Add shell code to spawn a process silently
    if (isWindows) {
      cmdVec.add("cmd.exe");
      cmdVec.add("/c");
      sb.append("start /b \"\" ");
    } else {
      // to address issue with users that don't have bash shell installed
      if (commandShell.equals("bash")) {
        cmdVec.add("bash");
        cmdVec.add("--norc");
        cmdVec.add("-c");
      } else {
        cmdVec.add(commandShell);
      }
    }
    // Add the actual command
    for (int i = 0; i < cmdarray.length; i++) {
      if (i != 0)
        sb.append(" ");
      if (cmdarray[i].length() != 0 && cmdarray[i].charAt(0) == '\"') {
        // The token has already been quoted, see bug 40835
        sb.append(cmdarray[i]);
      } else {
        sb.append("\"");
        sb.append(cmdarray[i]);
        sb.append("\"");
      }
    }
    // Add the IO redirction code, this prevents hangs and IO blocking
    sb.append(" >> ");
    sb.append(logfile.getPath());
    sb.append(" 2>&1");
    if (isWindows) {
      sb.append(" <NUL");
    } else {
      sb.append(" </dev/null &");
    }
    cmdVec.add(sb.toString());

    String[] cmdStrings = (String[]) cmdVec.toArray(new String[0]);
    if (trace != null && trace.length() > 0) {
      for (int i = 0; i < cmdStrings.length; i++) {
        System.out.println("cmdStrings[" + i + "] = " + cmdStrings[i]);
      }
      System.out.println("workdir=" + workdir.getPath());
      System.out.println("logfile=" + logfile.getPath());
    }
    final ProcessBuilder procBuilder = new ProcessBuilder(cmdStrings);
    if (env != null && env.size() > 0) {
      // adjust the environment variables inheriting from parent
      procBuilder.environment().putAll(env);
    }
    procBuilder.directory(workdir);
    final Process process = procBuilder.start();
    try {
      process.getInputStream().close();
    } catch (IOException ignore) {
    }
    try {
      process.getOutputStream().close();
    } catch (IOException ignore) {
    }
    try {
      process.getErrorStream().close();
    } catch (IOException ignore) {
    }
    try {
      // short count = 1000;
      boolean processIsStillRunning = true;
      while (processIsStillRunning) {
        Thread.sleep(10);
        try {
          process.exitValue();
          processIsStillRunning = false;
        } catch (IllegalThreadStateException itse) {
          // Ignore this, we are polling the exitStatus
          // instead of using the blocking Process#waitFor()
        }
      }
    } catch (InterruptedException ie) {
      Thread.currentThread().interrupt();
    }

    return result; // Always 0 for pureJava
  }

  /**
   * Checks to make sure that we are operating on a valid process id. Sending signals to processes
   * with <code>pid</code> 0 or -1 can have unintended consequences.
   *
   * @throws IllegalArgumentException If <code>pid</code> is not positive
   *
   * @since GemFire 4.0
   */
  private static void checkPid(int pid) {
    if (pid <= 0) {
      throw new IllegalArgumentException(
          String.format("Should not send a signal to pid %s",
              Integer.valueOf(pid)));
    }
  }

  /**
   * Ask a process to shut itself down. The process may catch and ignore this shutdown request.
   *
   * @param pid the id of the process to shutdown
   * @return true if the request was sent to the process; false if the process does not exist or can
   *         not be asked to shutdown.
   */
  public static boolean shutdown(int pid) {
    throw new RuntimeException(
        "shutdown not allowed in pure java mode");
  }

  private static native boolean _shutdown(int pid);

  /**
   * Terminate a process without warning and without a chance of an orderly shutdown. This method
   * should only be used as a last resort. The {@link #shutdown(int)} method should be used in most
   * cases.
   *
   * @param pid the id of the process to kill
   * @return true if the process was killed; false if it does not exist or can not be killed.
   */
  public static boolean kill(int pid) {
    throw new RuntimeException(
        "kill not allowed in pure java mode");
  }

  private static native boolean _kill(int pid);

  /**
   * Tells a process to print its stacks to its standard output
   *
   * @param pid the id of the process that will print its stacks, or zero for the current process
   * @return true if the process was told; false if it does not exist or can not be told.
   */
  public static boolean printStacks(int pid) {
    return printStacks(pid, false);
  }

  /**
   * Tells a process to print its stacks to its standard output or the given log writer
   *
   * @param pid the id of the process that will print its stacks, or zero for the current process
   * @param useNative if true we attempt to use native code, which goes to stdout
   * @return true if the process was told; false if it does not exist or can not be told.
   */
  public static boolean printStacks(int pid, boolean useNative) {
    if (!useNative) {
      if (pid > 0 && pid != myPid[0]) {
        return false;
      }
      CharArrayWriter cw = new CharArrayWriter(50000);
      PrintWriter sb = new PrintWriter(cw, true);
      sb.append("\n******** full thread dump ********\n");
      ThreadMXBean bean = ManagementFactory.getThreadMXBean();
      long[] threadIds = bean.getAllThreadIds();
      ThreadInfo[] infos = bean.getThreadInfo(threadIds, true, true);
      long thisThread = Thread.currentThread().getId();
      for (int i = 0; i < infos.length; i++) {
        if (i != thisThread && infos[i] != null) {
          formatThreadInfo(infos[i], sb);
        }
      }
      sb.flush();
      logger.warn(cw.toString());
      return true;
    } else {
      if (pid < 0)
        checkPid(pid);
      return _printStacks(pid);
    }
  }

  /** dumps this vm's stacks and returns gzipped result */
  public static byte[] zipStacks() throws IOException {
    ThreadMXBean bean = ManagementFactory.getThreadMXBean();
    long[] threadIds = bean.getAllThreadIds();
    ThreadInfo[] infos = bean.getThreadInfo(threadIds, true, true);
    long thisThread = Thread.currentThread().getId();
    ByteArrayOutputStream baos = new ByteArrayOutputStream(10000);
    GZIPOutputStream zipOut = new GZIPOutputStream(baos, 10000);
    PrintWriter pw = new PrintWriter(zipOut, true);
    for (int i = 0; i < infos.length; i++) {
      if (i != thisThread && infos[i] != null) {
        formatThreadInfo(infos[i], pw);
      }
    }
    pw.flush();
    zipOut.close();
    byte[] result = baos.toByteArray();
    return result;
  }

  private static native boolean _printStacks(int pid);

  static final int MAX_STACK_FRAMES = 75;

  private static void formatThreadInfo(ThreadInfo t, PrintWriter pw) {
    // this is largely copied from the JDK's ThreadInfo.java, but it limits the
    // stacks to 8 elements
    pw.append("\"" + t.getThreadName() + "\"" + " tid=0x" + Long.toHexString(t.getThreadId()));
    // this is in the stack trace elements so we don't need to add it
    // if (t.getLockName() != null) {
    // pw.append(" ");
    // pw.append(StringUtils.toLowerCase(t.getThreadState().toString()));
    // pw.append(" on " + t.getLockName());
    // }
    // priority is not known
    // daemon status is not known
    if (t.isSuspended()) {
      pw.append(" (suspended)");
    }
    if (t.isInNative()) {
      pw.append(" (in native)");
    }
    if (t.getLockOwnerName() != null) {
      pw.append(" owned by \"" + t.getLockOwnerName() + "\" tid=0x"
          + Long.toHexString(t.getLockOwnerId()));
    }
    pw.append('\n');
    pw.append("    java.lang.Thread.State: " + t.getThreadState() + "\n");
    int i = 0;
    StackTraceElement[] stackTrace = t.getStackTrace();
    for (; i < stackTrace.length && i < MAX_STACK_FRAMES; i++) {
      StackTraceElement ste = stackTrace[i];
      pw.append("\tat " + ste.toString());
      pw.append('\n');
      if (i == 0 && t.getLockInfo() != null) {
        Thread.State ts = t.getThreadState();
        switch (ts) {
          case BLOCKED:
            pw.append("\t-  blocked on " + t.getLockInfo());
            pw.append('\n');
            break;
          case WAITING:
            pw.append("\t-  waiting on " + t.getLockInfo());
            pw.append('\n');
            break;
          case TIMED_WAITING:
            pw.append("\t-  waiting on " + t.getLockInfo());
            pw.append('\n');
            break;
          default:
        }
      }

      for (MonitorInfo mi : t.getLockedMonitors()) {
        if (mi.getLockedStackDepth() == i) {
          pw.append("\t-  locked " + mi);
          pw.append('\n');
        }
      }
    }
    if (i < stackTrace.length) {
      pw.append("\t...");
      pw.append('\n');
    }

    LockInfo[] locks = t.getLockedSynchronizers();
    if (locks.length > 0) {
      pw.append("\n\tNumber of locked synchronizers = " + locks.length);
      pw.append('\n');
      for (LockInfo li : locks) {
        pw.append("\t- " + li);
        pw.append('\n');
      }
    }
    pw.append('\n');
  }

  /**
   * Find out if a process exists.
   *
   * @param pid the id of the process to check for
   * @return true if the process exists; false if it does not.
   */
  public static boolean exists(int pid) {
    throw new RuntimeException(
        "exists not allowed in pure java mode");
  }

  private static native boolean nativeExists(int pid);

  // Private stuff
  /**
   * Waits for a child process to die and reaps it.
   */
  private static native void waitForPid(int pid);

  /**
   * Waits until the identified process exits. If the process does not exist then returns
   * immediately.
   */
  public static void waitForPidToExit(int pid) {
    throw new RuntimeException(
        "waitForPidToExit not allowed in pure java mode");
  }

  /**
   * Sets the current directory of this process.
   *
   * @return true if current directory was set; false if not.
   */
  public static boolean setCurrentDirectory(File curDir) {
    throw new RuntimeException(
        "setCurrentDirectory not allowed in pure java mode");
  }

  /**
   * Returns true on success. Returns false and current directory is unchanged on failure.
   */
  private static native boolean jniSetCurDir(String dir);

  /**
   * Reaps a child process if it has died. Does not wait for the child.
   *
   * @param pid the id of the process to reap
   * @return true if it was reaped or lost (someone else reaped it); false if the child still
   *         exists. HACK: If pid is -1 then returns true if this platform needs reaping.
   */
  protected static native boolean reapPid(int pid);

  @MakeNotStatic
  private static Thread reaperThread;
  @MakeNotStatic
  protected static Set pids = null;

  // myPid caches result of getProcessId . To provide a stable processId
  // on Linux, where processId may differ per thread, we cache the
  // processId of the reaper thread .
  @MakeNotStatic
  static final int[] myPid = new int[1]; // cache of my processId

  @MakeNotStatic
  static boolean reaperStarted = false; // true if cache is valid

  /**
   * On Linux, getProcessId returns the processId of the calling thread
   */
  static native int getProcessId();

  static {
    // just initialize the pid cache
    synchronized (myPid) {
      int pid = 0;
      // Windows checks have been disabled as the ManagementFactory hack
      // to find the PID has been seen to work on Windows 7. Add checks
      // for more specific versions of Windows if this fails on them
      // if(! System.getProperty("os.name", "").startsWith("Windows")) {
      String name = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
      int idx = name.indexOf('@');
      try {
        pid = Integer.parseInt(name.substring(0, idx));
      } catch (NumberFormatException nfe) {
        // something changed in the RuntimeMXBean name
      }
      // }
      myPid[0] = pid;
      reaperStarted = true;
    }
  }

  /**
   * Get the vm's process id. On Linux, this returns the processId of the reaper thread.
   *
   * @return the vm's process id.
   */
  public static int getId() {
    boolean done = false;
    int result = -1;
    for (;;) {
      synchronized (myPid) {
        done = reaperStarted;
        result = myPid[0];
      }
      if (done)
        break;

      // wait for reaper thread to initialize myPid
      try {
        Thread.sleep(100);
      } catch (InterruptedException ignore) {
        Thread.currentThread().interrupt();
      }
    }
    return result;
  }

  public static PrintStream redirectOutput(File newOutput) throws IOException {
    return redirectOutput(newOutput, true);
  }

  public static PrintStream redirectOutput(File newOutput, boolean setOut) throws IOException {
    FileOutputStream newFileStream = null;
    try {
      newFileStream = new FileOutputStream(newOutput, true);
    } catch (FileNotFoundException e) {
      throw new IOException("File not found: " + newOutput, e);
    }
    final PrintStream newPrintStream =
        new PrintStream(new BufferedOutputStream(newFileStream, 128), true);
    if (((DISABLE_REDIRECTION_CONFIGURATION)
        || (ENABLE_OUTPUT_REDIRECTION && !DISABLE_OUTPUT_REDIRECTION)) && setOut) {
      System.setOut(newPrintStream);
      if (System.err instanceof TeePrintStream) {
        ((TeePrintStream) System.err).getTeeOutputStream()
            .setBranchOutputStream(new BufferedOutputStream(newFileStream, 128));
      } else {
        System.setErr(newPrintStream);
      }
    }
    return newPrintStream;
  }

  private static native void redirectCOutput(String file);

  /**
   * Registers a signal handler for SIGQUIT on UNIX platforms.
   */
  private static native void registerSigQuitHandler();
}
