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:32 UTC
[sling-org-apache-sling-feature-analyser] 01/01: SLING-10285 add
analyser to validate that feature id matches one of a given set
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;
- }
- }
}