
com.crabshue.commons.process.Processor Maven / Gradle / Ivy
package com.crabshue.commons.process;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import com.crabshue.commons.file.FileSystemUtils;
import com.crabshue.commons.process.exceptions.ProcessErrorType;
import com.crabshue.commons.process.exceptions.ProcessExecutionException;
import com.crabshue.commons.process.helpers.ProcessHelper;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Processor {
private static final String STDOUT_FILENAME = "stdout.log";
private static final String STDERR_FILENAME = "stderr.log";
private Process process;
/**
* Execute a command in given working directory.
*
* @param workingDir The working directory from which to execute the command.
* @param command The command to execute.
* @return The exit value returned by the command.
*/
public int execute(@NonNull File workingDir, @NonNull String command) {
return execute(workingDir, ProcessHelper.splitCommand(command));
}
/**
* Execute a command in given working directory.
*
* NOTE: stdout.log and stderr.log will be written in the provided workingDir
* unless they are empty in which case they get removed.
*
* @param workingDir The working directory from which to execute the command.
* @param command The command to execute in form of split parameters.
* @return The exit value returned by the command.
*/
public int execute(@NonNull File workingDir, @NonNull String... command) {
if (this.process != null) {
logger.error("Process already executed");
throw new ProcessExecutionException(
ProcessErrorType.PROCESS_ALREADY_EXECUTED,
"Process already executed. Only One process can be started per instance."
);
}
FileSystemUtils.provideFolder(workingDir);
File stdout = new File(workingDir, STDOUT_FILENAME);
File stderr = new File(workingDir, STDERR_FILENAME);
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(workingDir);
processBuilder.redirectOutput(stdout);
processBuilder.redirectError(stderr);
int exitValue;
try {
this.process = processBuilder.start();
this.process.waitFor();
exitValue = this.process.exitValue();
logger.info("Process {} executed with exit code [{}]", command, exitValue);
} catch (IOException | InterruptedException exception) {
logger.error("Error executing command: {}", processBuilder.command(), exception);
throw new ProcessExecutionException(
ProcessErrorType.EXECUTION_ERROR,
"Error executing command: " + processBuilder.command(),
exception
);
} finally {
cleanupEmptyFile(stdout);
cleanupEmptyFile(stderr);
}
return exitValue;
}
/**
* Delete a file if empty.
*
* @param file The file to check and eventually delete.
*/
private void cleanupEmptyFile(@NonNull File file) {
if (file.exists() && file.length() == 0) {
FileUtils.deleteQuietly(file);
}
}
}