You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by da...@apache.org on 2018/11/28 13:43:45 UTC
[sling-org-apache-sling-feature-analyser] branch master updated:
SLING-8137 Create an analyser that checks the order of API Regions
This is an automated email from the ASF dual-hosted git repository.
davidb 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 8b24c5d SLING-8137 Create an analyser that checks the order of API Regions
8b24c5d is described below
commit 8b24c5d0431f8288f982e16ff94a838fe6a14e72
Author: David Bosschaert <bo...@adobe.com>
AuthorDate: Wed Nov 28 13:39:45 2018 +0000
SLING-8137 Create an analyser that checks the order of API Regions
---
.../analyser/task/impl/CheckApiRegionsOrder.java | 122 ++++++++++++++++
...apache.sling.feature.analyser.task.AnalyserTask | 1 +
.../task/impl/CheckApiRegionsOrderTest.java | 156 +++++++++++++++++++++
3 files changed, 279 insertions(+)
diff --git a/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckApiRegionsOrder.java b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckApiRegionsOrder.java
new file mode 100644
index 0000000..cd7d6bc
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckApiRegionsOrder.java
@@ -0,0 +1,122 @@
+/*
+ * 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.Extension;
+import org.apache.sling.feature.Extensions;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.analyser.task.AnalyserTask;
+import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.json.Json;
+import javax.json.stream.JsonParser;
+import javax.json.stream.JsonParser.Event;
+
+public class CheckApiRegionsOrder implements AnalyserTask {
+ protected static final String API_REGIONS_KEY = "api-regions";
+
+ @Override
+ public String getId() {
+ return "api-regions-check-order";
+ }
+
+ @Override
+ public final void execute(AnalyserTaskContext ctx) throws Exception {
+ String order = ctx.getConfiguration().get("order");
+ Feature feature = ctx.getFeature();
+ if (feature == null) {
+ reportError(ctx, "No feature found. Illegal Analyser State.");
+ return;
+ }
+
+ if (order == null) {
+ reportError(ctx, "This analyser task must be configured: " + getId() + " for feature " + feature.getId());
+ reportError(ctx, "Must specify configuration key 'order'.");
+ return;
+ }
+
+ String[] sl = order.split("[,]");
+ List<String> prescribedOrder = new ArrayList<>();
+ for (String s : sl) {
+ s = s.trim();
+ if (s.length() > 0)
+ prescribedOrder.add(s);
+ }
+ if (prescribedOrder.size() == 0) {
+ reportError(ctx, "No regions declared in the 'order' configuration");
+ return;
+ }
+
+ // extract and check the api-regions
+ Extensions extensions = feature.getExtensions();
+ Extension apiRegionsExtension = extensions.getByName(API_REGIONS_KEY);
+ if (apiRegionsExtension == null) {
+ // no need to be analyzed
+ return;
+ }
+
+ String jsonRepresentation = apiRegionsExtension.getJSON();
+ if (jsonRepresentation == null || jsonRepresentation.isEmpty()) {
+ // no need to be analyzed
+ return;
+ }
+
+ int regionIdx = 0;
+ JsonParser parser = Json.createParser(new StringReader(jsonRepresentation));
+ while (parser.hasNext()) {
+ Event event = parser.next();
+ if (Event.KEY_NAME == event) {
+ switch (parser.getString()) {
+ case "name":
+ parser.next();
+ String name = parser.getString();
+ if (!prescribedOrder.contains(name)) {
+ reportError(ctx, "Region found with undeclared name: " + name);
+ return;
+ }
+ int prevIdx = regionIdx;
+ regionIdx = validateRegion(regionIdx, prescribedOrder, name);
+ if (regionIdx < 0) {
+ reportError(ctx, "Region '" + name + "' appears in the wrong order. It appears after '"
+ + prescribedOrder.get(prevIdx) + "'. Order of regions should be " + prescribedOrder);
+ }
+ }
+ }
+ }
+ }
+
+ private int validateRegion(int regionIdx, List<String> order, String name) {
+ for (int i=regionIdx; i<order.size(); i++) {
+ if (name.equals(order.get(i))) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private String getPrefix() {
+ return getId() + ": ";
+ }
+
+ private void reportError(AnalyserTaskContext ctx, String err) {
+ ctx.reportError(getPrefix() + err);
+ }
+}
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 72ad971..005b143 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
@@ -5,3 +5,4 @@ org.apache.sling.feature.analyser.task.impl.CheckRequirementsCapabilities
org.apache.sling.feature.analyser.task.impl.CheckApiRegions
org.apache.sling.feature.analyser.task.impl.CheckApiRegionsDependencies
org.apache.sling.feature.analyser.task.impl.CheckApiRegionsDuplicates
+org.apache.sling.feature.analyser.task.impl.CheckApiRegionsOrder
diff --git a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckApiRegionsOrderTest.java b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckApiRegionsOrderTest.java
new file mode 100644
index 0000000..65a7d88
--- /dev/null
+++ b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckApiRegionsOrderTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.ArtifactId;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CheckApiRegionsOrderTest {
+ @Test
+ public void testValidOrder() throws Exception {
+ CheckApiRegionsOrder caro = new CheckApiRegionsOrder();
+
+ Extension e = new Extension(ExtensionType.JSON, "api-regions", false);
+ e.setJSON("[{\"name\":\"deprecated\","
+ + "\"exports\": [\"a.b.c\"]},"
+ + "{\"name\":\"internal\","
+ + "\"exports\": [\"d.e.f\"]},"
+ + "{\"name\":\"internal\","
+ + "\"exports\": [\"g.h.i\"]}]");
+
+ Feature f = new Feature(ArtifactId.fromMvnId("a:b:1"));
+ f.getExtensions().add(e);
+
+ Map<String, String> cfgMap = new HashMap<>();
+ cfgMap.put("order", "deprecated, internal ");
+
+ AnalyserTaskContext ctx = Mockito.mock(AnalyserTaskContext.class);
+ Mockito.when(ctx.getConfiguration()).thenReturn(cfgMap);
+ Mockito.when(ctx.getFeature()).thenReturn(f);
+
+ caro.execute(ctx);
+ Mockito.verify(ctx, Mockito.never()).reportError(Mockito.anyString());
+ }
+
+ @Test
+ public void testInvalidOrder() throws Exception {
+ CheckApiRegionsOrder caro = new CheckApiRegionsOrder();
+
+ Extension e = new Extension(ExtensionType.JSON, "api-regions", false);
+ e.setJSON("[{\"name\":\"deprecated\","
+ + "\"exports\": [\"a.b.c\"]},"
+ + "{\"name\":\"internal\","
+ + "\"exports\": [\"d.e.f\"]},"
+ + "{\"name\":\"deprecated\","
+ + "\"exports\": [\"g.h.i\"]}]");
+
+ Feature f = new Feature(ArtifactId.fromMvnId("a:b:1"));
+ f.getExtensions().add(e);
+
+ Map<String, String> cfgMap = new HashMap<>();
+ cfgMap.put("order", "deprecated, internal ");
+
+ AnalyserTaskContext ctx = Mockito.mock(AnalyserTaskContext.class);
+ Mockito.when(ctx.getConfiguration()).thenReturn(cfgMap);
+ Mockito.when(ctx.getFeature()).thenReturn(f);
+
+ caro.execute(ctx);
+ Mockito.verify(ctx).reportError(Mockito.contains("wrong order"));
+ }
+
+ @Test
+ public void testInvalidRegion() throws Exception {
+ CheckApiRegionsOrder caro = new CheckApiRegionsOrder();
+
+ Extension e = new Extension(ExtensionType.JSON, "api-regions", false);
+ e.setJSON("[{\"name\":\"foo\"}]");
+
+ Feature f = new Feature(ArtifactId.fromMvnId("a:b:1"));
+ f.getExtensions().add(e);
+
+ Map<String, String> cfgMap = new HashMap<>();
+ cfgMap.put("order", "bar");
+
+ AnalyserTaskContext ctx = Mockito.mock(AnalyserTaskContext.class);
+ Mockito.when(ctx.getConfiguration()).thenReturn(cfgMap);
+ Mockito.when(ctx.getFeature()).thenReturn(f);
+
+ caro.execute(ctx);
+ Mockito.verify(ctx).reportError(Mockito.contains("undeclared"));
+ }
+
+ @Test
+ public void testNoExtensionsIsValid() throws Exception {
+ CheckApiRegionsOrder caro = new CheckApiRegionsOrder();
+
+ Map<String, String> cfgMap = new HashMap<>();
+ cfgMap.put("order", "deprecated, internal ");
+
+ AnalyserTaskContext ctx = Mockito.mock(AnalyserTaskContext.class);
+ Mockito.when(ctx.getConfiguration()).thenReturn(cfgMap);
+ Mockito.when(ctx.getFeature()).thenReturn(new Feature(ArtifactId.fromMvnId("a:b:1")));
+
+ caro.execute(ctx);
+ Mockito.verify(ctx, Mockito.never()).reportError(Mockito.anyString());
+ }
+
+ @Test
+ public void testEmptyOrder() throws Exception {
+ CheckApiRegionsOrder caro = new CheckApiRegionsOrder();
+
+ Map<String, String> cfgMap = new HashMap<>();
+ cfgMap.put("order", " ");
+
+ AnalyserTaskContext ctx = Mockito.mock(AnalyserTaskContext.class);
+ Mockito.when(ctx.getConfiguration()).thenReturn(cfgMap);
+ Mockito.when(ctx.getFeature()).thenReturn(new Feature(ArtifactId.fromMvnId("a:b:1")));
+
+ caro.execute(ctx);
+ Mockito.verify(ctx).reportError(Mockito.contains("No regions"));
+ }
+
+ @Test
+ public void testNoFeature() throws Exception {
+ CheckApiRegionsOrder caro = new CheckApiRegionsOrder();
+
+ AnalyserTaskContext ctx = Mockito.mock(AnalyserTaskContext.class);
+ Mockito.when(ctx.getConfiguration()).thenReturn(new HashMap<>());
+
+ caro.execute(ctx);
+ Mockito.verify(ctx).reportError(Mockito.contains("No feature"));
+ }
+
+ @Test
+ public void testNoOrderConfig() throws Exception {
+ CheckApiRegionsOrder caro = new CheckApiRegionsOrder();
+
+ AnalyserTaskContext ctx = Mockito.mock(AnalyserTaskContext.class);
+ Mockito.when(ctx.getConfiguration()).thenReturn(new HashMap<>());
+ Mockito.when(ctx.getFeature()).thenReturn(new Feature(ArtifactId.fromMvnId("a:b:1")));
+
+ caro.execute(ctx);
+ Mockito.verify(ctx).reportError(Mockito.contains("'order'"));
+ }
+}