You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2022/06/13 14:13:48 UTC

[sling-feature-launcher-maven-plugin] 01/01: SLING-11387 - Allow overriding the version selected artifact ids when launching

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch issue/SLING-11387
in repository https://gitbox.apache.org/repos/asf/sling-feature-launcher-maven-plugin.git

commit 843f625b1b23efbb050d7547be14786b94bc9911
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Mon Jun 13 16:05:54 2022 +0200

    SLING-11387 - Allow overriding the version selected artifact ids when launching
    
    Add an 'additionalBundles' configuration section that can be used to
    configure extra bundles and ensures that the defined version is used.
---
 .../sling/maven/feature/launcher/Launch.java       | 29 ++++---
 .../maven/feature/launcher/LauncherArguments.java  |  4 +-
 .../sling/maven/feature/launcher/StartMojo.java    | 94 +++++++++++++++++-----
 src/main/resources/override-bundles-template.json  |  6 ++
 4 files changed, 100 insertions(+), 33 deletions(-)

diff --git a/src/main/java/org/apache/sling/maven/feature/launcher/Launch.java b/src/main/java/org/apache/sling/maven/feature/launcher/Launch.java
index a0c3d10..6fba085 100644
--- a/src/main/java/org/apache/sling/maven/feature/launcher/Launch.java
+++ b/src/main/java/org/apache/sling/maven/feature/launcher/Launch.java
@@ -18,15 +18,17 @@
  */
 package org.apache.sling.maven.feature.launcher;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
 
 import org.apache.maven.model.Dependency;
 
 public class Launch {
-    
+
     private static final Pattern ID_PATTERN = Pattern.compile("[a-zA-Z0-9_\\-\\.]+");
 
     private String id;
@@ -35,6 +37,7 @@ public class Launch {
     private int startTimeoutSeconds = 30;
     private boolean skip = false;
     private Map<String,String> environmentVariables = new HashMap<>();
+    private List<String> additionalBundles = new ArrayList<>();
 
     public String getId() {
         return id;
@@ -59,11 +62,11 @@ public class Launch {
     public void setLauncherArguments(LauncherArguments launcherArguments) {
         this.launcherArguments = launcherArguments;
     }
-    
+
     public int getStartTimeoutSeconds() {
         return startTimeoutSeconds;
     }
-    
+
     public void setStartTimeoutSeconds(int startTimeoutSeconds) {
         this.startTimeoutSeconds = startTimeoutSeconds;
     }
@@ -86,23 +89,31 @@ public class Launch {
         this.environmentVariables = environmentVariables;
     }
 
+    public List<String> getAdditionalBundles() {
+        return additionalBundles;
+    }
+
+    public void setAdditionalBundles(List<String> additionalBundles) {
+        this.additionalBundles = additionalBundles;
+    }
+
     public void validate() {
-        if ( id == null || id.trim().isEmpty() ) 
+        if ( id == null || id.trim().isEmpty() )
             throw new IllegalArgumentException("Missing id");
-        
+
         if ( !ID_PATTERN.matcher(id).matches() )
             throw new IllegalArgumentException("Invalid id '" + id + "'. Allowed characters are digits, numbers, '-','_' and '.'.");
-        
+
         if ( startTimeoutSeconds < 0 )
             throwInvalid("startTimeout value '" + startTimeoutSeconds + "' is negative" );
-        
+
         if ( feature == null )
             throwInvalid("required field 'feature' is missing");
-        
+
         if ( ! "slingosgifeature".equals(feature.getType()) )
             throwInvalid("type must be 'slingosgifeature' but is '" + feature.getType()+"'");
     }
-    
+
     private void throwInvalid(String reason) {
         throw new IllegalArgumentException("Invalid launch '" + id + "': " + reason);
     }
diff --git a/src/main/java/org/apache/sling/maven/feature/launcher/LauncherArguments.java b/src/main/java/org/apache/sling/maven/feature/launcher/LauncherArguments.java
index 3693172..e70c68f 100644
--- a/src/main/java/org/apache/sling/maven/feature/launcher/LauncherArguments.java
+++ b/src/main/java/org/apache/sling/maven/feature/launcher/LauncherArguments.java
@@ -26,7 +26,7 @@ public class LauncherArguments {
     private String[] vmOptions = new String[0];
     private Map<String, String> frameworkProperties = new HashMap<>();
     private Map<String, String> variables = new HashMap<>();
-    
+
     public String[] getVmOptions() {
         return vmOptions;
     }
@@ -38,7 +38,7 @@ public class LauncherArguments {
     public Map<String, String> getFrameworkProperties() {
         return frameworkProperties;
     }
-    
+
     public void setFrameworkProperties(Map<String, String> frameworkProperties) {
         this.frameworkProperties = frameworkProperties;
     }
diff --git a/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java b/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java
index b25849e..b8965a8 100644
--- a/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java
+++ b/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java
@@ -22,14 +22,20 @@ package org.apache.sling.maven.feature.launcher;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.lang.ProcessBuilder.Redirect;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.model.Dependency;
 import org.apache.maven.plugin.AbstractMojo;
@@ -51,7 +57,7 @@ import org.eclipse.aether.resolution.ArtifactResult;
 
 @Mojo( name = "start", defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST )
 public class StartMojo extends AbstractMojo {
-    
+
     /**
      * Location of the file.
      */
@@ -60,10 +66,10 @@ public class StartMojo extends AbstractMojo {
 
     @Parameter( required = true, defaultValue = "1.1.4")
     private String featureLauncherVersion;
-    
+
     @Parameter(required = true)
     private List<Launch> launches;
-    
+
     // <launches>
     //   <launch>
     //     <id>...</id>
@@ -92,13 +98,15 @@ public class StartMojo extends AbstractMojo {
 
     @Parameter(property = "session", readonly = true, required = true)
     protected MavenSession mavenSession;
-    
+
     @Component
     private ProcessTracker processes;
-    
+
+    @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
 
         Artifact launcherArtifact = new DefaultArtifact("org.apache.sling:org.apache.sling.feature.launcher:" + featureLauncherVersion);
+        List<Path> cleanupPaths = new ArrayList<>();
 
         try {
             RepositorySystemSession repositorySession = mavenSession.getRepositorySession();
@@ -106,10 +114,10 @@ public class StartMojo extends AbstractMojo {
                 .resolveArtifact(repositorySession, new ArtifactRequest(launcherArtifact, remoteRepos, null))
                 .getArtifact()
                 .getFile();
-            
+
             File workDir = new File(outputDirectory, "launchers");
             workDir.mkdirs();
-            
+
             for ( Launch launch : launches ) {
                 if (launch.isSkip()) {
                     getLog().info("Skipping starting launch with id " + launch.getId());
@@ -119,10 +127,10 @@ public class StartMojo extends AbstractMojo {
                 launch.validate();
 
                 Artifact artifact = toArtifact(launch.getFeature());
-                
+
                 ArtifactResult result = resolver.resolveArtifact(repositorySession, new ArtifactRequest(artifact, remoteRepos, null));
                 File featureFile = result.getArtifact().getFile();
-                
+
                 List<String> args = new ArrayList<>();
                 String javahome = System.getenv("JAVA_HOME");
                 if (javahome == null || javahome.isEmpty()) {
@@ -133,25 +141,36 @@ public class StartMojo extends AbstractMojo {
                 args.add(javahome + File.separatorChar + "bin" + File.separatorChar + "java");
                 // SLING-9994 - if any extra vm options were supplied, apply them here
                 String[] vmOptions = launch.getLauncherArguments().getVmOptions();
-                if (vmOptions != null) {
-                    for (String vmOption : vmOptions) {
-                        if (vmOption != null && !vmOption.isEmpty()) {
-                            args.add(vmOption);
-                        }
+                for (String vmOption : vmOptions) {
+                    if (vmOption != null && !vmOption.isEmpty()) {
+                        args.add(vmOption);
                     }
                 }
                 args.add("-jar");
                 args.add(launcher.getAbsolutePath());
                 args.add("-f");
-                args.add(featureFile.getAbsolutePath());
+                if ( ! launch.getAdditionalBundles().isEmpty() ) {
+                    Path overridePath = createOverrideFeatureFile(launch.getAdditionalBundles(), cleanupPaths);
+                    args.add(featureFile.getAbsolutePath() + "," + overridePath.toString());
+                } else {
+                    args.add(featureFile.getAbsolutePath());
+                }
+
+                launch.getAdditionalBundles().stream()
+                    .map( DefaultArtifact::new )
+                    .forEach( a -> {
+                        args.add("-C");
+                        args.add(a.getGroupId() + ":" + a.getArtifactId() + ":*:*:LATEST");
+                });
+
                 args.add("-p");
                 args.add(launch.getId());
-                
+
                 for ( Map.Entry<String, String> frameworkProperty : launch.getLauncherArguments().getFrameworkProperties().entrySet() ) {
                     args.add("-D");
                     args.add(frameworkProperty.getKey()+"="+frameworkProperty.getValue());
                 }
-                
+
                 for ( Map.Entry<String, String> variable : launch.getLauncherArguments().getVariables().entrySet() ) {
                     args.add("-V");
                     args.add(variable.getKey()+"="+variable.getValue());
@@ -164,13 +183,13 @@ public class StartMojo extends AbstractMojo {
                 pb.directory(workDir);
                 launch.getEnvironmentVariables().entrySet()
                     .forEach( e -> pb.environment().put(e.getKey(), e.getValue()) );
-                
+
                 getLog().info("Starting launch with id '" + launch.getId() + "', args=" + args);
-                
+
                 CountDownLatch latch = new CountDownLatch(1);
-                
+
                 Process process = pb.start();
-                
+
                 Thread monitor = new Thread("launch-monitor-" + launch.getId()) {
                     @Override
                     public void run() {
@@ -196,7 +215,7 @@ public class StartMojo extends AbstractMojo {
                     ProcessTracker.stop(process);
                     throw new MojoExecutionException("Launch " + launch.getId() + " failed to start in " + launch.getStartTimeoutSeconds() + " seconds.");
                 }
-                
+
                 processes.startTracking(launch.getId(), process);
             }
 
@@ -205,7 +224,38 @@ public class StartMojo extends AbstractMojo {
         } catch ( InterruptedException e ) {
             Thread.currentThread().interrupt();
             throw new MojoExecutionException("Execution interrupted", e);
+        } finally {
+            for ( Path cleanupPath : cleanupPaths ) {
+                try {
+                    if ( cleanupPath.toFile().exists() )
+                        Files.delete(cleanupPath);
+                } catch (IOException e) {
+                    getLog().warn("Failed deleting " + cleanupPath, e);
+                }
+            }
+        }
+    }
+
+    // we strive to not pull in dependencies on the feature model and only retrieve it at runtime
+    // therefore we don't use the feature model API here
+    private Path createOverrideFeatureFile(List<String> overrideArtifacts, List<Path> cleanupPaths) throws IOException {
+        Path overridePath = Files.createTempFile("launcher-override-", ".json");
+        cleanupPaths.add(overridePath);
+        String jsonFragment = overrideArtifacts.stream()
+            .map( a -> "{ \"id\": \"" + a + "\" }\n"  )
+            .collect(Collectors.joining(","));
+
+
+        try ( InputStream inputStream = getClass().getResourceAsStream("/override-bundles-template.json") ) {
+            if ( inputStream == null )
+                throw new IllegalArgumentException("Failed to locate feature template for artifact override");
+            List<String> inputLines = IOUtils.readLines(inputStream, StandardCharsets.UTF_8);
+            List<String> outputLines = inputLines.stream()
+                .map( s -> s.replace("##BUNDLES##", jsonFragment) )
+                .collect(Collectors.toList());
+            Files.write(overridePath, outputLines);
         }
+        return overridePath;
     }
 
     private Artifact toArtifact(Dependency dependency) {
diff --git a/src/main/resources/override-bundles-template.json b/src/main/resources/override-bundles-template.json
new file mode 100644
index 0000000..510bfce
--- /dev/null
+++ b/src/main/resources/override-bundles-template.json
@@ -0,0 +1,6 @@
+{
+  "id":"org.apache.sling:org.apache.sling.tmp.synthetic-feature:slingosgifeature:1-SNAPSHOT",
+  "bundles":[
+    ##BUNDLES##
+  ]
+}
\ No newline at end of file