Skip to content

Commit

Permalink
šŸµšŸ¶šŸ»
Browse files Browse the repository at this point in the history
  • Loading branch information
alexsuter committed Jul 29, 2024
1 parent 5a1fe3e commit 5b3559b
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 76 deletions.
97 changes: 51 additions & 46 deletions src/main/java/ch/ivyteam/ivy/maven/engine/EngineControl.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,18 @@
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.ExecuteResultHandler;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.Executor;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.exec.ShutdownHookProcessDestroyer;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;

Expand All @@ -53,6 +50,7 @@
* Sends commands like start, stop to the ivy Engine
*/
public class EngineControl {

public static interface Property {
String TEST_ENGINE_URL = "test.engine.url";
String TEST_ENGINE_LOG = "test.engine.log";
Expand All @@ -76,60 +74,65 @@ public EngineControl(EngineMojoContext context) {
this.context = context;
}

public Executor start() throws Exception {
CommandLine startCmd = toEngineCommand(Command.start);
public Process start() throws Exception {
var startCmd = toEngineCommand(Command.start);
context.log.info("Start Axon Ivy Engine in folder: " + context.engineDirectory);

Executor executor = createEngineExecutor();
executor.setStreamHandler(createEngineLogStreamForwarder(logLine -> findStartEngineUrl(logLine)));
var watchdog = ExecuteWatchdog.builder()
.setTimeout(ExecuteWatchdog.INFINITE_TIMEOUT_DURATION)
.get();
executor.setWatchdog(watchdog);
executor.setProcessDestroyer(new ShutdownHookProcessDestroyer());
executor.execute(startCmd, asynchExecutionHandler());
waitForEngineStart(executor);
return executor;
//Executor executor = createEngineExecutor();
//executor.setStreamHandler(createEngineLogStreamForwarder(logLine -> findStartEngineUrl(logLine)));
//var watchdog = ExecuteWatchdog.builder()
// .setTimeout(ExecuteWatchdog.INFINITE_TIMEOUT_DURATION)
// .get();
//executor.setWatchdog(watchdog);
//executor.setProcessDestroyer(new ShutdownHookProcessDestroyer());
//executor.execute(startCmd, asynchExecutionHandler());

var process = startCmd.start();
waitForEngineStart(process);
return process;
}

public void stop() throws Exception {
CommandLine stopCmd = toEngineCommand(Command.stop);
var stopCmd = toEngineCommand(Command.stop);
context.log.info("Stopping Axon Ivy Engine in folder: " + context.engineDirectory);

executeSynch(stopCmd);
waitFor(() -> EngineState.STOPPED == state(), context.timeoutInSeconds, TimeUnit.SECONDS);
}

EngineState state() {
CommandLine statusCmd = toEngineCommand(Command.status);
var statusCmd = toEngineCommand(Command.status);
String engineOutput = executeSynch(statusCmd);
return parseState(engineOutput);
}

private CommandLine toEngineCommand(Command command) {
private ProcessBuilder toEngineCommand(Command command) {
var classpath = context.engineClasspathJarPath.toString();
if (StringUtils.isNotBlank(context.vmOptions.additionalClasspath())) {
classpath += File.pathSeparator + context.vmOptions.additionalClasspath();
}

var osgiDir = context.engineDirectory.resolve(OsgiDir.INSTALL_AREA);

CommandLine cli = new CommandLine(new File(getJavaExec()))
.addArgument("-classpath")
.addArgument(classpath)
.addArgument("-Divy.engine.testheadless=true")
.addArgument("-Djava.awt.headless=true")
.addArgument("-Dosgi.install.area=" + osgiDir.toAbsolutePath());

var commands = new ArrayList<String>();
commands.add(getJavaExec());
commands.add("-classpath");
commands.add(classpath);
commands.add("-Divy.engine.testheadless=true");
commands.add("-Djava.awt.headless=true");
commands.add("-Dosgi.install.area=" + osgiDir.toAbsolutePath());
if (StringUtils.isNotBlank(context.vmOptions.additionalVmOptions())) {
cli.addArguments(context.vmOptions.additionalVmOptions(), false);
// todo quoting
commands.add(context.vmOptions.additionalVmOptions());
}
EngineModuleHints.loadFromJvmOptionsFile(context, cli);

cli.addArgument("org.eclipse.equinox.launcher.Main")
.addArgument("-application").addArgument("ch.ivyteam.ivy.server.exec.engine")
.addArgument(command.toString());
return cli;
//EngineModuleHints.loadFromJvmOptionsFile(context, cli);

commands.add("org.eclipse.equinox.launcher.Main");
commands.add("-application");
commands.add("ch.ivyteam.ivy.server.exec.engine");
// todo correct=
commands.add(command.toString());
return new ProcessBuilder(commands);
}

private Executor createEngineExecutor() {
Expand Down Expand Up @@ -224,14 +227,15 @@ static String evaluateIvyContextFromUrl(String location) {
return StringUtils.substringBefore(StringUtils.removeStart(location, "/"), "sys");
}

private void waitForEngineStart(Executor executor) throws Exception {
private void waitForEngineStart(Process executor) throws Exception {
int i = 0;
while (!engineStarted.get()) {
Thread.sleep(1_000);
i++;
if (!executor.getWatchdog().isWatching()) {
throw new RuntimeException("Engine start failed unexpected.");
}

//if (!executor.getWatchdog().isWatching()) {
// throw new RuntimeException("Engine start failed unexpected.");
//}
if (i > context.timeoutInSeconds) {
throw new TimeoutException("Timeout while starting engine " + context.timeoutInSeconds + " [s].\n"
+ "Check the engine log for details or increase the timeout property '"
Expand Down Expand Up @@ -261,19 +265,20 @@ public void onProcessComplete(int exitValue) {
* @param statusCmd
* @return the output of the engine command.
*/
private String executeSynch(CommandLine statusCmd) {
private String executeSynch(ProcessBuilder statusCmd) {
String engineOutput = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream, System.err);
Executor executor = createEngineExecutor();
executor.setStreamHandler(streamHandler);
executor.setExitValue(-1);
//ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream, System.err);
//Executor executor = createEngineExecutor();
//executor.setStreamHandler(streamHandler);
//executor.setExitValue(-1);
try {
executor.execute(statusCmd);
statusCmd.start();
//executor.execute(statusCmd);
} catch (IOException ex) { // expected!
} finally {
engineOutput = outputStream.toString();
IOUtils.closeQuietly(outputStream);
//engineOutput = outputStream.toString();
//IOUtils.closeQuietly(outputStream);
}
return engineOutput;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.nio.file.StandardCopyOption;
import java.util.stream.Stream;

import org.apache.commons.exec.Executor;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
Expand Down Expand Up @@ -106,7 +105,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
}
}

public Executor startEngine() throws Exception {
public Process startEngine() throws Exception {
var engineDir = engineDir();
var vmOptions = new EngineVmOptions(additionalClasspath, additionalVmOptions);
var ctx = new EngineMojoContext(engineDir, project, getLog(), engineLogFile, vmOptions, startTimeoutInSeconds);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.io.PrintStream;
import java.nio.file.Path;

import org.apache.commons.exec.Executor;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.settings.Server;
Expand Down Expand Up @@ -71,7 +70,7 @@ public void canDeployIar() throws Exception {
var deployedIar = getTarget(deployMojo.deployFile, deployMojo);
var deployedIarFlagFile = deployedIar.resolveSibling(deployedIar.getFileName() + ".deployed");
var deployedIarLogFile = deployedIar.resolveSibling(deployedIar.getFileName() + ".deploymentLog");
Executor startedProcess = null;
Process startedProcess = null;
try {
startedProcess = mojo.startEngine();
deployMojo.execute();
Expand Down Expand Up @@ -116,7 +115,7 @@ private void deployIarRemoteAndAssert() throws Exception, MojoExecutionException
deployMojo.deployToEngineApplication = "test";
deployMojo.deployMethod = DeployMethod.HTTP;

Executor startedProcess = null;
Process startedProcess = null;
try {
System.setOut(originalOut);
startedProcess = mojo.startEngine();
Expand All @@ -142,9 +141,9 @@ private static Path getTarget(Path iar, DeployToEngineMojo mojo) {
.resolve(iar.getFileName().toString());
}

private static void kill(Executor startedProcess) {
private static void kill(Process startedProcess) {
if (startedProcess != null) {
startedProcess.getWatchdog().destroyProcess();
startedProcess.destroy();
}
}

Expand Down
43 changes: 20 additions & 23 deletions src/test/java/ch/ivyteam/ivy/maven/test/TestStartEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
import java.nio.file.Files;
import java.nio.file.Path;

import org.apache.commons.exec.Executor;
import org.apache.commons.exec.ShutdownHookProcessDestroyer;
import org.apache.maven.plugin.MojoExecutionException;
import org.junit.Rule;
import org.junit.Test;
Expand All @@ -44,7 +42,7 @@ public void canStartEngine() throws Exception {
assertThat(getProperty(EngineControl.Property.TEST_ENGINE_URL)).isNull();
assertThat(getProperty(EngineControl.Property.TEST_ENGINE_LOG)).isNull();

Executor startedProcess = null;
Process startedProcess = null;
try {
startedProcess = mojo.startEngine();
assertThat(getProperty(EngineControl.Property.TEST_ENGINE_URL)).startsWith("http://")
Expand All @@ -55,21 +53,20 @@ public void canStartEngine() throws Exception {
}
}

@Test
public void testKillEngineOnVmExit() throws Exception {
StartTestEngineMojo mojo = rule.getMojo();
Executor startedProcess = null;
try {
startedProcess = mojo.startEngine();
assertThat(startedProcess.getProcessDestroyer()).isInstanceOf(ShutdownHookProcessDestroyer.class);
var jvmShutdownHoock = (ShutdownHookProcessDestroyer) startedProcess.getProcessDestroyer();
assertThat(jvmShutdownHoock.size())
.as("One started engine process must be killed on VM end.")
.isEqualTo(1);
} finally {
kill(startedProcess);
}
}
// @Test
// public void testKillEngineOnVmExit() throws Exception {
// StartTestEngineMojo mojo = rule.getMojo();
// Process startedProcess = null;
// try {
// startedProcess = mojo.startEngine();
// var jvmShutdownHoock = (ShutdownHookProcessDestroyer) startedProcess.getProcessDestroyer();
// assertThat(jvmShutdownHoock.size())
// .as("One started engine process must be killed on VM end.")
// .isEqualTo(1);
// } finally {
// kill(startedProcess);
// }
// }

/**
* MODIFY_EXISTING 1. If engine
Expand Down Expand Up @@ -146,7 +143,7 @@ public void startEngine_COPY_FROM_CACHE_cacheEngine() throws MojoExecutionExcept
@Test
public void startEngine_copyEngineToTarget() throws Exception {
StartTestEngineMojo mojo = rule.getMojo();
Executor startedProcess = null;
Process startedProcess = null;
try {
mojo.testEngine = TestEngineLocation.COPY_FROM_TEMPLATE;
var engineDirTarget = mojo.getEngineDir(mojo.project);
Expand All @@ -166,7 +163,7 @@ public void startEngine_targetDirectoryNotClean() throws Exception {
StartTestEngineMojo mojo = rule.getMojo();
mojo.setLog(log);

Executor startedProcess = null;
Process startedProcess = null;
try {
var engineDirTarget = mojo.getEngineDir(mojo.project);
assertThat(engineDirTarget).endsWith(Path.of("/target/ivyEngine"));
Expand All @@ -191,7 +188,7 @@ public void startEngine_targetDirectoryNotClean() throws Exception {
public void startEngine_copiedEngine_executable() throws Exception {
StartTestEngineMojo mojo = rule.getMojo();
mojo.testEngine = TestEngineLocation.COPY_FROM_TEMPLATE;
Executor startedProcess = null;
Process startedProcess = null;
try {
var cacheEngine = mojo.engineDirectory;
assertFileExecutable(cacheEngine.resolve("elasticsearch/bin/elasticsearch"));
Expand All @@ -212,9 +209,9 @@ private void assertFileExecutable(Path file) {
.isExecutable();
}

private static void kill(Executor startedProcess) {
private static void kill(Process startedProcess) {
if (startedProcess != null) {
startedProcess.getWatchdog().destroyProcess();
startedProcess.destroy();
}
}

Expand Down

0 comments on commit 5b3559b

Please sign in to comment.