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/07/05 13:21:38 UTC

[sling-whiteboard] branch master updated: Initial implementation of the whitelist service and resolver hook

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-whiteboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 6ef377b  Initial implementation of the whitelist service and resolver hook
6ef377b is described below

commit 6ef377b8a6e6794d4a5dfad93ae9c66cb6d3bbf3
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Thu Jul 5 14:20:50 2018 +0100

    Initial implementation of the whitelist service and resolver hook
---
 featuremodel/feature-whitelist/pom.xml             |   7 +-
 .../feature/whitelist/impl/ResolverHookImpl.java   |   6 +-
 .../whitelist/impl/WhitelistServiceImpl.java       |  25 +++-
 .../whitelist/impl/ResolverHookImplTest.java       | 163 +++++++++++++++++++++
 4 files changed, 190 insertions(+), 11 deletions(-)

diff --git a/featuremodel/feature-whitelist/pom.xml b/featuremodel/feature-whitelist/pom.xml
index 6e5fc2d..0aa23b9 100644
--- a/featuremodel/feature-whitelist/pom.xml
+++ b/featuremodel/feature-whitelist/pom.xml
@@ -96,6 +96,11 @@
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
-
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>2.8.9</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/featuremodel/feature-whitelist/src/main/java/org/apache/sling/feature/whitelist/impl/ResolverHookImpl.java b/featuremodel/feature-whitelist/src/main/java/org/apache/sling/feature/whitelist/impl/ResolverHookImpl.java
index 4926593..46ce493 100644
--- a/featuremodel/feature-whitelist/src/main/java/org/apache/sling/feature/whitelist/impl/ResolverHookImpl.java
+++ b/featuremodel/feature-whitelist/src/main/java/org/apache/sling/feature/whitelist/impl/ResolverHookImpl.java
@@ -88,7 +88,7 @@ class ResolverHookImpl implements ResolverHook {
                 Feature capFeat = fs.getFeatureForBundle(capBundleID);
 
                 // Within a single feature everything can wire to everything else
-                if (capFeat.equals(reqFeat))
+                if (reqFeat.equals(capFeat))
                     continue nextCapability;
 
 
@@ -96,7 +96,7 @@ class ResolverHookImpl implements ResolverHook {
                 if (pkg instanceof String) {
                     String packageName = (String) pkg;
                     // If the export is in the global region.
-                    if (whitelistService.regionWhitelistsPackage(WhitelistService.GLOBAL_REGION, packageName))
+                    if (Boolean.TRUE.equals(whitelistService.regionWhitelistsPackage(WhitelistService.GLOBAL_REGION, packageName)))
                         continue nextCapability;
 
                     // If the export is in a region that the feature is also in, then allow
@@ -105,7 +105,7 @@ class ResolverHookImpl implements ResolverHook {
                         if (WhitelistService.GLOBAL_REGION.equals(region))
                             continue;
 
-                        if (whitelistService.regionWhitelistsPackage(region, packageName))
+                        if (!Boolean.FALSE.equals(whitelistService.regionWhitelistsPackage(region, packageName)))
                             continue nextCapability;
                     }
 
diff --git a/featuremodel/feature-whitelist/src/main/java/org/apache/sling/feature/whitelist/impl/WhitelistServiceImpl.java b/featuremodel/feature-whitelist/src/main/java/org/apache/sling/feature/whitelist/impl/WhitelistServiceImpl.java
index 2243f7e..9877c0e 100644
--- a/featuremodel/feature-whitelist/src/main/java/org/apache/sling/feature/whitelist/impl/WhitelistServiceImpl.java
+++ b/featuremodel/feature-whitelist/src/main/java/org/apache/sling/feature/whitelist/impl/WhitelistServiceImpl.java
@@ -32,19 +32,30 @@ class WhitelistServiceImpl implements WhitelistService {
 
     WhitelistServiceImpl(Map<String, Set<String>> regionPackages,
             Map<String, Set<String>> featureRegions) {
+        Set<String> allRegions = new HashSet<>();
+
+        Map<String, Set<String>> frm = new HashMap<>();
+        for (Map.Entry<String, Set<String>> entry : featureRegions.entrySet()) {
+            Set<String> regions = Collections.unmodifiableSet(new HashSet<>(entry.getValue()));
+            allRegions.addAll(regions);
+            frm.put(entry.getKey(), regions);
+        }
+        featureRegionMapping = Collections.unmodifiableMap(frm);
+
         Map<String, Set<String>> rpm = new HashMap<>();
         for (Map.Entry<String, Set<String>> entry : regionPackages.entrySet()) {
-            rpm.put(entry.getKey(),
+            String region = entry.getKey();
+            rpm.put(region,
                     Collections.unmodifiableSet(new HashSet<>(entry.getValue())));
+            allRegions.remove(region);
         }
-        regionPackageMapping = Collections.unmodifiableMap(rpm);
 
-        Map<String, Set<String>> frm = new HashMap<>();
-        for (Map.Entry<String, Set<String>> entry : featureRegions.entrySet()) {
-            frm.put(entry.getKey(),
-                    Collections.unmodifiableSet(new HashSet<>(entry.getValue())));
+        // If there are more regions mentioned but these don't have any package
+        // mappings, give them an empty mapping
+        for (String region : allRegions) {
+            rpm.put(region, Collections.emptySet());
         }
-        featureRegionMapping = Collections.unmodifiableMap(frm);
+        regionPackageMapping = Collections.unmodifiableMap(rpm);
     }
 
     @Override
diff --git a/featuremodel/feature-whitelist/src/test/java/org/apache/sling/feature/whitelist/impl/ResolverHookImplTest.java b/featuremodel/feature-whitelist/src/test/java/org/apache/sling/feature/whitelist/impl/ResolverHookImplTest.java
new file mode 100644
index 0000000..fbfbbe0
--- /dev/null
+++ b/featuremodel/feature-whitelist/src/test/java/org/apache/sling/feature/whitelist/impl/ResolverHookImplTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.whitelist.impl;
+
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.service.FeatureService;
+import org.apache.sling.feature.whitelist.WhitelistService;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.util.tracker.ServiceTracker;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+
+public class ResolverHookImplTest {
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void testFilterMatches() throws Exception {
+        ArtifactId fid = new ArtifactId("gid", "aid", "0.0.9", null, null);
+        Feature f = new Feature(fid);
+
+        ArtifactId fid2 = new ArtifactId("gid2", "aid2", "1.0.0-SNAPSHOT", null, null);
+        Feature f2 = new Feature(fid2);
+
+        FeatureService fs = Mockito.mock(FeatureService.class);
+        Mockito.when(fs.getFeatureForBundle(7)).thenReturn(f);
+        Mockito.when(fs.getFeatureForBundle(9)).thenReturn(f2);
+        Mockito.when(fs.getFeatureForBundle(10)).thenReturn(f2);
+
+        ServiceTracker st = Mockito.mock(ServiceTracker.class);
+        Mockito.when(st.waitForService(Mockito.anyLong())).thenReturn(fs);
+
+        Map<String, Set<String>> rpm = new HashMap<>();
+        rpm.put("r0", Collections.singleton("org.bar"));
+        rpm.put("r1", new HashSet<>(Arrays.asList("org.blah", "org.foo")));
+        rpm.put(WhitelistService.GLOBAL_REGION, Collections.singleton("org.bar.tar"));
+
+        Map<String, Set<String>> frm = new HashMap<>();
+        frm.put("gid:aid:0.0.9",
+                new HashSet<>(Arrays.asList("r1", "r2", WhitelistService.GLOBAL_REGION)));
+        frm.put("gid2:aid2:1.0.0-SNAPSHOT", Collections.singleton("r2"));
+
+        WhitelistService wls = new WhitelistServiceImpl(rpm, frm);
+        ResolverHookImpl rh = new ResolverHookImpl(st, wls);
+
+        // Check that we can get the capability from another bundle in the same region
+        // Bundle 7 is in feature f with regions r1, r2
+        BundleRequirement req = mockRequirement(7);
+        BundleCapability bc1 = mockCapability("org.foo", 19);
+        List<BundleCapability> candidates = new ArrayList<>(Arrays.asList(bc1));
+        rh.filterMatches(req, candidates);
+        assertEquals(Collections.singletonList(bc1), candidates);
+
+        // Check that we cannot get the capability from another bundle in a different region
+        // Bundle 9 is in feature f2 with region r2
+        BundleRequirement req2 = mockRequirement(9);
+        BundleCapability bc2 = mockCapability("org.bar", 17);
+        Collection<BundleCapability> c2 = new ArrayList<>(Arrays.asList(bc2));
+        rh.filterMatches(req2, c2);
+        assertEquals(0, c2.size());
+
+        // Check that we can get the capability from the same bundle
+        BundleRequirement req3 = mockRequirement(9);
+        BundleCapability bc3 = mockCapability("org.bar", 9);
+        Collection<BundleCapability> c3 = new ArrayList<>(Arrays.asList(bc3));
+        rh.filterMatches(req3, c3);
+        assertEquals(Collections.singletonList(bc3), c3);
+
+        // Check that we can get the capability from the another bundle in the same feature
+        BundleRequirement req4 = mockRequirement(9);
+        BundleCapability bc4 = mockCapability("org.bar", 10);
+        Collection<BundleCapability> c4 = new ArrayList<>(Arrays.asList(bc4));
+        rh.filterMatches(req4, c4);
+        assertEquals(Collections.singletonList(bc4), c4);
+
+        // Check that we cannot get the capability from another bundle where the capability
+        // is globally visible (from bundle 9, f2)
+        BundleRequirement req5 = mockRequirement(9);
+        BundleCapability bc5 = mockCapability("org.bar.tar", 17);
+        Collection<BundleCapability> c5 = new ArrayList<>(Arrays.asList(bc5));
+        rh.filterMatches(req5, c5);
+        assertEquals(Collections.singletonList(bc5), c5);
+
+        // Check that we cannot get the capability from another bundle where the capability
+        // is globally visible (from bundle 7, f)
+        BundleRequirement req6 = mockRequirement(7);
+        BundleCapability bc6 = mockCapability("org.bar.tar", 17);
+        Collection<BundleCapability> c6 = new ArrayList<>(Arrays.asList(bc6));
+        rh.filterMatches(req6, c6);
+        assertEquals(Collections.singletonList(bc6), c6);
+
+        // Check that capabilities in non-package namespaces are ignored
+        BundleRequirement req7 = Mockito.mock(BundleRequirement.class);
+        Mockito.when(req7.getNamespace()).thenReturn("some.other.namespace");
+        BundleCapability bc7 = mockCapability("org.bar", 17);
+        Collection<BundleCapability> c7 = new ArrayList<>(Arrays.asList(bc7));
+        rh.filterMatches(req7, c7);
+        assertEquals(Collections.singletonList(bc7), c7);
+    }
+
+    private BundleCapability mockCapability(String pkg, long bundleID) {
+        Map<String, Object> attrs =
+                Collections.singletonMap(PackageNamespace.PACKAGE_NAMESPACE, pkg);
+
+        Bundle bundle = Mockito.mock(Bundle.class);
+        Mockito.when(bundle.getBundleId()).thenReturn(bundleID);
+
+        BundleRevision br = Mockito.mock(BundleRevision.class);
+        Mockito.when(br.getBundle()).thenReturn(bundle);
+
+
+        BundleCapability cap = Mockito.mock(BundleCapability.class);
+        Mockito.when(cap.getAttributes()).thenReturn(attrs);
+        Mockito.when(cap.getRevision()).thenReturn(br);
+        return cap;
+    }
+
+    private BundleRequirement mockRequirement(long bundleID) {
+        Bundle bundle = Mockito.mock(Bundle.class);
+        Mockito.when(bundle.getBundleId()).thenReturn(bundleID);
+
+        BundleRevision br = Mockito.mock(BundleRevision.class);
+        Mockito.when(br.getBundle()).thenReturn(bundle);
+
+        BundleRequirement req = Mockito.mock(BundleRequirement.class);
+        Mockito.when(req.getNamespace()).thenReturn(PackageNamespace.PACKAGE_NAMESPACE);
+        Mockito.when(req.getRevision()).thenReturn(br);
+
+        return req;
+    }
+}