You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2022/10/14 12:46:59 UTC

[karaf] branch karaf-4.3.x updated: [KARAF-6319] - add option to assembly mojo

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

jbonofre pushed a commit to branch karaf-4.3.x
in repository https://gitbox.apache.org/repos/asf/karaf.git


The following commit(s) were added to refs/heads/karaf-4.3.x by this push:
     new 9873f949a2 [KARAF-6319] - add <firstStageBootFeatures> option to assembly mojo
9873f949a2 is described below

commit 9873f949a264955b2ab65c01f2fe184c549aebbd
Author: Aleksy Wróblewski <al...@bbbit.io>
AuthorDate: Thu Oct 13 23:50:05 2022 +0200

    [KARAF-6319] - add <firstStageBootFeatures> option to assembly mojo
    
    (cherry picked from commit b86a4eb7937fff8284ad9fede2bfb8b4e42a1282)
---
 .../karaf-maven-example-assembly/pom.xml           | 10 +++-
 .../developer-guide/karaf-maven-plugin.adoc        |  8 ++-
 .../org/apache/karaf/profile/assembly/Builder.java | 14 +++++
 .../apache/karaf/profile/assembly/BuilderTest.java | 65 +++++++++++++++++++---
 .../repo/foo/qux/1.0/qux-1.0-features.xml          | 22 ++++++++
 .../org/apache/karaf/tooling/AssemblyMojo.java     | 11 ++++
 6 files changed, 117 insertions(+), 13 deletions(-)

diff --git a/examples/karaf-maven-example/karaf-maven-example-assembly/pom.xml b/examples/karaf-maven-example/karaf-maven-example-assembly/pom.xml
index b82c911eea..e1669a5be2 100644
--- a/examples/karaf-maven-example/karaf-maven-example-assembly/pom.xml
+++ b/examples/karaf-maven-example/karaf-maven-example-assembly/pom.xml
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.apache.karaf.examples</groupId>
         <artifactId>karaf-maven-example</artifactId>
-        <version>4.3.0-SNAPSHOT</version>
+        <version>4.4.2-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
@@ -60,10 +60,14 @@
                     <installedBundles>
                         <installedBundle>mvn:commons-lang/commons-lang/2.6</installedBundle>
                     </installedBundles>
+                    <firstStageBootFeatures>
+                        <feature>instance</feature>
+                        <feature>diagnostic</feature>
+                        <!-- resolves to 'bundle' -->
+                        <feature>bun*</feature>
+                    </firstStageBootFeatures>
                     <bootFeatures>
-                        <feature>bundle</feature>
                         <feature>config</feature>
-                        <feature>diagnostic</feature>
                         <feature>feature</feature>
                         <feature>jaas</feature>
                         <feature>shell</feature>
diff --git a/manual/src/main/asciidoc/developer-guide/karaf-maven-plugin.adoc b/manual/src/main/asciidoc/developer-guide/karaf-maven-plugin.adoc
index a6c38662aa..993e6ce249 100644
--- a/manual/src/main/asciidoc/developer-guide/karaf-maven-plugin.adoc
+++ b/manual/src/main/asciidoc/developer-guide/karaf-maven-plugin.adoc
@@ -471,6 +471,9 @@ The `karaf:assembly` goal creates a Karaf instance (assembly) filesystem using t
                     <installedBundles>
                         <installedBundle>${additional.bundle}</installedBundle>
                     </installedBundles>
+                    <firstStageBootFeatures>
+                        <feature>ssh</feature>
+                    </firstStageBootFeatures>
                     <bootFeatures>
                         <feature>bundle</feature>
                         <feature>config</feature>
@@ -482,7 +485,6 @@ The `karaf:assembly` goal creates a Karaf instance (assembly) filesystem using t
                         <feature>management</feature>
                         <feature>package</feature>
                         <feature>shell-compat</feature>
-                        <feature>ssh</feature>
                         <feature>system</feature>
                         <feature>wrap</feature>
                     </bootFeatures>
@@ -593,6 +595,10 @@ It's also possible to generate a Karaf instance as a static distribution (kind o
 |`List<String>`
 |List of features from compile-scope features XML files and KARs to be installed into system repo and listed in etc/startup.properties.
 
+|`firstStageBootFeatures`
+|`List<String>`
+|List of features from runtime-scope features XML files and KARs to be installed into system repo and listed in featuresBoot property in etc/org.apache.karaf.features.cfg.These will be installed before bootFeatures. They will be wrapped in parentheses in featuresBoot.
+
 |`bootFeatures`
 |`List<String>`
 |List of features from runtime-scope features XML files and KARs to be installed into system repo and listed in featuresBoot property in etc/org.apache.karaf.features.cfg
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
index 14c4b8d0ce..1f96027866 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
@@ -288,6 +288,7 @@ public class Builder {
     Map<String, Stage> profiles = new LinkedHashMap<>();
     Map<String, RepositoryInfo> repositories = new LinkedHashMap<>();
     Map<String, Stage> features = new LinkedHashMap<>();
+    Set<String> firstStageBootFeatures = new HashSet<>();
     Map<String, Stage> bundles = new LinkedHashMap<>();
     List<String> blacklistedProfileNames = new ArrayList<>();
     List<String> blacklistedFeatureIdentifiers = new ArrayList<>();
@@ -441,6 +442,17 @@ public class Builder {
         return this;
     }
 
+    /**
+     * Configure first stage features to use at boot stage. Each feature may be specified as
+     * <code>name</code> or <code>name/version</code> (no version ranges allowed).
+     * @param features
+     * @return
+     */
+    public Builder firstStageBootFeatures(String... features) {
+        this.firstStageBootFeatures.addAll(Arrays.asList(features));
+        return features(Stage.Boot, features);
+    }
+
     /**
      * Configure features to use at current {@link #defaultStage stage}. Each feature may be specified as
      * <code>name</code> or <code>name/version</code> (no version ranges allowed).
@@ -1734,6 +1746,8 @@ public class Builder {
                     generatedDep.put(dep.getName(), dep);
                 }
                 dep.setDependency(false);
+                dep.setPrerequisite(firstStageBootFeatures.contains(dep.getName()) || firstStageBootFeatures.contains(
+                        nameOrPattern));
             }
         }
         // Add bundles
diff --git a/profile/src/test/java/org/apache/karaf/profile/assembly/BuilderTest.java b/profile/src/test/java/org/apache/karaf/profile/assembly/BuilderTest.java
index 366859bceb..9f10b38704 100644
--- a/profile/src/test/java/org/apache/karaf/profile/assembly/BuilderTest.java
+++ b/profile/src/test/java/org/apache/karaf/profile/assembly/BuilderTest.java
@@ -16,6 +16,9 @@
  */
 package org.apache.karaf.profile.assembly;
 
+import org.junit.Test;
+import org.osgi.framework.Constants;
+
 import java.io.BufferedWriter;
 import java.io.IOException;
 import java.nio.file.DirectoryStream;
@@ -25,17 +28,17 @@ import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.List;
 
-import org.junit.Test;
-import org.osgi.framework.Constants;
-
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 public class BuilderTest {
 
-    @Test
-    public void testCyclicRepos() throws Exception {
-        Path workDir = Paths.get("target/distrib");
+    private final Path workDir = Paths.get("target/distrib");
+    private final Path mvnRepo = Paths.get("target/test-classes/repo");
+
+
+    private void setUp() throws Exception {
         recursiveDelete(workDir);
 
         // Create dummy etc/config.properties file
@@ -47,8 +50,12 @@ public class BuilderTest {
             w.write(Constants.FRAMEWORK_SYSTEMCAPABILITIES + "= ");
             w.newLine();
         }
+    }
+
+    @Test
+    public void testCyclicRepos() throws Exception {
+        setUp();
 
-        Path mvnRepo = Paths.get("target/test-classes/repo");
         Builder builder = Builder.newInstance()
                 .repositories(Builder.Stage.Startup, true, "mvn:foo/baz/1.0/xml/features")
                 .homeDirectory(workDir)
@@ -61,6 +68,47 @@ public class BuilderTest {
         }
     }
 
+    @Test
+    public void testFeatures() throws Exception {
+        setUp();
+
+        Builder builder = Builder.newInstance()
+                .repositories(Builder.Stage.Startup, false, "mvn:foo/qux/1.0/xml/features")
+                .homeDirectory(workDir)
+                .localRepository(mvnRepo.toString())
+                .features("qux-*");
+
+        builder.generateAssembly();
+
+        assertFeaturesBootContainsFeatures("qux-feature", "qux-feature2");
+    }
+
+    @Test
+    public void testFirstStageBootFeatures() throws Exception {
+        setUp();
+
+        Builder builder = Builder.newInstance()
+                .repositories(Builder.Stage.Startup, false, "mvn:foo/qux/1.0/xml/features")
+                .homeDirectory(workDir).localRepository(mvnRepo.toString())
+                .firstStageBootFeatures("another-feature")
+                .features("qux-*");
+
+        builder.generateAssembly();
+
+        assertFeaturesBootContainsFeatures("qux-feature", "qux-feature2", "(another-feature)");
+    }
+
+    private void assertFeaturesBootContainsFeatures(String... expectedFeatures) throws IOException {
+        Path featuresCfgFilePath = Paths.get(workDir.toString(), "/etc/org.apache.karaf.features.cfg");
+        List<String> featuresCfgFile = Files.readAllLines(featuresCfgFilePath);
+
+        assertTrue(featuresCfgFile.stream().anyMatch(line -> line.startsWith("featuresBoot")));
+
+        for (String feature : expectedFeatures) {
+            assertTrue(featuresCfgFile.stream().anyMatch(line -> line.contains(feature)));
+        }
+    }
+
     @Test
     public void testPidsToExtract() {
         String pidsToExtract = "\n" +
@@ -75,7 +123,7 @@ public class BuilderTest {
         assertThat(builder.getPidsToExtract().get(2), equalTo("*"));
     }
 
-    private static void recursiveDelete(Path path) throws IOException {
+    private void recursiveDelete(Path path) throws IOException {
         if (Files.exists(path)) {
             if (Files.isDirectory(path)) {
                 try (DirectoryStream<Path> children = Files.newDirectoryStream(path)) {
@@ -87,5 +135,4 @@ public class BuilderTest {
             Files.delete(path);
         }
     }
-
 }
diff --git a/profile/src/test/resources/repo/foo/qux/1.0/qux-1.0-features.xml b/profile/src/test/resources/repo/foo/qux/1.0/qux-1.0-features.xml
new file mode 100644
index 0000000000..3463591b80
--- /dev/null
+++ b/profile/src/test/resources/repo/foo/qux/1.0/qux-1.0-features.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<features name="qux-repo" xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
+    <feature name="qux-feature" />
+    <feature name="qux-feature2" />
+    <feature name="another-feature" />
+</features>
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java
index 592bf88359..d7b106104c 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java
@@ -212,6 +212,15 @@ public class AssemblyMojo extends MojoSupport {
      */
     @Parameter
     private List<String> bootFeatures;
+
+    /**
+     * List of features from runtime-scope features XML files and KARs to be installed into system repo
+     * and listed in featuresBoot property in etc/org.apache.karaf.features.cfg. These will be installed
+     * before {@link this#bootFeatures}. They will be wrapped in parentheses in featuresBoot.
+     */
+    @Parameter
+    private List<String> firstStageBootFeatures;
+
     /**
      * List of features from provided-scope features XML files and KARs to be installed into system repo
      * and not mentioned elsewhere.
@@ -580,6 +589,7 @@ public class AssemblyMojo extends MojoSupport {
         builder.defaultStage(Builder.Stage.Boot)
                 .kars(toArray(bootKars))
                 .repositories(bootFeatures.isEmpty() && bootProfiles.isEmpty() && installAllFeaturesByDefault, toArray(bootRepositories))
+                .firstStageBootFeatures(toArray(firstStageBootFeatures))
                 .features(toArray(bootFeatures))
                 .bundles(toArray(bootBundles))
                 .profiles(toArray(bootProfiles));
@@ -905,6 +915,7 @@ public class AssemblyMojo extends MojoSupport {
         blacklistedBundles = nonNullList(blacklistedBundles);
         startupFeatures = nonNullList(startupFeatures);
         bootFeatures = nonNullList(bootFeatures);
+        firstStageBootFeatures = nonNullList(firstStageBootFeatures);
         installedFeatures = nonNullList(installedFeatures);
         blacklistedFeatures = nonNullList(blacklistedFeatures);
         startupProfiles = nonNullList(startupProfiles);