package org.sonar.application.process;
import java.io.Closeable;
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
public interface JavaProcessLauncher extends Closeable {
- class SystemProcessBuilder {
- private final ProcessBuilder builder = new ProcessBuilder();
-
- /**
- * @see ProcessBuilder#command()
- */
- public List<String> command() {
- return builder.command();
- }
-
- /**
- * @see ProcessBuilder#command(List)
- */
- public SystemProcessBuilder command(List<String> commands) {
- builder.command(commands);
- return this;
- }
-
- /**
- * @see ProcessBuilder#directory(File)
- */
- public SystemProcessBuilder directory(File dir) {
- builder.directory(dir);
- return this;
- }
-
- /**
- * @see ProcessBuilder#environment()
- */
- public Map<String, String> environment() {
- return builder.environment();
- }
-
- /**
- * @see ProcessBuilder#redirectErrorStream(boolean)
- */
- public SystemProcessBuilder redirectErrorStream(boolean b) {
- builder.redirectErrorStream(b);
- return this;
- }
-
- /**
- * @see ProcessBuilder#start()
- */
- public Process start() throws IOException {
- return builder.start();
- }
- }
-
@Override
void close();
import java.io.File;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
import java.util.function.Supplier;
import org.slf4j.Logger;
private final File tempDir;
private final AllProcessesCommands allProcessesCommands;
- private final Supplier<SystemProcessBuilder> processBuilderSupplier;
+ private final Supplier<ProcessBuilder> processBuilderSupplier;
public JavaProcessLauncherImpl(File tempDir) {
- this(tempDir, new AllProcessesCommands(tempDir), SystemProcessBuilder::new);
+ this(tempDir, new AllProcessesCommands(tempDir), JavaLangProcessBuilder::new);
}
- JavaProcessLauncherImpl(File tempDir, AllProcessesCommands allProcessesCommands, Supplier<SystemProcessBuilder> processBuilderSupplier) {
+ JavaProcessLauncherImpl(File tempDir, AllProcessesCommands allProcessesCommands, Supplier<ProcessBuilder> processBuilderSupplier) {
this.tempDir = tempDir;
this.allProcessesCommands = allProcessesCommands;
this.processBuilderSupplier = processBuilderSupplier;
try {
commands = allProcessesCommands.createAfterClean(javaCommand.getProcessId().getIpcIndex());
- SystemProcessBuilder processBuilder = create(javaCommand);
+ ProcessBuilder processBuilder = create(javaCommand);
LOG.info("Launch process[{}]: {}", javaCommand.getProcessId().getKey(), String.join(" ", processBuilder.command()));
process = processBuilder.start();
return new ProcessMonitorImpl(process, commands);
}
}
- private SystemProcessBuilder create(JavaCommand javaCommand) {
+ private ProcessBuilder create(JavaCommand javaCommand) {
List<String> commands = new ArrayList<>();
commands.add(buildJavaPath());
commands.addAll(javaCommand.getJavaOptions());
commands.add(javaCommand.getClassName());
commands.add(buildPropertiesFile(javaCommand).getAbsolutePath());
- SystemProcessBuilder processBuilder = processBuilderSupplier.get();
+ ProcessBuilder processBuilder = processBuilderSupplier.get();
processBuilder.command(commands);
processBuilder.directory(javaCommand.getWorkDir());
processBuilder.environment().putAll(javaCommand.getEnvVariables());
throw new IllegalStateException("Cannot write temporary settings to " + propertiesFile, e);
}
}
+
+ /**
+ * An interface of the methods of {@link java.lang.ProcessBuilder} that we use in {@link JavaProcessLauncherImpl}.
+ * <p>Allows testing creating processes without actualling creating them at OS level</p>
+ */
+ public interface ProcessBuilder {
+ List<String> command();
+
+ ProcessBuilder command(List<String> commands);
+
+ ProcessBuilder directory(File dir);
+
+ Map<String, String> environment();
+
+ ProcessBuilder redirectErrorStream(boolean b);
+
+ Process start() throws IOException;
+ }
+
+ private static class JavaLangProcessBuilder implements ProcessBuilder {
+ private final java.lang.ProcessBuilder builder = new java.lang.ProcessBuilder();
+
+ /**
+ * @see java.lang.ProcessBuilder#command()
+ */
+ @Override
+ public List<String> command() {
+ return builder.command();
+ }
+
+ /**
+ * @see java.lang.ProcessBuilder#command(List)
+ */
+ @Override
+ public ProcessBuilder command(List<String> commands) {
+ builder.command(commands);
+ return this;
+ }
+
+ /**
+ * @see java.lang.ProcessBuilder#directory(File)
+ */
+ @Override
+ public ProcessBuilder directory(File dir) {
+ builder.directory(dir);
+ return this;
+ }
+
+ /**
+ * @see java.lang.ProcessBuilder#environment()
+ */
+ @Override
+ public Map<String, String> environment() {
+ return builder.environment();
+ }
+
+ /**
+ * @see java.lang.ProcessBuilder#redirectErrorStream(boolean)
+ */
+ @Override
+ public ProcessBuilder redirectErrorStream(boolean b) {
+ builder.redirectErrorStream(b);
+ return this;
+ }
+
+ /**
+ * @see java.lang.ProcessBuilder#start()
+ */
+ @Override
+ public Process start() throws IOException {
+ return builder.start();
+ }
+ }
}