You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2019/12/05 15:11:20 UTC

[sling-org-apache-sling-feature-analyser] 01/01: SLING-8873 - Validate the sourceId property at build time

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

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

commit c5f89235d9866221bffe97e04f2fbdb455d7e328
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Thu Dec 5 14:31:04 2019 +0100

    SLING-8873 - Validate the sourceId property at build time
    
    Add a new analyser for the source id property.
---
 readme.md                                          |   2 +
 .../task/impl/CheckApisJarsProperties.java         |  77 +++++++++++
 ...apache.sling.feature.analyser.task.AnalyserTask |   1 +
 .../task/impl/CheckApisJarsPropertiesTest.java     | 147 +++++++++++++++++++++
 4 files changed, 227 insertions(+)

diff --git a/readme.md b/readme.md
index e156ea7..7f0d435 100644
--- a/readme.md
+++ b/readme.md
@@ -30,6 +30,8 @@ information as part of the check, to ensure that bundles don't import packages o
 * `exported-packages`: Lists all packages in the feature and writes these to a `packages.txt` file. This 
 analyser task is not enabled by default.
 
+* `apis-jar`: validates that the `sourceId` property of a bundle, if defined, is a comma-separated value list of artifact ids.
+
 There are a number of analysers which relate to API Region definitions in Feature Models. 
 
 * `api-regions`: This analyser ensures that packages listed as exports in API-Regions sections are actually exported by a bundle that's part of the feature.
diff --git a/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckApisJarsProperties.java b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckApisJarsProperties.java
new file mode 100644
index 0000000..01f1177
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckApisJarsProperties.java
@@ -0,0 +1,77 @@
+/*
+ * 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.Arrays;
+import java.util.List;
+
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.analyser.task.AnalyserTask;
+import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+
+/**
+ * This analyser validates that the entries related to Apis Jar are valid.
+ * 
+ * Current checks:
+ * 
+ * <ol>
+ *  <li>The <tt>sourceId</tt> property is a CSV list of valid artifact ids.</li>
+ * </ol>
+ *
+ */
+public class CheckApisJarsProperties implements AnalyserTask {
+    
+    // TODO - also defined in ApisJarMojo
+    private static final String SOURCE_ID = "sourceId";
+
+    @Override
+    public String getId() {
+        return "apis-jar";
+    }
+    
+    @Override
+    public String getName() {
+        return "APIs jar properties check";
+    }
+    
+    @Override
+    public void execute(AnalyserTaskContext ctx) throws Exception {
+
+        ctx.getFeature().getBundles().getBundlesByStartOrder().values().stream()
+            .flatMap( List::stream )
+            .filter ( artifact -> artifact.getMetadata().containsKey(SOURCE_ID) )
+            .forEach( artifact -> checkSourceIdValidity(artifact, ctx));
+    }
+    
+    private void checkSourceIdValidity(Artifact a, AnalyserTaskContext ctx) {
+        String sourceId = a.getMetadata().get(SOURCE_ID);
+        Arrays.stream(sourceId.split(","))
+            .map( String::trim )
+            .filter( el -> el.length() > 0)
+            .forEach( el -> {
+                try {
+                    // at the moment we can not validate the availability of the artifact since there is no access to Maven APIs
+                    ArtifactId.parse(el);
+                } catch ( IllegalArgumentException e) {
+                    ctx.reportError("Bundle " + a.getId() + " has invalid sourceId entry '" + el + "' : " + e.getMessage());
+                }
+            });
+        
+    }
+
+}
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 0da2434..e7ec563 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
@@ -4,3 +4,4 @@ org.apache.sling.feature.analyser.task.impl.CheckBundlesForInitialContent
 org.apache.sling.feature.analyser.task.impl.CheckBundlesForResources
 org.apache.sling.feature.analyser.task.impl.CheckRequirementsCapabilities
 org.apache.sling.feature.analyser.task.impl.CheckContentPackagesDependencies
+org.apache.sling.feature.analyser.task.impl.CheckApiJarsProperties
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckApisJarsPropertiesTest.java b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckApisJarsPropertiesTest.java
new file mode 100644
index 0000000..7307b25
--- /dev/null
+++ b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckApisJarsPropertiesTest.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 static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.feature.Artifact;
+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.scanner.BundleDescriptor;
+import org.apache.sling.feature.scanner.FeatureDescriptor;
+import org.junit.Test;
+
+public class CheckApisJarsPropertiesTest {
+
+    private static class SpyAnalyserTaskContext implements AnalyserTaskContext {
+        private final Feature f;
+        private final List<String> warnings = new ArrayList<>();
+        private final List<String> errors = new ArrayList<>();
+
+        private SpyAnalyserTaskContext(Feature f) {
+            this.f = f;
+        }
+
+        @Override
+        public void reportWarning(String message) {
+            System.out.println("[WARN] " + message);
+            warnings.add(message);
+        }
+
+        @Override
+        public void reportError(String message) {
+            System.out.println("[ERROR] " + message);
+            errors.add(message);
+        }
+
+        @Override
+        public BundleDescriptor getFrameworkDescriptor() {
+            return null;
+        }
+
+        @Override
+        public FeatureDescriptor getFeatureDescriptor() {
+            throw new UnsupportedOperationException("stub");
+        }
+
+        @Override
+        public Feature getFeature() {
+            return f;
+        }
+
+        @Override
+        public Map<String, String> getConfiguration() {
+            return Collections.emptyMap();
+        }
+        
+        public List<String> getErrors() {
+            return errors;
+        }
+        
+        public List<String> getWarnings() {
+            return warnings;
+        }
+    }
+    
+    static class FeatureStub extends Feature {
+
+        public FeatureStub() {
+            super(ArtifactId.fromMvnId("org.apache.sling:org.apache.sling.feature.analyser.test:slingosgifeature:validSourceIds:1.0"));
+            
+            setComplete(true);
+        }
+        
+        public void addArtifactWithSourceId(String artifactId, String sourceId) {
+            Artifact artifact = new Artifact(ArtifactId.parse(artifactId));
+            if ( sourceId != null )
+                artifact.getMetadata().put("sourceId", sourceId);
+            
+            getBundles().add(artifact);
+        }
+        
+        public void addArtifact(String artifactId) {
+            addArtifactWithSourceId(artifactId, null);
+        }
+        
+    }
+
+    @Test
+    public void validSourceIds() throws Exception {
+        CheckApisJarsProperties check = new CheckApisJarsProperties();
+        
+        FeatureStub f = new FeatureStub();
+        // 1 entry with CSV sourceId
+        f.addArtifactWithSourceId("org.apache.aries.transaction:org.apache.aries.transaction.manager:1.2.0", 
+                "org.apache.aries.transaction:org.apache.aries.transaction.manager:jar:sources:1.2.0,javax.transaction:javax.transaction-api:jar:sources:1.2,org.apache.geronimo.components:geronimo-transaction:jar:sources:3.1.2");
+
+        // 1 entry with simple sourceId
+        f.addArtifactWithSourceId("org.apache.sling:org.apache.sling.scripting.jsp-api:1.0.0", 
+                "org.apache.tomcat:tomcat-jsp-api:jar:sources:7.0.96");
+        
+        // 1 entry with no sourceId
+        f.addArtifact("org.apache.sling:org.apache.sling.engine:2.6.20");
+
+        SpyAnalyserTaskContext context = new SpyAnalyserTaskContext(f);
+        check.execute(context);
+        assertThat("errors.size", context.getErrors().size(), equalTo(0));
+        assertThat("warnings.size", context.getWarnings().size(), equalTo(0));
+    }
+    
+    @Test
+    public void invalidSourceId() throws Exception {
+        CheckApisJarsProperties check = new CheckApisJarsProperties();
+        
+        FeatureStub f = new FeatureStub();
+        // 1 entry with invalid sourceId
+        f.addArtifactWithSourceId("org.apache.sling:org.apache.sling.scripting.jsp-api:1.0.0", 
+                "invalid-source-id");
+
+        SpyAnalyserTaskContext context = new SpyAnalyserTaskContext(f);
+        check.execute(context);
+        assertThat("errors.size", context.getErrors().size(), equalTo(1));
+        assertThat("warnings.size", context.getWarnings().size(), equalTo(0));  
+    }
+}