All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cedarsoftware.util.Executor Maven / Gradle / Ivy

The newest version!
package com.cedarsoftware.util;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.cedarsoftware.util.LoggingConfig;

/**
 * A utility class for executing system commands and capturing their output.
 * 

* This class provides a convenient wrapper around Java's {@link Runtime#exec(String)} methods, * capturing both standard output and standard error streams. It handles stream management * and process cleanup automatically. *

* *

Features:

*
    *
  • Executes system commands with various parameter combinations
  • *
  • Captures stdout and stderr output
  • *
  • Supports environment variables
  • *
  • Supports working directory specification
  • *
  • Non-blocking output handling
  • *
* *

Example Usage:

*
{@code
 * Executor exec = new Executor();
 * int exitCode = exec.exec("ls -l");
 * String output = exec.getOut();      // Get stdout
 * String errors = exec.getError();    // Get stderr
 * }
* * @author John DeRegnaucourt ([email protected]) *
* Copyright (c) Cedar Software LLC *

* Licensed 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 *

* License *

* 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. * *

Thread Safety: Instances of this class are not thread * safe. Create a new {@code Executor} per command execution or synchronize * externally if sharing across threads.

*/ public class Executor { private String _error; private String _out; private static final long DEFAULT_TIMEOUT_SECONDS = 60L; private static final Logger LOG = Logger.getLogger(Executor.class.getName()); static { LoggingConfig.init(); } /** * Execute the supplied command line using the platform shell. * * @param command command to execute * @return result of the execution */ public ExecutionResult execute(String command) { return execute(command, null, null); } /** * Execute the specified command array. * * @param cmdarray command and arguments * @return result of the execution */ public ExecutionResult execute(String[] cmdarray) { return execute(cmdarray, null, null); } /** * Execute a command with environment variables. * * @param command command line to run * @param envp environment variables, may be {@code null} * @return result of the execution */ public ExecutionResult execute(String command, String[] envp) { return execute(command, envp, null); } /** * Execute a command array with environment variables. * * @param cmdarray command and arguments * @param envp environment variables, may be {@code null} * @return result of the execution */ public ExecutionResult execute(String[] cmdarray, String[] envp) { return execute(cmdarray, envp, null); } /** * Execute a command with optional environment and working directory. * * @param command command line to run * @param envp environment variables or {@code null} * @param dir working directory, may be {@code null} * @return result of the execution */ public ExecutionResult execute(String command, String[] envp, File dir) { try { Process proc = startProcess(command, envp, dir); return runIt(proc); } catch (InterruptedException e) { LOG.log(Level.SEVERE, "Error occurred executing command: " + command, e); return new ExecutionResult(-1, "", e.getMessage()); } } /** * Execute a command array with optional environment and working directory. * * @param cmdarray command and arguments * @param envp environment variables or {@code null} * @param dir working directory, may be {@code null} * @return result of the execution */ public ExecutionResult execute(String[] cmdarray, String[] envp, File dir) { try { Process proc = startProcess(cmdarray, envp, dir); return runIt(proc); } catch ( InterruptedException e) { LOG.log(Level.SEVERE, "Error occurred executing command: " + cmdArrayToString(cmdarray), e); return new ExecutionResult(-1, "", e.getMessage()); } } private Process startProcess(String command, String[] envp, File dir) { boolean windows = System.getProperty("os.name").toLowerCase().contains("windows"); String[] shellCmd = windows ? new String[]{"cmd.exe", "/c", command} : new String[]{"sh", "-c", command}; return startProcess(shellCmd, envp, dir); } private Process startProcess(String[] cmdarray, String[] envp, File dir) { ProcessBuilder pb = new ProcessBuilder(cmdarray); if (envp != null) { for (String env : envp) { int idx = env.indexOf('='); if (idx > 0) { pb.environment().put(env.substring(0, idx), env.substring(idx + 1)); } } } if (dir != null) { pb.directory(dir); } try { return pb.start(); } catch (IOException e) { ExceptionUtilities.uncheckedThrow(e); return null; // ignored } } /** * Executes a command using the system's runtime environment. * * @param command the command to execute * @return the exit value of the process (0 typically indicates success), * or -1 if an error occurred starting the process */ public int exec(String command) { ExecutionResult result = execute(command); return result.getExitCode(); } /** * Executes a command array using the system's runtime environment. *

* This version allows commands with arguments to be specified as separate array elements, * avoiding issues with argument quoting and escaping. * * @param cmdarray array containing the command and its arguments * @return the exit value of the process (0 typically indicates success), * or -1 if an error occurred starting the process */ public int exec(String[] cmdarray) { ExecutionResult result = execute(cmdarray); return result.getExitCode(); } /** * Executes a command with specified environment variables. * * @param command the command to execute * @param envp array of strings, each element of which has environment variable settings in format name=value, * or null if the subprocess should inherit the environment of the current process * @return the exit value of the process (0 typically indicates success), * or -1 if an error occurred starting the process */ public int exec(String command, String[] envp) { ExecutionResult result = execute(command, envp); return result.getExitCode(); } /** * Executes a command array with specified environment variables. * * @param cmdarray array containing the command and its arguments * @param envp array of strings, each element of which has environment variable settings in format name=value, * or null if the subprocess should inherit the environment of the current process * @return the exit value of the process (0 typically indicates success), * or -1 if an error occurred starting the process */ public int exec(String[] cmdarray, String[] envp) { ExecutionResult result = execute(cmdarray, envp); return result.getExitCode(); } /** * Executes a command with specified environment variables and working directory. * * @param command the command to execute * @param envp array of strings, each element of which has environment variable settings in format name=value, * or null if the subprocess should inherit the environment of the current process * @param dir the working directory of the subprocess, or null if the subprocess should inherit * the working directory of the current process * @return the exit value of the process (0 typically indicates success), * or -1 if an error occurred starting the process */ public int exec(String command, String[] envp, File dir) { ExecutionResult result = execute(command, envp, dir); return result.getExitCode(); } /** * Executes a command array with specified environment variables and working directory. * * @param cmdarray array containing the command and its arguments * @param envp array of strings, each element of which has environment variable settings in format name=value, * or null if the subprocess should inherit the environment of the current process * @param dir the working directory of the subprocess, or null if the subprocess should inherit * the working directory of the current process * @return the exit value of the process (0 typically indicates success), * or -1 if an error occurred starting the process */ public int exec(String[] cmdarray, String[] envp, File dir) { ExecutionResult result = execute(cmdarray, envp, dir); return result.getExitCode(); } private ExecutionResult runIt(Process proc) throws InterruptedException { StreamGobbler errors = new StreamGobbler(proc.getErrorStream()); Thread errorGobbler = new Thread(errors); StreamGobbler out = new StreamGobbler(proc.getInputStream()); Thread outputGobbler = new Thread(out); errorGobbler.start(); outputGobbler.start(); boolean finished = proc.waitFor(DEFAULT_TIMEOUT_SECONDS, TimeUnit.SECONDS); if (!finished) { proc.destroyForcibly(); } errorGobbler.join(); outputGobbler.join(); String err = errors.getResult(); String outStr = out.getResult(); int exitVal = finished ? proc.exitValue() : -1; _error = err; _out = outStr; return new ExecutionResult(exitVal, outStr, err); } /** * Returns the content written to standard error by the last executed command. * * @return the stderr output as a string, or null if no command has been executed */ public String getError() { return _error; } /** * Returns the content written to standard output by the last executed command. * * @return the stdout output as a string, or null if no command has been executed */ public String getOut() { return _out; } private String cmdArrayToString(String[] cmdArray) { return String.join(" ", cmdArray); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy