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