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());
+    }
+}

Reply via email to