From eb0a8320afb40d430b8ca0dc0d835a6b0680e890 Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Fri, 7 Aug 2026 10:09:14 +0200 Subject: [PATCH 1/6] SLING-13293 - Support setting ranking header for bundled script bundles Co-Authored-By: Claude Opus 4.8 --- README.md | 3 +++ .../plugin/bnd/BundledScriptsScannerPlugin.java | 17 +++++++++++++++++ .../plugin/maven/MetadataMojo.java | 15 +++++++++++++++ .../plugin/processor/Constants.java | 2 ++ src/site/markdown/usage.md.vm | 14 ++++++++++++++ .../plugin/AbstractPluginTest.java | 3 +++ .../scriptingbundle/plugin/PluginExecution.java | 8 +++++++- .../bnd/BundledScriptsScannerPluginTest.java | 6 ++++-- .../plugin/maven/MetadataMojoTest.java | 8 ++++---- src/test/resources/project-2/bnd.bnd | 3 ++- src/test/resources/project-2/pom.xml | 1 + 11 files changed, 72 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 24a8ce9..128a92e 100644 --- a/README.md +++ b/README.md @@ -13,4 +13,7 @@ Sling application. When executed, the plugin will define two project properties `org.apache.sling.scriptingbundle.maven.plugin.Provide-Capability`) which can be used to populate the corresponding bundle headers. +An optional `serviceRanking` can be configured to apply a service ranking to all bundled +scripts in the bundle via the `Sling-Bundled-Scripts-Ranking` bundle header. + For more details head over to the documentation page from https://sling.apache.org/components/scriptingbundle-maven-plugin/. diff --git a/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java b/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java index d7893cc..1e33b5d 100644 --- a/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java +++ b/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java @@ -113,6 +113,11 @@ public boolean analyzeJar(Analyzer analyzer) throws Exception { requiredCapabilities = requiredCapabilitiesDefinition; } analyzer.set(aQute.bnd.osgi.Constants.REQUIRE_CAPABILITY, requiredCapabilities); + + Integer serviceRanking = getConfiguredServiceRanking(); + if (serviceRanking != null) { + analyzer.set(Constants.SLING_BUNDLED_SCRIPTS_RANKING_HEADER, serviceRanking.toString()); + } return false; } @@ -198,6 +203,18 @@ private boolean getMissingRequirementsOptional() { return true; } + private Integer getConfiguredServiceRanking() { + String serviceRankingString = pluginProperties.get(Constants.BND_SERVICE_RANKING); + if (StringUtils.isNotEmpty(serviceRankingString)) { + try { + return Integer.valueOf(serviceRankingString.trim()); + } catch (NumberFormatException e) { + logger.error(String.format("Invalid service ranking: %s.", serviceRankingString)); + } + } + return null; + } + private Stream walkPath(Path path, Set includes, Set excludes) throws IOException { return Files.walk(path).filter(file -> { boolean include = includes.isEmpty(); diff --git a/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java b/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java index 1a562e4..1b7d723 100644 --- a/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java +++ b/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java @@ -175,6 +175,17 @@ public class MetadataMojo extends AbstractMojo { @Parameter(property = "scriptingbundle.missingRequirementsOptional", defaultValue = "true") private boolean missingRequirementsOptional = true; + /** + * When set, the given numeric value is exposed via the {@code org.apache.sling.scriptingbundle.maven.plugin.Sling-Bundled-Scripts-Ranking} + * Maven project property, which can be used to generate the {@code Sling-Bundled-Scripts-Ranking} OSGi bundle header. That header + * applies globally to all scripts in the bundle and allows influencing the service ranking of the servlets registered for the + * bundled scripts. When not set, the property is not generated. + * + * @since 0.6.0 + */ + @Parameter(property = "scriptingbundle.serviceRanking") + private Integer serviceRanking; + private Capabilities capabilities; public void execute() { @@ -236,6 +247,10 @@ public void execute() { providedCapabilitiesDefinition); project.getProperties().put("org.apache.sling.scriptingbundle.maven.plugin." + org.osgi.framework.Constants.REQUIRE_CAPABILITY, requiredCapabilitiesDefinition); + if (serviceRanking != null) { + project.getProperties().put("org.apache.sling.scriptingbundle.maven.plugin." + Constants.SLING_BUNDLED_SCRIPTS_RANKING_HEADER, + serviceRanking.toString()); + } } catch (IOException e) { logger.error("Unable to generate working directory.", e); } diff --git a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/Constants.java b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/Constants.java index 0c38ba8..fcd8962 100644 --- a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/Constants.java +++ b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/Constants.java @@ -53,7 +53,9 @@ private Constants() {} public static final String BND_SCRIPT_ENGINE_MAPPINGS = "scriptEngineMappings"; public static final String BND_SEARCH_PATHS = "searchPaths"; public static final String BND_MISSING_REQUIREMENTS_OPTIONAL = "missingRequirementsOptional"; + public static final String BND_SERVICE_RANKING = "serviceRanking"; + public static final String SLING_BUNDLED_SCRIPTS_RANKING_HEADER = "Sling-Bundled-Scripts-Ranking"; public static final String SLING_RESOURCE_SUPER_TYPE_XML_LOCAL_NAME = "resourceSuperType"; public static final String SLING_REQUIRED_RESOURCE_TYPES = "sling:requiredResourceTypes"; public static final String SLING_REQUIRED_RESOURCE_TYPES_XML_LOCAL_NAME = "requiredResourceTypes"; diff --git a/src/site/markdown/usage.md.vm b/src/site/markdown/usage.md.vm index 2cdaa10..a860951 100644 --- a/src/site/markdown/usage.md.vm +++ b/src/site/markdown/usage.md.vm @@ -111,3 +111,17 @@ writing instructions of another plugin like the `maven-bundle-plugin`: The `osgi.extender` requirement is mandatory to have the bundle wired up to the Apache Sling Servlets Resolver, but this should be manually defined by the developers, so that their bundle is correctly wired up to whatever version of the Servlets Resolver is available on the destination platform. + +$h3 Setting a service ranking for the bundled scripts + +Starting with version 0.6.0, a numeric `serviceRanking` can be configured. It is applied globally to all scripts in the bundle and +influences the service ranking of the servlets that the Apache Sling Servlets Resolver registers for the bundled scripts. When used as a +bnd plugin, the ranking is written directly into the `Sling-Bundled-Scripts-Ranking` bundle header. When used as a Maven plugin, the value +is exposed via the `org.apache.sling.scriptingbundle.maven.plugin.Sling-Bundled-Scripts-Ranking` project property, which has to be added +to the manifest writing instructions of the plugin that generates the bundle, e.g.: + +``` + + ${org.apache.sling.scriptingbundle.maven.plugin.Sling-Bundled-Scripts-Ranking} + +``` diff --git a/src/test/java/org/apache/sling/scriptingbundle/plugin/AbstractPluginTest.java b/src/test/java/org/apache/sling/scriptingbundle/plugin/AbstractPluginTest.java index ee5adb2..ec643f6 100644 --- a/src/test/java/org/apache/sling/scriptingbundle/plugin/AbstractPluginTest.java +++ b/src/test/java/org/apache/sling/scriptingbundle/plugin/AbstractPluginTest.java @@ -19,6 +19,7 @@ package org.apache.sling.scriptingbundle.plugin; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.util.Arrays; @@ -31,6 +32,7 @@ import org.apache.sling.scriptingbundle.plugin.capability.ProvidedResourceTypeCapability; import org.apache.sling.scriptingbundle.plugin.capability.ProvidedScriptCapability; import org.apache.sling.scriptingbundle.plugin.capability.RequiredResourceTypeCapability; +import org.apache.sling.scriptingbundle.plugin.processor.Constants; import org.junit.Test; import org.osgi.framework.Version; import org.osgi.framework.VersionRange; @@ -158,6 +160,7 @@ public void testProject2() throws Exception { PluginExecution execution = executePluginOnProject("project-2"); Capabilities capabilities = execution.getCapabilities(); Map scriptEngineMappings = execution.getScriptEngineMappings(); + assertEquals("100", execution.getHeaderValue(Constants.SLING_BUNDLED_SCRIPTS_RANKING_HEADER)); Set pExpected = new HashSet<>(Arrays.asList( ProvidedResourceTypeCapability.builder().withResourceType("libs/sling/test").withScriptEngine("thymeleaf") .withScriptExtension("html").build(), diff --git a/src/test/java/org/apache/sling/scriptingbundle/plugin/PluginExecution.java b/src/test/java/org/apache/sling/scriptingbundle/plugin/PluginExecution.java index 8c17036..c1d2374 100644 --- a/src/test/java/org/apache/sling/scriptingbundle/plugin/PluginExecution.java +++ b/src/test/java/org/apache/sling/scriptingbundle/plugin/PluginExecution.java @@ -19,17 +19,20 @@ package org.apache.sling.scriptingbundle.plugin; import java.util.Map; +import java.util.function.Function; import org.apache.sling.scriptingbundle.plugin.capability.Capabilities; public class PluginExecution { private final Capabilities capabilities; private final Map scriptEngineMappings; + private final Function valueGetter; - public PluginExecution(Capabilities capabilities, Map scriptEngineMappings) { + public PluginExecution(Capabilities capabilities, Map scriptEngineMappings, Function valueGetter) { super(); this.capabilities = capabilities; this.scriptEngineMappings = scriptEngineMappings; + this.valueGetter = valueGetter; } public Capabilities getCapabilities() { @@ -40,4 +43,7 @@ public Map getScriptEngineMappings() { return scriptEngineMappings; } + public String getHeaderValue(String key) { + return valueGetter.apply(key); + } } diff --git a/src/test/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPluginTest.java b/src/test/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPluginTest.java index 12a2976..7170fdc 100644 --- a/src/test/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPluginTest.java +++ b/src/test/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPluginTest.java @@ -25,6 +25,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.function.Function; import java.util.jar.Manifest; import org.apache.commons.io.FileUtils; @@ -66,8 +67,9 @@ public PluginExecution executePluginOnProject(String projectName) throws Excepti try (Builder builder = prepareBuilder(projectName)) { BundledScriptsScannerPlugin plugin = builder.getPlugin(BundledScriptsScannerPlugin.class); assertNotNull(plugin); - builder.build(); - return new PluginExecution(plugin.getCapabilities(), plugin.getScriptEngineMappings()); + Jar jar = builder.build(); + Function headerGetter = jar.getManifest().getMainAttributes()::getValue; + return new PluginExecution(plugin.getCapabilities(), plugin.getScriptEngineMappings(), headerGetter); } } diff --git a/src/test/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojoTest.java b/src/test/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojoTest.java index 7b1327e..f6524e0 100644 --- a/src/test/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojoTest.java +++ b/src/test/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojoTest.java @@ -20,9 +20,7 @@ import java.io.File; import java.nio.file.Paths; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; +import java.util.function.Function; import org.apache.commons.io.FileUtils; import org.apache.maven.execution.MavenSession; @@ -68,7 +66,9 @@ private static class MojoProject { public PluginExecution executePluginOnProject(String projectName) throws Exception { MojoProject mojoProject = getMojoProject(projectName); mojoProject.mojo.execute(); - return new PluginExecution(mojoProject.mojo.getCapabilities(), mojoProject.mojo.getScriptEngineMappings()); + Function propertyGetter = key -> mojoProject.project.getProperties() + .getProperty("org.apache.sling.scriptingbundle.maven.plugin." + key); + return new PluginExecution(mojoProject.mojo.getCapabilities(), mojoProject.mojo.getScriptEngineMappings(), propertyGetter); } @Override diff --git a/src/test/resources/project-2/bnd.bnd b/src/test/resources/project-2/bnd.bnd index fe12e69..d242650 100644 --- a/src/test/resources/project-2/bnd.bnd +++ b/src/test/resources/project-2/bnd.bnd @@ -16,4 +16,5 @@ # under the License. -plugin: org.apache.sling.scriptingbundle.plugin.bnd.BundledScriptsScannerPlugin; \ scriptEngineMappings="html:thymeleaf,js:rhino"; \ - searchPaths=/bin + searchPaths=/bin; \ + serviceRanking=100 diff --git a/src/test/resources/project-2/pom.xml b/src/test/resources/project-2/pom.xml index d8aa4ca..10b0254 100644 --- a/src/test/resources/project-2/pom.xml +++ b/src/test/resources/project-2/pom.xml @@ -40,6 +40,7 @@ thymeleaf rhino + 100 From 6eb122f78b96c3e7280c024eb4b50ff86f852fec Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Fri, 7 Aug 2026 16:01:22 +0200 Subject: [PATCH 2/6] trivial: remove java 13, add 17 and 21 --- .sling-module.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.sling-module.json b/.sling-module.json index b83f728..63f09b6 100644 --- a/.sling-module.json +++ b/.sling-module.json @@ -1,5 +1,5 @@ { "jenkins": { - "jdks": [8, 11, 13] + "jdks": [8, 11, 17, 21] } } From 8b53f28337ae100ea25b963c22425bd6cc073a13 Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Fri, 7 Aug 2026 16:19:20 +0200 Subject: [PATCH 3/6] update spotbugs and fix spotbugs errors --- pom.xml | 2 +- .../plugin/bnd/BundledScriptsScannerPlugin.java | 5 ++++- .../sling/scriptingbundle/plugin/maven/MetadataMojo.java | 5 ++++- .../plugin/processor/filevault/VaultContentXmlReader.java | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 5d351dd..705cfde 100644 --- a/pom.xml +++ b/pom.xml @@ -108,7 +108,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.3.0 + 4.10.3.0 Max true diff --git a/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java b/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java index 1e33b5d..aa914c5 100644 --- a/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java +++ b/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java @@ -79,7 +79,10 @@ public boolean analyzeJar(Analyzer analyzer) throws Exception { try { if (!Files.isDirectory(file)) { Path workingCopy = Paths.get(workDirectory.toString(), sourceDirectoryPath.relativize(file).toString()); - Files.createDirectories(workingCopy.getParent()); + Path parentDir = workingCopy.getParent(); + if (parentDir != null) { + Files.createDirectories(parentDir); + } Files.copy(file, workingCopy, StandardCopyOption.REPLACE_EXISTING); } } catch (IOException e) { diff --git a/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java b/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java index 1b7d723..b6d54dd 100644 --- a/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java +++ b/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java @@ -210,7 +210,10 @@ public void execute() { try { if (!Files.isDirectory(file)) { Path workingCopy = workDirectory.resolve(sourceDirectoryPath.relativize(file)); - Files.createDirectories(workingCopy.getParent()); + Path parentDir = workingCopy.getParent(); + if (parentDir != null) { + Files.createDirectories(parentDir); + } Files.copy(file, workingCopy, StandardCopyOption.REPLACE_EXISTING); } } catch (IOException e) { diff --git a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/filevault/VaultContentXmlReader.java b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/filevault/VaultContentXmlReader.java index edee6bc..ddb286e 100644 --- a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/filevault/VaultContentXmlReader.java +++ b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/filevault/VaultContentXmlReader.java @@ -47,7 +47,7 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; -public class VaultContentXmlReader { +public final class VaultContentXmlReader { private static final DocumentBuilderFactory documentBuilderFactory; From c28307ef4b8de9ffbc746729b92e45f48bda3f26 Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Fri, 7 Aug 2026 16:21:57 +0200 Subject: [PATCH 4/6] update maven version to 3.6.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 705cfde..3c7e034 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 8 - 3.6.0 + 3.6.3 12344664,12347157,12348422,12350010,12350474,12350606 ${project.artifactId}-archives/${project.artifactId}-LATEST 2021-12-16T14:04:46Z From df9c918dd57c2b6ef2718b5b8a39b254d91f9110 Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Fri, 7 Aug 2026 16:34:03 +0200 Subject: [PATCH 5/6] don't build on java 8 --- .sling-module.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.sling-module.json b/.sling-module.json index 63f09b6..966a2fe 100644 --- a/.sling-module.json +++ b/.sling-module.json @@ -1,5 +1,5 @@ { "jenkins": { - "jdks": [8, 11, 17, 21] + "jdks": [11, 17, 21] } } From 9b855dd1e706edaf6e3c03d4dfe4022e48b052ba Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Fri, 7 Aug 2026 16:53:31 +0200 Subject: [PATCH 6/6] update maven version to latest, add previously transitive dependencies, set explicit scopes --- pom.xml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3c7e034..9219e04 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 8 - 3.6.3 + 3.9.16 12344664,12347157,12348422,12350010,12350474,12350606 ${project.artifactId}-archives/${project.artifactId}-LATEST 2021-12-16T14:04:46Z @@ -167,23 +167,28 @@ org.jetbrains annotations + provided org.apache.maven maven-plugin-api + compile org.apache.maven maven-model + compile org.apache.maven maven-core + compile org.apache.maven maven-compat + compile org.apache.maven.plugin-tools @@ -191,6 +196,18 @@ 3.4 provided + + org.apache.commons + commons-lang3 + 3.20.0 + compile + + + commons-io + commons-io + 2.22.0 + compile + org.osgi org.osgi.framework