You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2021/04/09 12:53:31 UTC

[sling-org-apache-sling-feature-analyser] branch feature/feature-id-analyser created (now fd09932)

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

kwin pushed a change to branch feature/feature-id-analyser
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-analyser.git.


      at fd09932  SLING-10285 add analyser to validate that feature id matches one of a given set

This branch includes the following new commits:

     new fd09932  SLING-10285 add analyser to validate that feature id matches one of a given set

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[sling-org-apache-sling-feature-analyser] 01/01: SLING-10285 add analyser to validate that feature id matches one of a given set

Posted by kw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/feature-id-analyser
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-analyser.git

commit fd099328e74a0b0ab7838e36952c23dadb128785
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Apr 9 14:53:16 2021 +0200

    SLING-10285 add analyser to validate that feature id matches one of a
    given set
---
 readme.md                                          |  12 +++
 .../feature/analyser/task/impl/CheckFeatureId.java |  93 ++++++++++++++++++
 ...apache.sling.feature.analyser.task.AnalyserTask |   1 +
 .../task/impl/AnalyserTaskContextImpl.java         | 109 +++++++++++++++++++++
 .../analyser/task/impl/CheckFeatureIdTest.java     |  52 ++++++++++
 .../analyser/task/impl/CheckRepoinitTest.java      |  75 --------------
 6 files changed, 267 insertions(+), 75 deletions(-)

diff --git a/readme.md b/readme.md
index 4a4d137..9f17ff9 100644
--- a/readme.md
+++ b/readme.md
@@ -32,6 +32,8 @@ The following analysers are defined:
 
 * `repoinit`: Checks the syntax of all repoinit sections.
 
+* `feature-id`: Checks if the used feature id matches one of the given Maven coordinates.
+
 Additional analysers in relation to Feature Model API Regions can be found here: https://github.com/apache/sling-org-apache-sling-feature-extension-apiregions
 
 For further documentation see: https://github.com/apache/sling-org-apache-sling-feature/blob/master/readme.md
@@ -49,3 +51,13 @@ This analyser requires additional configuration:
 `compare-extension` | extension name | If this configuration is absent, the feature's bundles are compared. Otherwise the extensions with the specified name are compared. These extensions must be of type `ARTIFACTS`.
 `compare-mode` | `SAME` or `DIFFERENT` | Whether the sections must be the same or must be different. Defaults to `SAME`.
 `compare-metadata` | `true` or `false` | Whether to include the artifact metadata in the comparison. Defaults to `false`.
+
+## `feature-id`
+
+This analyser checks that the feature id matches one of the given accepted feature ids. If it doesn't it will emit an error.
+
+This analyser requires additional configuration:
+
+ Configuration key | Allowed values | Description 
+ ----- | ----- | -----
+`accepted-feature-ids` | comma-separated list of Maven IDs | The Maven ID/coordinates have the format `groupId:artifactId[:packaging[:classifier]]:version`. Each item is either a string which must be equal to the according item of the feature id, or a `*` which acts as wildcard (i.e. everything matches).
diff --git a/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckFeatureId.java b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckFeatureId.java
new file mode 100644
index 0000000..050db36
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckFeatureId.java
@@ -0,0 +1,93 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.analyser.task.AnalyserTask;
+import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+
+public class CheckFeatureId implements AnalyserTask {
+
+    static final String CONFIG_KEY_ACCEPTED_FEATURE_IDS = "accepted-feature-ids";
+
+    @Override
+    public String getId() {
+        return "feature-id";
+    }
+
+    @Override
+    public String getName() {
+        return "Restrict feature id format";
+    }
+
+    @Override
+    public void execute(AnalyserTaskContext ctx) throws Exception {
+        Map<String, String> cfg = ctx.getConfiguration();
+        String acceptedFeatureIds = cfg.get(CONFIG_KEY_ACCEPTED_FEATURE_IDS);
+        if (acceptedFeatureIds == null) {
+            // this is a comma-separated list of accepted 
+            throw new IllegalArgumentException("Missing 'accepted-feature-ids' configuration for feature-id analyser.");
+        }
+        Collection<ArtifactId> acceptedArtifactIds = new ArrayList<>();
+        for (String acceptedFeatureId : acceptedFeatureIds.split(",")) {
+            try {
+                acceptedArtifactIds.add(ArtifactId.fromMvnId(acceptedFeatureId));
+            } catch (IllegalArgumentException e) {
+                throw new IllegalArgumentException("Invalid 'accepted-feature-ids' configuration for feature-id analyser, element '" + acceptedFeatureId + "' is not a valid maven coordinate string in format 'groupId:artifactId[:packaging[:classifier]]:version'", e);
+            }
+        }
+        if (!matchesAnyOf(ctx.getFeature().getId(), acceptedArtifactIds)) {
+            ctx.reportError("Feature " + ctx.getFeature().getId() + " does not match any of the accepted feature ids ");
+        }
+    }
+
+    static boolean matchesAnyOf(ArtifactId artifactId, Collection<ArtifactId> expectedArtifactIds) {
+        for (ArtifactId expectedArtifactId : expectedArtifactIds) {
+            if (matches(artifactId, expectedArtifactId)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static boolean matches(ArtifactId artifactId, ArtifactId expectedArtifactId) {
+        if (!expectedArtifactId.getGroupId().equals(artifactId.getGroupId()) && !expectedArtifactId.getGroupId().equals("*")) {
+            return false;
+        }
+        if (!expectedArtifactId.getArtifactId().equals(artifactId.getArtifactId()) && !expectedArtifactId.getArtifactId().equals("*")) {
+            return false;
+        }
+        if (!expectedArtifactId.getVersion().equals(artifactId.getVersion()) && !expectedArtifactId.getVersion().equals("*")) {
+            return false;
+        }
+        if (!expectedArtifactId.getType().equals(artifactId.getType()) && !expectedArtifactId.getVersion().equals("*")) {
+            return false;
+        }
+        // classifier is optional
+        if (expectedArtifactId.getClassifier() != null && !expectedArtifactId.getClassifier().equals(artifactId.getClassifier()) && !expectedArtifactId.getClassifier().equals("*")) {
+            return false;
+        }
+        return true;
+    }
+
+}
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 9a0111e..503dc36 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
@@ -11,3 +11,4 @@ org.apache.sling.feature.analyser.task.impl.CheckDuplicateSymbolicName
 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
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/feature/analyser/task/impl/AnalyserTaskContextImpl.java b/src/test/java/org/apache/sling/feature/analyser/task/impl/AnalyserTaskContextImpl.java
new file mode 100644
index 0000000..1ee90d2
--- /dev/null
+++ b/src/test/java/org/apache/sling/feature/analyser/task/impl/AnalyserTaskContextImpl.java
@@ -0,0 +1,109 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+import org.apache.sling.feature.builder.FeatureProvider;
+import org.apache.sling.feature.scanner.BundleDescriptor;
+import org.apache.sling.feature.scanner.FeatureDescriptor;
+
+public class AnalyserTaskContextImpl implements AnalyserTaskContext {
+
+    private final Feature f;
+    private final Map<String, String> configuration = new HashMap<>();
+
+    private final List<String> errors = new ArrayList<>();
+
+    public AnalyserTaskContextImpl() {
+        this("g:a:1");
+    }
+    
+    public AnalyserTaskContextImpl(String artifactId) {
+        f = new Feature(ArtifactId.parse(artifactId));
+    }
+
+    @Override
+    public Feature getFeature() {
+        return f;
+    }
+
+    @Override
+    public FeatureDescriptor getFeatureDescriptor() {
+        return null;
+    }
+
+    @Override
+    public BundleDescriptor getFrameworkDescriptor() {
+        return null;
+    }
+
+    @Override
+    public Map<String, String> getConfiguration() {
+        return configuration;
+    }
+
+    public void putConfigurationValue(String key, String value) {
+        configuration.put(key, value);
+    }
+
+    @Override
+    public FeatureProvider getFeatureProvider() {
+        return null;
+    }
+
+    @Override
+    public void reportWarning(String message) {
+    }
+
+    @Override
+    public void reportArtifactWarning(ArtifactId artifactId, String message) {
+
+    }
+
+    @Override
+    public void reportArtifactError(ArtifactId artifactId, String message) {
+        errors.add(message);
+    }
+
+    @Override
+    public void reportExtensionWarning(String extension, String message) {
+
+    }
+
+    @Override
+    public void reportExtensionError(String extension, String message) {
+        errors.add(message);
+    }
+
+    @Override
+    public void reportError(String message) {
+        errors.add(message);
+    }
+
+    public List<String> getErrors() {
+        return this.errors;
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckFeatureIdTest.java b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckFeatureIdTest.java
new file mode 100644
index 0000000..fdde3a8
--- /dev/null
+++ b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckFeatureIdTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.sling.feature.analyser.task.AnalyserTask;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CheckFeatureIdTest {
+
+    private AnalyserTaskContextImpl ctx;
+    private AnalyserTask task;
+
+    @Before
+    public void setUp() {
+        ctx = new AnalyserTaskContextImpl("myGroupId:myArtifactId:jar:myClassifier");
+        task = new CheckFeatureId();
+    }
+ 
+    @Test
+    public void testValidFeatureId() throws Exception {
+        ctx.getConfiguration().put(CheckFeatureId.CONFIG_KEY_ACCEPTED_FEATURE_IDS, "myGroupId:*:jar:myClassifier");
+        task.execute(ctx);
+        assertTrue(ctx.getErrors().isEmpty());
+    }
+
+    @Test
+    public void testInValidFeatureId() throws Exception {
+        ctx.getConfiguration().put(CheckFeatureId.CONFIG_KEY_ACCEPTED_FEATURE_IDS, "myGroupId:*:jar:myOtherClassifier");
+        task.execute(ctx);
+        assertEquals(1, ctx.getErrors().size());
+    }
+}
diff --git a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoinitTest.java b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoinitTest.java
index 0cf89bc..74a87c6 100644
--- a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoinitTest.java
+++ b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoinitTest.java
@@ -20,21 +20,11 @@ package org.apache.sling.feature.analyser.task.impl;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Configuration;
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionState;
 import org.apache.sling.feature.ExtensionType;
-import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.analyser.task.AnalyserTask;
-import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
-import org.apache.sling.feature.builder.FeatureProvider;
-import org.apache.sling.feature.scanner.BundleDescriptor;
-import org.apache.sling.feature.scanner.FeatureDescriptor;
 import org.junit.Test;
 
 public class CheckRepoinitTest {
@@ -104,69 +94,4 @@ public class CheckRepoinitTest {
         task.execute(ctx);
         assertEquals(1, ctx.getErrors().size());
     }
-
-    public static class AnalyserTaskContextImpl implements AnalyserTaskContext {
-
-        private final Feature f = new Feature(ArtifactId.parse("g:a:1"));
-
-        private final List<String> errors = new ArrayList<>();
-
-        @Override
-        public Feature getFeature() {
-            return f;
-        }
-
-        @Override
-        public FeatureDescriptor getFeatureDescriptor() {
-            return null;
-        }
-
-        @Override
-        public BundleDescriptor getFrameworkDescriptor() {
-            return null;
-        }
-
-        @Override
-        public Map<String, String> getConfiguration() {
-            return null;
-        }
-
-        @Override
-        public FeatureProvider getFeatureProvider() {
-            return null;
-        }
-
-        @Override
-        public void reportWarning(String message) {
-        }
-
-        @Override
-        public void reportArtifactWarning(ArtifactId artifactId, String message) {
-
-        }
-
-        @Override
-        public void reportArtifactError(ArtifactId artifactId, String message) {
-            errors.add(message);
-        }
-
-        @Override
-        public void reportExtensionWarning(String extension, String message) {
-
-        }
-
-        @Override
-        public void reportExtensionError(String extension, String message) {
-            errors.add(message);
-        }
-
-        @Override
-        public void reportError(String message) {
-            errors.add(message);
-        }
-
-        public List<String> getErrors() {
-            return this.errors;
-        }
-    }
 }