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();
         }

Reply via email to