You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by en...@apache.org on 2022/11/19 03:27:48 UTC
[sling-feature-launcher-maven-plugin] branch master updated: SLING-11685 use feature launcher assembly to launch (#4)
This is an automated email from the ASF dual-hosted git repository.
enorman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-feature-launcher-maven-plugin.git
The following commit(s) were added to refs/heads/master by this push:
new 16063e8 SLING-11685 use feature launcher assembly to launch (#4)
16063e8 is described below
commit 16063e803ffebd915f6f5e2202581376574d9dd8
Author: Eric Norman <en...@apache.org>
AuthorDate: Fri Nov 18 19:27:44 2022 -0800
SLING-11685 use feature launcher assembly to launch (#4)
unpack the feature launcher assembly and use the contained script
---
pom.xml | 6 +
.../pom.xml | 7 +-
.../src/main/features/model.json | 14 +++
.../apache/sling/it/SLING10956/AppRunningIT.java | 84 +++++++++++++
src/it/simple-for-SLING-10956-it/verify.groovy | 21 ++++
src/it/simple-it/pom.xml | 3 +
.../sling/maven/feature/launcher/StartMojo.java | 131 +++++++++++++++++----
7 files changed, 240 insertions(+), 26 deletions(-)
diff --git a/pom.xml b/pom.xml
index e9de3d1..f110a09 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,6 +81,12 @@
<artifactId>javax.inject</artifactId>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-archiver</artifactId>
+ <version>4.2.7</version>
+ <scope>compile</scope>
+ </dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-interactivity-api</artifactId>
diff --git a/src/it/simple-it/pom.xml b/src/it/simple-for-SLING-10956-it/pom.xml
similarity index 96%
copy from src/it/simple-it/pom.xml
copy to src/it/simple-for-SLING-10956-it/pom.xml
index 04286ed..35db3e7 100644
--- a/src/it/simple-it/pom.xml
+++ b/src/it/simple-for-SLING-10956-it/pom.xml
@@ -15,7 +15,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.sling</groupId>
- <artifactId>simple-it</artifactId>
+ <artifactId>simple-for-SLING-10956-it</artifactId>
<version>1.0-SNAPSHOT</version>
<description>A simple IT verifying starting and stopping.</description>
@@ -40,7 +40,7 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
- <version>4.5.13</version>
+ <version>4.5.12</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -101,12 +101,13 @@
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<configuration>
+ <featureLauncherVersion>1.2.0</featureLauncherVersion>
<launches>
<launch>
<id>model</id>
<feature>
<groupId>org.apache.sling</groupId>
- <artifactId>simple-it</artifactId>
+ <artifactId>simple-for-SLING-10956-it</artifactId>
<version>1.0-SNAPSHOT</version>
<classifier>main</classifier>
<type>slingosgifeature</type>
diff --git a/src/it/simple-for-SLING-10956-it/src/main/features/model.json b/src/it/simple-for-SLING-10956-it/src/main/features/model.json
new file mode 100644
index 0000000..ee05e71
--- /dev/null
+++ b/src/it/simple-for-SLING-10956-it/src/main/features/model.json
@@ -0,0 +1,14 @@
+{
+ "id":"${project.groupId}:${project.artifactId}:model:${project.version}",
+ "bundles": [
+ "org.apache.felix/org.apache.felix.scr/2.1.20",
+ "org.apache.felix/org.apache.felix.log/1.2.2",
+ "org.apache.felix/org.apache.felix.configadmin/1.9.16",
+ "org.osgi/org.osgi.util.promise/1.1.1",
+ "org.osgi/org.osgi.util.function/1.1.0",
+ "org.osgi/org.osgi.util.converter/1.0.1",
+ "org.apache.commons/commons-lang3/3.9",
+ "org.apache.felix/org.apache.felix.http.jetty/4.0.16",
+ "org.apache.felix/org.apache.felix.http.servlet-api/1.1.2"
+ ]
+}
\ No newline at end of file
diff --git a/src/it/simple-for-SLING-10956-it/src/test/java/org/apache/sling/it/SLING10956/AppRunningIT.java b/src/it/simple-for-SLING-10956-it/src/test/java/org/apache/sling/it/SLING10956/AppRunningIT.java
new file mode 100644
index 0000000..d7671bd
--- /dev/null
+++ b/src/it/simple-for-SLING-10956-it/src/test/java/org/apache/sling/it/SLING10956/AppRunningIT.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.it.SLING10956;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Optional;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.MethodOrderer.Alphanumeric;
+import org.junit.jupiter.api.TestMethodOrder;
+ import org.apache.http.impl.client.*;
+import org.apache.http.client.methods.*;
+
+@TestMethodOrder(Alphanumeric.class)
+public class AppRunningIT {
+
+ @Test
+ public void aaSlingAppIsUp() throws Exception {
+
+ int port = Integer.getInteger("HTTP_PORT", 8080);
+
+ try ( CloseableHttpClient httpclient = HttpClients.createDefault() ) {
+ HttpGet get = new HttpGet("http://localhost:" + port + "/");
+ for ( int i = 0; i < 30; i++ ) {
+ try ( CloseableHttpResponse response = httpclient.execute(get) ) {
+ System.out.println("Status line = " + response.getStatusLine().toString());
+ int statusCode = response.getStatusLine().getStatusCode();
+ if ( (statusCode / 100 < 5 ) ) {
+ System.out.println("App is ready");
+ return;
+ }
+ Thread.sleep(1000l);
+ }
+ }
+
+ fail("App is not yet ready, failing");
+ }
+ }
+
+ @Test
+ public void bbCheckLauncherEnvironmentVarInLogs() throws Exception {
+ final String logFilename = System.getProperty("build.log.file");
+
+ // This verifies the launcherArguments vmOptions and variables from our test pom
+ final Pattern expected = Pattern.compile(".*\\-DTEST_VM_OPTION=TEST_VM_OPTION_VALUE.*");
+
+ try (Stream<String> lines = Files.lines(Paths.get(logFilename))) {
+ final Optional<String> expectedLine = lines.filter(line -> expected.matcher(line).matches()).findFirst();
+ assertTrue(expectedLine.isPresent(), "Expected pattern " + expected + " to be found in log file " + logFilename);
+ }
+ }
+
+ @Test
+ public void bbCheckLauncherCommandLineInLogs() throws Exception {
+ final String logFilename = System.getProperty("build.log.file");
+
+ // This verifies the launcherArguments vmOptions and variables from our test pom
+ final Pattern expected = Pattern.compile(".*\\-V, TEST_VARIABLE=TEST_VALUE.*");
+
+ try (Stream<String> lines = Files.lines(Paths.get(logFilename))) {
+ final Optional<String> expectedLine = lines.filter(line -> expected.matcher(line).matches()).findFirst();
+ assertTrue(expectedLine.isPresent(), "Expected pattern " + expected + " to be found in log file " + logFilename);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/it/simple-for-SLING-10956-it/verify.groovy b/src/it/simple-for-SLING-10956-it/verify.groovy
new file mode 100644
index 0000000..e9b7465
--- /dev/null
+++ b/src/it/simple-for-SLING-10956-it/verify.groovy
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+File touchFile = new File( basedir, "build.log" );
+
+assert touchFile.isFile()
diff --git a/src/it/simple-it/pom.xml b/src/it/simple-it/pom.xml
index 04286ed..903dd04 100644
--- a/src/it/simple-it/pom.xml
+++ b/src/it/simple-it/pom.xml
@@ -101,6 +101,9 @@
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<configuration>
+ <!-- pin this at the 1.1.26 version to test launching
+ using the pre SLING-10956 technique -->
+ <featureLauncherVersion>1.1.26</featureLauncherVersion>
<launches>
<launch>
<id>model</id>
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 c1f9970..2278d6f 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
@@ -24,12 +24,18 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ProcessBuilder.Redirect;
+import java.nio.file.Path;
+import java.nio.file.Paths;
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.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
@@ -40,6 +46,10 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
+import org.apache.maven.shared.utils.Os;
+import org.codehaus.plexus.archiver.UnArchiver;
+import org.codehaus.plexus.archiver.manager.ArchiverManager;
+import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
@@ -54,7 +64,10 @@ import org.eclipse.aether.resolution.ArtifactResult;
*/
@Mojo( name = "start", defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST )
public class StartMojo extends AbstractMojo {
-
+
+ private static final String JAVA_HOME = "JAVA_HOME";
+ private static final String JAVA_OPTS = "JAVA_OPTS";
+
/**
* The directory in which the features are launched (below its child directory {@code launchers/<launch-id>}).
*/
@@ -101,21 +114,55 @@ public class StartMojo extends AbstractMojo {
@Component
private ProcessTracker processes;
-
- @Override
- public void execute() throws MojoExecutionException, MojoFailureException {
- Artifact launcherArtifact = new DefaultArtifact("org.apache.sling:org.apache.sling.feature.launcher:" + featureLauncherVersion);
+ /**
+ * To look up UnArchiver implementations
+ */
+ @Component
+ private ArchiverManager archiverManager;
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
try {
+ // the feature launcher before version 1.1.28 used a single jar, while versions
+ // after that provide an assembly per SLING-10956
+ VersionRange beforeAssemblyRange = VersionRange.createFromVersionSpec("(,1.1.26]");
+ boolean useAssembly = !beforeAssemblyRange.containsVersion(new DefaultArtifactVersion(featureLauncherVersion));
+
RepositorySystemSession repositorySession = mavenSession.getRepositorySession();
- File launcher = resolver
- .resolveArtifact(repositorySession, new ArtifactRequest(launcherArtifact, remoteRepos, null))
- .getArtifact()
- .getFile();
-
File workDir = new File(outputDirectory, "launchers");
workDir.mkdirs();
+
+ File launcher;
+ if (useAssembly) {
+ // fetch the assembly artifact
+ Artifact launcherAssemblyArtifact = new DefaultArtifact("org.apache.sling:org.apache.sling.feature.launcher:tar.gz:" + featureLauncherVersion);
+ File assemblyArchive = resolver
+ .resolveArtifact(repositorySession, new ArtifactRequest(launcherAssemblyArtifact, remoteRepos, null))
+ .getArtifact()
+ .getFile();
+
+ // unpack the file
+ UnArchiver unArchiver = archiverManager.getUnArchiver( assemblyArchive );
+ unArchiver.setSourceFile(assemblyArchive);
+ unArchiver.setDestFile(workDir);
+ unArchiver.extract();
+
+ // system property
+ Path relPath = Paths.get(launcherAssemblyArtifact.getArtifactId() + "-" + launcherAssemblyArtifact.getVersion(), "bin");
+ if (Os.isFamily(Os.FAMILY_WINDOWS)) {
+ relPath = relPath.resolve("launcher.bat");
+ } else {
+ relPath = relPath.resolve("launcher");
+ }
+ launcher = workDir.toPath().resolve(relPath).toFile();
+ } else {
+ Artifact launcherArtifact = new DefaultArtifact("org.apache.sling:org.apache.sling.feature.launcher:" + featureLauncherVersion);
+ launcher = resolver
+ .resolveArtifact(repositorySession, new ArtifactRequest(launcherArtifact, remoteRepos, null))
+ .getArtifact()
+ .getFile();
+ }
for ( Launch launch : launches ) {
if (launch.isSkip()) {
@@ -129,24 +176,59 @@ public class StartMojo extends AbstractMojo {
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");
+
+ String javahome = System.getenv(JAVA_HOME);
if (javahome == null || javahome.isEmpty()) {
// SLING-9843 fallback to java.home system property if JAVA_HOME env variable is not set
getLog().warn("The JAVA_HOME env variable was not set, falling back to the java.home system property");
javahome = System.getProperty("java.home");
}
- 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();
- for (String vmOption : vmOptions) {
- if (vmOption != null && !vmOption.isEmpty()) {
- args.add(vmOption);
+ List<String> args = new ArrayList<>();
+ if (useAssembly) {
+ // use the post v1.1.28 launcher script
+
+ Map<String, String> newEnv = new HashMap<>(launch.getEnvironmentVariables());
+ newEnv.put(JAVA_HOME, javahome);
+
+ // SLING-9994 - if any extra vm options were supplied, apply them here
+ StringBuilder javaOptsBuilder = null;
+ String[] vmOptions = launch.getLauncherArguments().getVmOptions();
+ for (String vmOption : vmOptions) {
+ if (vmOption != null && !vmOption.isEmpty()) {
+ if (javaOptsBuilder == null) {
+ javaOptsBuilder = new StringBuilder();
+ } else {
+ javaOptsBuilder.append(" ");
+ }
+ javaOptsBuilder.append(vmOption);
+ }
+ }
+ if (javaOptsBuilder != null) {
+ // pass vmOptions through JAVA_OPTS environment variable?
+ if (newEnv.containsKey(JAVA_OPTS)) {
+ // if the original value existed append it to our buffer
+ javaOptsBuilder.append(" ").append(newEnv.get(JAVA_OPTS));
+ }
+ newEnv.put(JAVA_OPTS, javaOptsBuilder.toString());
+ }
+
+ args.add(launcher.getAbsolutePath());
+
+ launch.setEnvironmentVariables(newEnv);
+ } else {
+ // use the pre v1.1.28 single jar technique
+
+ 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();
+ for (String vmOption : vmOptions) {
+ if (vmOption != null && !vmOption.isEmpty()) {
+ args.add(vmOption);
+ }
}
+ args.add("-jar");
+ args.add(launcher.getAbsolutePath());
}
- args.add("-jar");
- args.add(launcher.getAbsolutePath());
args.add("-f");
args.add(featureFile.getAbsolutePath());
args.add("-p");
@@ -168,7 +250,10 @@ public class StartMojo extends AbstractMojo {
pb.redirectInput(Redirect.INHERIT);
pb.directory(workDir);
launch.getEnvironmentVariables().entrySet()
- .forEach( e -> pb.environment().put(e.getKey(), e.getValue()) );
+ .forEach( e -> {
+ getLog().info("Setting environment variable '" + e.getKey() + "' to '" + e.getValue() + "'");
+ pb.environment().put(e.getKey(), e.getValue());
+ } );
getLog().info("Starting launch with id '" + launch.getId() + "', args=" + args);
@@ -205,7 +290,7 @@ public class StartMojo extends AbstractMojo {
processes.startTracking(launch.getId(), process);
}
- } catch (ArtifactResolutionException | IOException e) {
+ } catch (NoSuchArchiverException | InvalidVersionSpecificationException | ArtifactResolutionException | IOException e) {
throw new MojoExecutionException(e.getMessage(), e);
} catch ( InterruptedException e ) {
Thread.currentThread().interrupt();