This is an automated email from the ASF dual-hosted git repository.
angela pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-analyser.git
The following commit(s) were added to refs/heads/master by this push:
new 1827150 SLING-12346 : Create service-user-mapping analyser (#45)
1827150 is described below
commit 1827150128542a08b14393e8d4857efc38a47e75
Author: anchela <[email protected]>
AuthorDate: Wed Jun 5 18:11:48 2024 +0200
SLING-12346 : Create service-user-mapping analyser (#45)
* SLING-12346 : Create service-user-mapping analyser (initial draft)
* SLING-12346 : Create service-user-mapping analyser (replace log output
with configurationWarning)
* SLING-12346 : Create service-user-mapping analyser (use separate short id
instead of PID)
* SLING-12346 : Create service-user-mapping analyser (simplifying Mapping
and avoiding import of o.a.s.serviceusermapping.Mapping for utilities that are
not needed to detect usage of deprecated mapping)
* SLING-12346 : Create service-user-mapping analyser (removing unused
dependency)
---
pom.xml | 6 +
.../task/impl/CheckServiceUserMapping.java | 136 +++++++++++++++++++
...apache.sling.feature.analyser.task.AnalyserTask | 1 +
.../task/impl/CheckServiceUserMappingTest.java | 147 +++++++++++++++++++++
4 files changed, 290 insertions(+)
diff --git a/pom.xml b/pom.xml
index 5466ef4..21ce457 100644
--- a/pom.xml
+++ b/pom.xml
@@ -147,6 +147,12 @@
<version>1.11.8</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.jetbrains</groupId>
+ <artifactId>annotations</artifactId>
+ <version>24.1.0</version>
+ <scope>provided</scope>
+ </dependency>
<!-- Content-Package check -->
<dependency>
diff --git
a/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckServiceUserMapping.java
b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckServiceUserMapping.java
new file mode 100644
index 0000000..7be354a
--- /dev/null
+++
b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckServiceUserMapping.java
@@ -0,0 +1,136 @@
+/*
+ * 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.feature.analyser.task.impl;
+
+import org.apache.sling.feature.Configuration;
+import org.apache.sling.feature.Configurations;
+import org.apache.sling.feature.analyser.task.AnalyserTask;
+import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.util.converter.Converters;
+
+public class CheckServiceUserMapping implements AnalyserTask {
+
+ static final String SERVICE_USER_MAPPING_PID =
"org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl";
+
+ static final String FACTORY_PID =
"org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended";
+
+ static final String USER_MAPPING = "user.mapping";
+
+ static final String CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS =
"warnOnlyForDeprecatedMappings";
+ static final String CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS_DEFAULT =
Boolean.FALSE.toString();
+
+ @Override
+ public String getName() {
+ return "Service User Mapping Check";
+ }
+
+ @Override
+ public String getId() {
+ return "serviceusermapping";
+ }
+
+ @Override
+ public void execute(final AnalyserTaskContext ctx) {
+ final boolean warnOnlyForDeprecation =
Boolean.parseBoolean(ctx.getConfiguration().getOrDefault(CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS,
CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS_DEFAULT));
+
+ // configuration
+ Configurations configurations = ctx.getFeature().getConfigurations();
+ final Configuration cfg =
configurations.getConfiguration(SERVICE_USER_MAPPING_PID);
+ if (cfg != null) {
+ check(ctx, cfg, warnOnlyForDeprecation);
+ }
+ for (final Configuration c :
configurations.getFactoryConfigurations(FACTORY_PID)) {
+ check(ctx, c, warnOnlyForDeprecation);
+ }
+ }
+
+ private static void check(final AnalyserTaskContext ctx, final
Configuration cfg, final boolean warnOnlyForDeprecation) {
+ final Object val = cfg.getConfigurationProperties().get(USER_MAPPING);
+ if (val != null) {
+ final String[] mappings =
Converters.standardConverter().convert(val).to(String[].class);
+ for (final String spec : mappings) {
+ check(ctx, cfg, spec, warnOnlyForDeprecation);
+ }
+ }
+ }
+
+ private static void check(final @NotNull AnalyserTaskContext ctx, final
@NotNull Configuration cfg, final @Nullable String spec, final boolean
warnOnlyForDeprecation) {
+ final String id = cfg.getPid();
+ if (spec == null || spec.trim().isEmpty()) {
+ ctx.reportConfigurationWarning(cfg, "Ignoring empty mapping in " +
id);
+ return;
+ }
+
+ final Mapping mapping = Mapping.parse(spec, ctx, cfg);
+ if (mapping == null) {
+ ctx.reportConfigurationError(cfg, String.format("Invalid service
user mapping '%s' from %s", spec, id));
+ } else if (mapping.isDeprecated()) {
+ String msg = String.format("Deprecated service user mapping '%s'
from %s", spec, id);
+ if (warnOnlyForDeprecation) {
+ ctx.reportConfigurationWarning(cfg, msg);
+ } else {
+ ctx.reportConfigurationError(cfg, msg);
+ }
+ }
+ }
+
+ /**
+ * Parsing copied from sling-org-apache-sling-serviceusermapper.Mapping
+ */
+ private static class Mapping {
+
+ private final boolean isDeprecated;
+
+ private static @Nullable Mapping parse(@NotNull final String spec,
@NotNull final AnalyserTaskContext ctx, @NotNull final Configuration cfg) {
+ final int colon = spec.indexOf(':');
+ final int equals = spec.indexOf('=');
+
+ if (colon == 0 || equals <= 0) {
+ ctx.reportConfigurationWarning(cfg, "Invalid service user
mapping: serviceName is required");
+ return null;
+ } else if (equals == spec.length() - 1) {
+ ctx.reportConfigurationWarning(cfg, "Invalid service user
mapping: userName or principalNames is required");
+ return null;
+ } else if (colon + 1 == equals) {
+ ctx.reportConfigurationWarning(cfg, "Invalid service user
mapping: serviceInfo must not be empty");
+ return null;
+ }
+
+ final String userName;
+ String s = spec.substring(equals + 1);
+ if (s.charAt(0) == '[' && s.charAt(s.length() - 1) == ']') {
+ userName = null;
+ } else {
+ userName = s;
+ }
+ return new Mapping(userName != null);
+ }
+
+ private Mapping(boolean isDeprecated) {
+ this.isDeprecated = isDeprecated;
+ }
+
+ private boolean isDeprecated() {
+ return isDeprecated;
+ }
+ }
+}
+
diff --git
a/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask
b/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask
index 283edc8..86874e4 100644
---
a/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask
+++
b/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask
@@ -15,3 +15,4 @@ org.apache.sling.feature.analyser.task.impl.CheckRepoinit
org.apache.sling.feature.analyser.task.impl.CheckRequirementsCapabilities
org.apache.sling.feature.analyser.task.impl.CheckUnusedBundles
org.apache.sling.feature.analyser.task.impl.CheckFeatureId
+org.apache.sling.feature.analyser.task.impl.CheckServiceUserMapping
diff --git
a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckServiceUserMappingTest.java
b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckServiceUserMappingTest.java
new file mode 100644
index 0000000..3e4bfb8
--- /dev/null
+++
b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckServiceUserMappingTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.feature.analyser.task.impl;
+
+import org.apache.sling.feature.Configuration;
+import org.apache.sling.feature.analyser.task.AnalyserTask;
+import org.junit.Before;
+import org.junit.Test;
+
+import static
org.apache.sling.feature.analyser.task.impl.CheckServiceUserMapping.CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS;
+import static
org.apache.sling.feature.analyser.task.impl.CheckServiceUserMapping.CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS_DEFAULT;
+import static
org.apache.sling.feature.analyser.task.impl.CheckServiceUserMapping.USER_MAPPING;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class CheckServiceUserMappingTest {
+
+ public static final String[] DEPRECATED_STATEMENTS = {
+ "org.apache.sling.test_service:sub_service=sling-reader-service",
+ "org.apache.sling.test_service=sling-reader-service"};
+ public static final String[] VALID_STATEMENTS = {
+
"org.apache.sling.test_service:sub_service=[sling-reader-service]",
+ "org.apache.sling.test_service=[sling-reader-service,
sling-writer-service],\n" +
+
"org.apache.sling.test_service:sub_service=[sling-reader-service]"};
+ public static final String[] INVALID_STATEMENTS = {
+ ":subservice=[sling-reader-service]",
+ "=[sling-reader-service]",
+ "org.apache.sling.test_service:sub_service=",
+ "org.apache.sling.test_service:=[sling-reader-service]",
+ "org.apache.sling.test_service",
+ ":=[sling-reader-service]"};
+
+ private AnalyserTaskContextImpl ctx;
+ private AnalyserTask task;
+
+ @Before
+ public void setUp() throws Exception {
+ ctx = new AnalyserTaskContextImpl();
+ task = new CheckServiceUserMapping();
+ task.execute(ctx);
+ assertTrue(ctx.getErrors().isEmpty());
+ }
+
+ @Test
+ public void testId() {
+ assertEquals("serviceusermapping", task.getId());
+ }
+
+ @Test
+ public void testName() {
+ assertEquals("Service User Mapping Check", task.getName());
+ }
+
+ @Test
+ public void testValidConfiguration() throws Exception {
+ // create valid configuration
+ for (String statement : VALID_STATEMENTS) {
+ final Configuration cfg = new
Configuration(CheckServiceUserMapping.SERVICE_USER_MAPPING_PID);
+ cfg.getProperties().put(USER_MAPPING, statement);
+ ctx.getFeature().getConfigurations().add(cfg);
+
+ task.execute(ctx);
+ assertTrue(ctx.getErrors().isEmpty());
+ }
+ }
+
+ @Test
+ public void testValidFactoryConfiguration() throws Exception {
+ // create valid configuration
+ for (String statement : VALID_STATEMENTS) {
+ final Configuration cfg = new
Configuration(CheckServiceUserMapping.FACTORY_PID.concat("~name"));
+ cfg.getProperties().put(USER_MAPPING, statement);
+ ctx.getFeature().getConfigurations().add(cfg);
+
+ task.execute(ctx);
+ assertTrue(ctx.getErrors().isEmpty());
+ }
+ }
+
+ @Test
+ public void testEmptyConfiguration() throws Exception {
+ final Configuration cfg = new
Configuration(CheckServiceUserMapping.FACTORY_PID.concat("~name"));
+ cfg.getProperties().put(USER_MAPPING, "");
+ ctx.getFeature().getConfigurations().add(cfg);
+
+ task.execute(ctx);
+ assertTrue(ctx.getErrors().isEmpty());
+ }
+
+ @Test
+ public void testInvalidConfiguration() throws Exception {
+ for (String statement : INVALID_STATEMENTS) {
+ final Configuration cfg = new
Configuration(CheckServiceUserMapping.FACTORY_PID.concat("~name"));
+ cfg.getProperties().put(USER_MAPPING, statement);
+ ctx.getFeature().getConfigurations().add(cfg);
+ }
+
+ task.execute(ctx);
+ assertEquals(6, ctx.getErrors().size());
+ }
+
+ @Test
+ public void testDeprecatedMappingInvalied() throws Exception {
+
assertFalse(Boolean.parseBoolean(ctx.getConfiguration().getOrDefault(CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS,
CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS_DEFAULT)));
+
+ for (String statement : DEPRECATED_STATEMENTS) {
+ final Configuration cfg = new
Configuration(CheckServiceUserMapping.FACTORY_PID.concat("~name"));
+ cfg.getProperties().put(USER_MAPPING, statement);
+ ctx.getFeature().getConfigurations().add(cfg);
+ }
+
+ task.execute(ctx);
+ assertEquals(2, ctx.getErrors().size());
+ }
+
+ @Test
+ public void testDeprecatedMappingWarnOnly() throws Exception {
+ ctx.putConfigurationValue(CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS,
Boolean.TRUE.toString());
+
+
assertTrue(Boolean.parseBoolean(ctx.getConfiguration().getOrDefault(CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS,
CFG_WARN_ONLY_FOR_DEPRECATED_MAPPINGS_DEFAULT)));
+ for (String statement : DEPRECATED_STATEMENTS) {
+ final Configuration cfg = new
Configuration(CheckServiceUserMapping.FACTORY_PID.concat("~name"));
+ cfg.getProperties().put(USER_MAPPING, statement);
+ ctx.getFeature().getConfigurations().add(cfg);
+ }
+
+ task.execute(ctx);
+ assertTrue(ctx.getErrors().isEmpty());
+ }
+}