This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
The following commit(s) were added to refs/heads/master by this push:
new 8dabbe0 SLING-9526 - Allow launching feature model applications in
external processes, non-blocking
8dabbe0 is described below
commit 8dabbe04b413b40231825555df65cf8cb94f5835
Author: Robert Munteanu <[email protected]>
AuthorDate: Wed Jun 24 22:39:35 2020 +0200
SLING-9526 - Allow launching feature model applications in external
processes, non-blocking
Advanced with a very basic implementation, but good enough to start
launchpad-testing.
---
.../launcher/{Processes.java => Launch.java} | 38 +++++--
.../{Processes.java => LauncherArguments.java} | 16 +--
.../sling/maven/feature/launcher/Processes.java | 13 ++-
.../sling/maven/feature/launcher/StartMojo.java | 123 +++++++++++++++------
.../sling/maven/feature/launcher/StopMojo.java | 19 ++--
5 files changed, 146 insertions(+), 63 deletions(-)
diff --git
a/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java
b/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Launch.java
similarity index 56%
copy from
feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java
copy to
feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Launch.java
index 85eed28..0b98119 100644
---
a/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java
+++
b/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Launch.java
@@ -18,18 +18,36 @@
*/
package org.apache.sling.maven.feature.launcher;
-import java.util.Optional;
+import org.apache.maven.model.Dependency;
-// TODO - refactor to a Mojo Component
-public class Processes {
+public class Launch {
- private static Process process;
-
- public static void set(Process process) {
- Processes.process = process;
+ private String id;
+ private Dependency feature;
+ private LauncherArguments launcherArguments;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
}
-
- public static Optional<Process> get() {
- return Optional.ofNullable(process);
+
+ public Dependency getFeature() {
+ return feature;
+ }
+
+ public void setFeature(Dependency feature) {
+ this.feature = feature;
}
+
+ public LauncherArguments getLauncherArguments() {
+ return launcherArguments;
+ }
+
+ public void setLauncherArguments(LauncherArguments launcherArguments) {
+ this.launcherArguments = launcherArguments;
+ }
+
}
diff --git
a/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java
b/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/LauncherArguments.java
similarity index 69%
copy from
feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java
copy to
feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/LauncherArguments.java
index 85eed28..c96958f 100644
---
a/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java
+++
b/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/LauncherArguments.java
@@ -18,18 +18,18 @@
*/
package org.apache.sling.maven.feature.launcher;
-import java.util.Optional;
+import java.util.HashMap;
+import java.util.Map;
-// TODO - refactor to a Mojo Component
-public class Processes {
+public class LauncherArguments {
- private static Process process;
+ private Map<String, String> frameworkProperties = new HashMap<>();
- public static void set(Process process) {
- Processes.process = process;
+ public Map<String, String> getFrameworkProperties() {
+ return frameworkProperties;
}
- public static Optional<Process> get() {
- return Optional.ofNullable(process);
+ public void setFrameworkProperties(Map<String, String>
frameworkProperties) {
+ this.frameworkProperties = frameworkProperties;
}
}
diff --git
a/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java
b/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java
index 85eed28..79d7351 100644
---
a/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java
+++
b/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java
@@ -18,18 +18,21 @@
*/
package org.apache.sling.maven.feature.launcher;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Optional;
// TODO - refactor to a Mojo Component
public class Processes {
- private static Process process;
+ private static final Map<String, Process> processes = new HashMap<>();
- public static void set(Process process) {
- Processes.process = process;
+ public static void addProcess(String id, Process process) {
+ // TODO - check for duplicates
+ processes.put(id, process);
}
- public static Optional<Process> get() {
- return Optional.ofNullable(process);
+ public static Optional<Process> get(String id) {
+ return Optional.ofNullable(processes.get(id));
}
}
diff --git
a/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java
b/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java
index 4b39d99..7ec48ab 100644
---
a/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java
+++
b/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java
@@ -19,12 +19,15 @@
package org.apache.sling.maven.feature.launcher;
+import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.ProcessBuilder.Redirect;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
@@ -54,12 +57,22 @@ public class StartMojo
@Parameter( defaultValue = "${project.build.directory}", property =
"outputDir", required = true )
private File outputDirectory;
- // TODO - support multiple dependencies and also have proper parameter
names
@Parameter(required = true)
- private Dependency toLaunch;
-
- @Parameter
- private Map<String, String> frameworkProperties = new HashMap<String,
String>();
+ private List<Launch> launches;
+
+ // <launches>
+ // <launch>
+ // <id>...</id>
+ // <dependency>...</dependency>
+ // <launcherArguments>
+ // <frameworkProperties>
+ // <org.osgi.service.http.port>8090</org.osgi.service.http.port>
+ // </framweworkProperties>
+ // ...
+ // </launcherArguments>
+ // <environment>
+ // <JAVA_HOME>...</JAVA_HOME>
+ // </environment>
@Component
private ArtifactResolver resolver;
@@ -76,11 +89,6 @@ public class StartMojo
try {
RepositorySystemSession repositorySession =
mavenSession.getRepositorySession();
- Artifact artifact = toArtifact(toLaunch);
-
- ArtifactResult result =
resolver.resolveArtifact(repositorySession, new ArtifactRequest(artifact, null,
null));
- File featureFile = result.getArtifact().getFile();
-
// TODO - this should be inferred from the plugin's pom.xml
dependency (not the project's pom.xml)
Dependency featureLauncherDep = project.getDependencies().stream()
@@ -97,28 +105,79 @@ public class StartMojo
File workDir = new File(outputDirectory, "launchers");
workDir.mkdirs();
- List<String> args = new ArrayList<>();
- args.add(System.getenv("JAVA_HOME") + File.separatorChar + "bin" +
File.separatorChar + "java");
- args.add("-jar");
- args.add(launcher.getAbsolutePath());
- args.add("-f");
- args.add(featureFile.getAbsolutePath());
+ for ( Launch launch : launches ) {
- for ( var frameworkProperty : frameworkProperties.entrySet() ) {
- args.add("-D");
-
args.add(frameworkProperty.getKey()+"="+frameworkProperty.getValue());
+ // TODO - validate it is actually a feature
+ Artifact artifact = toArtifact(launch.getFeature());
+
+ ArtifactResult result =
resolver.resolveArtifact(repositorySession, new ArtifactRequest(artifact, null,
null));
+ File featureFile = result.getArtifact().getFile();
+
+ List<String> args = new ArrayList<>();
+ args.add(System.getenv("JAVA_HOME") + File.separatorChar +
"bin" + File.separatorChar + "java");
+ args.add("-jar");
+ args.add(launcher.getAbsolutePath());
+ args.add("-f");
+ args.add(featureFile.getAbsolutePath());
+ args.add("-p");
+ args.add(launch.getId()); // TODO - validate launch id is a
valid file name
+
+ for ( var frameworkProperty :
launch.getLauncherArguments().getFrameworkProperties().entrySet() ) {
+ args.add("-D");
+
args.add(frameworkProperty.getKey()+"="+frameworkProperty.getValue());
+ }
+
+ // TODO - add support for all arguments supported by the
feature launcher
+ ProcessBuilder pb = new ProcessBuilder(args);
+ pb.redirectOutput(Redirect.INHERIT);
+ pb.redirectInput(Redirect.INHERIT);
+ pb.directory(workDir);
+
+ getLog().info("Starting launch with id " + launch.getId());
+
+ CountDownLatch latch = new CountDownLatch(1);
+
+ Process process = pb.start();
+
+ Thread monitor = new Thread("launch-monitor-" +
launch.getId()) {
+ @Override
+ public void run() {
+ BufferedReader reader = new BufferedReader(new
InputStreamReader(process.getErrorStream()));
+ String line;
+ try {
+ while ( (line = reader.readLine()) != null ) {
+ System.out.println(line);
+// getLog().info("Checking line '" + line);
+ if ( line.contains("Framework started")) {
+// getLog().info("STARTED!");
+ latch.countDown();
+ break;
+ }
+ }
+ } catch (IOException e) {
+ getLog().warn(e.getMessage(), e);
+ }
+ }
+ };
+ monitor.start();
+ getLog().info("Waiting for " + launch.getId() + " to start");
+ boolean started = latch.await(30, TimeUnit.SECONDS);
+ if ( !started ) {
+ process.destroy();
+ boolean stopped = process.waitFor(30, TimeUnit.SECONDS);
+ if ( !stopped )
+ process.destroyForcibly();
+ throw new MojoExecutionException("Launch " +
launch.getId() + " failed to start in the allocated time.");
+ }
+
+
+ // TODO - reliably stop started processes in case 'stop' is
not invoked
+
+ Processes.addProcess(launch.getId(), process);
}
-
- // TODO - add support for all arguments supported by the feature
launcher
- ProcessBuilder pb = new ProcessBuilder(args);
- pb.inheritIO();
- pb.directory(workDir);
- Process process = pb.start();
-
- // TODO - reliably stop started processes in case 'stop' is not
invoked
-
- Processes.set(process);
- } catch (ArtifactResolutionException | IOException e) {
+
+ // TODO - properly handle interrupted exception
+ } catch (ArtifactResolutionException | IOException |
InterruptedException e) {
throw new MojoExecutionException(e.getMessage(), e);
}
}
diff --git
a/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/StopMojo.java
b/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/StopMojo.java
index 837a0c2..d3b10bf 100644
---
a/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/StopMojo.java
+++
b/feature-launcher-maven-plugin/src/main/java/org/apache/sling/maven/feature/launcher/StopMojo.java
@@ -18,6 +18,7 @@
*/
package org.apache.sling.maven.feature.launcher;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.maven.plugin.AbstractMojo;
@@ -25,22 +26,24 @@ import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
@Mojo( name = "stop", defaultPhase = LifecyclePhase.POST_INTEGRATION_TEST)
public class StopMojo extends AbstractMojo {
+ @Parameter(required = true)
+ private List<Launch> launches;
+
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
try {
- // TODO - for testing only, remove once the IT does something
meaningful
- Thread.sleep(30 * 1000);
-
- Process process = Processes.get()
- .get();
-
- process.destroy();
- process.waitFor(30, TimeUnit.SECONDS);
+ for ( Launch launch : launches ) {
+ getLog().info("Stopping launch with id " + launch.getId());
+ Process process = Processes.get(launch.getId()).get();
+ process.destroy();
+ process.waitFor(30, TimeUnit.SECONDS);
+ }
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}