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/10 10:59:22 UTC
[sling-whiteboard] branch master updated: Update Features service
API and extend the whitelist unit tests
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 03e429e Update Features service API and extend the whitelist unit tests
03e429e is described below
commit 03e429e3035e9e9db5a5f5332217c9d0d90ea14c
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Tue Jul 10 11:58:57 2018 +0100
Update Features service API and extend the whitelist unit tests
---
.../org/apache/sling/feature/service/Features.java | 4 +-
.../feature/service/impl/FeatureServiceImpl.java | 16 +++---
.../service/impl/FeaturesServiceManager.java | 44 +++++++++-------
.../service/impl/FeatureServiceImplTest.java | 19 ++++---
.../feature/whitelist/impl/ResolverHookImpl.java | 18 +++++--
.../whitelist/impl/ResolverHookImplTest.java | 60 ++++++++++++++--------
6 files changed, 101 insertions(+), 60 deletions(-)
diff --git a/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/Features.java b/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/Features.java
index d1e91a6..46dd595 100644
--- a/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/Features.java
+++ b/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/Features.java
@@ -18,9 +18,11 @@
*/
package org.apache.sling.feature.service;
+import org.osgi.framework.Version;
+
import java.util.Collection;
public interface Features {
Collection<String> listFeatures();
- String getFeatureForBundle(long bundleId);
+ String getFeatureForBundle(String bsn, Version ver);
}
diff --git a/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/impl/FeatureServiceImpl.java b/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/impl/FeatureServiceImpl.java
index f0fa389..03d2064 100644
--- a/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/impl/FeatureServiceImpl.java
+++ b/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/impl/FeatureServiceImpl.java
@@ -19,21 +19,21 @@
package org.apache.sling.feature.service.impl;
import org.apache.sling.feature.service.Features;
+import org.osgi.framework.Version;
+import java.util.AbstractMap;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-public class FeatureServiceImpl implements Features {
+class FeatureServiceImpl implements Features {
private final Set<String> features;
- private final Map<Long, String> bundleFeatureMap;
+ private final Map<Map.Entry<String, Version>, String> bundleFeatureMap;
- public FeatureServiceImpl(Map<Long, String> bundleIDFeatures) {
- Map<Long, String> bfm = new HashMap<>(bundleIDFeatures);
- bundleFeatureMap = Collections.unmodifiableMap(bfm);
+ FeatureServiceImpl(Map<Map.Entry<String, Version>, String> bundleIDFeatures) {
+ bundleFeatureMap = Collections.unmodifiableMap(bundleIDFeatures);
Set<String> fs = new HashSet<>(bundleIDFeatures.values());
features = Collections.unmodifiableSet(fs);
@@ -45,7 +45,7 @@ public class FeatureServiceImpl implements Features {
}
@Override
- public String getFeatureForBundle(long bundleId) {
- return bundleFeatureMap.get(bundleId);
+ public String getFeatureForBundle(String bsn, Version version) {
+ return bundleFeatureMap.get(new AbstractMap.SimpleEntry<String, Version>(bsn, version));
}
}
diff --git a/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/impl/FeaturesServiceManager.java b/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/impl/FeaturesServiceManager.java
index 4925bbb..e4492c9 100644
--- a/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/impl/FeaturesServiceManager.java
+++ b/featuremodel/feature-service/src/main/java/org/apache/sling/feature/service/impl/FeaturesServiceManager.java
@@ -19,16 +19,19 @@
package org.apache.sling.feature.service.impl;
import org.apache.sling.feature.service.Features;
-import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.Version;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
+import java.util.AbstractMap;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
@@ -42,36 +45,40 @@ class FeaturesServiceManager implements ManagedService {
@Override
public synchronized void updated(Dictionary<String, ?> properties) throws ConfigurationException {
- System.out.println("######******* Updated " + properties);
if (reg != null)
reg.unregister();
if (properties == null)
return;
- Map<String, Long> bsnVerToID = getBundleToID();
-
- Map<Long, String> bundleIDFeatures = new HashMap<>();
+ Map<Map.Entry<String, Version>, String> bundleIDFeatures = new HashMap<>();
+ Dictionary<String, String> props = new Hashtable<>();
for(Enumeration<String> e = properties.keys(); e.hasMoreElements(); ) {
String key = e.nextElement();
- Long bid = bsnVerToID.get(key);
- if (bid != null) {
- bundleIDFeatures.put(bid, getStringPlus(properties.get(key)));
- }
- }
+ if (key.startsWith("."))
+ continue;
- FeatureServiceImpl fs = new FeatureServiceImpl(bundleIDFeatures);
- reg = bundleContext.registerService(Features.class, fs, null);
- }
+ if (Constants.SERVICE_PID.equals(key))
+ continue;
- private Map<String, Long> getBundleToID() {
- Map<String, Long> m = new HashMap<>();
+ String[] bsnver = key.split(":");
+ if (bsnver.length != 2)
+ continue;
- for (Bundle b : bundleContext.getBundles()) {
- m.put(b.getSymbolicName() + ":" + b.getVersion(), b.getBundleId());
+ try {
+ Version ver = Version.valueOf(bsnver[1]);
+
+ String value = getStringPlus(properties.get(key));
+ AbstractMap.SimpleEntry<String, Version> newKey = new AbstractMap.SimpleEntry<>(bsnver[0], ver);
+ bundleIDFeatures.put(newKey, value);
+ props.put(key, value);
+ } catch (IllegalArgumentException iae) {
+ // TODO log
+ }
}
- return m;
+ FeatureServiceImpl fs = new FeatureServiceImpl(bundleIDFeatures);
+ reg = bundleContext.registerService(Features.class, fs, props);
}
private String getStringPlus(Object obj) {
@@ -85,4 +92,5 @@ class FeaturesServiceManager implements ManagedService {
}
return null;
}
+
}
diff --git a/featuremodel/feature-service/src/test/java/org/apache/sling/feature/service/impl/FeatureServiceImplTest.java b/featuremodel/feature-service/src/test/java/org/apache/sling/feature/service/impl/FeatureServiceImplTest.java
index 0a3ef0c..5b9a74a 100644
--- a/featuremodel/feature-service/src/test/java/org/apache/sling/feature/service/impl/FeatureServiceImplTest.java
+++ b/featuremodel/feature-service/src/test/java/org/apache/sling/feature/service/impl/FeatureServiceImplTest.java
@@ -20,9 +20,12 @@ package org.apache.sling.feature.service.impl;
import org.apache.sling.feature.service.Features;
import org.junit.Test;
+import org.osgi.framework.Version;
+import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
+import java.util.Map.Entry;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -30,21 +33,21 @@ import static org.junit.Assert.assertNull;
public class FeatureServiceImplTest {
@Test
public void testFeatureService() {
- Map<Long, String> bif = new HashMap<>();
+ Map<Entry<String, Version>, String> bif = new HashMap<>();
String f1 = "gid:aid:1.0.0:myfeature:slingfeature";
- bif.put(123L, f1);
- bif.put(456L, f1);
+ bif.put(new AbstractMap.SimpleEntry<String,Version>("mybsn", new Version(1,2,3)), f1);
+ bif.put(new AbstractMap.SimpleEntry<String,Version>("mybsn2", new Version(4,5,6)), f1);
String f2 = "gid:aid2:1.0.0";
- bif.put(789L, f2);
+ bif.put(new AbstractMap.SimpleEntry<String,Version>("mybsn", new Version(7,8,9)), f2);
Features fs = new FeatureServiceImpl(bif);
assertEquals(2, fs.listFeatures().size());
- assertEquals(f1, fs.getFeatureForBundle(123));
- assertEquals(f1, fs.getFeatureForBundle(456));
- assertEquals(f2, fs.getFeatureForBundle(789));
- assertNull(fs.getFeatureForBundle(999));
+ assertEquals(f1, fs.getFeatureForBundle("mybsn", new Version(1,2,3)));
+ assertEquals(f1, fs.getFeatureForBundle("mybsn2", new Version(4,5,6)));
+ assertEquals(f2, fs.getFeatureForBundle("mybsn", new Version(7,8,9)));
+ assertNull(fs.getFeatureForBundle("mybsn2", new Version(1,2,3)));
}
}
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 21a737a..eff6353 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
@@ -20,6 +20,8 @@ package org.apache.sling.feature.whitelist.impl;
import org.apache.sling.feature.service.Features;
import org.apache.sling.feature.whitelist.WhitelistService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
import org.osgi.framework.hooks.resolver.ResolverHook;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleCapability;
@@ -59,7 +61,10 @@ class ResolverHookImpl implements ResolverHook {
if (!PackageNamespace.PACKAGE_NAMESPACE.equals(requirement.getNamespace()))
return;
- long reqBundleID = requirement.getRevision().getBundle().getBundleId();
+ Bundle reqBundle = requirement.getRevision().getBundle();
+ long reqBundleID = reqBundle.getBundleId();
+ String reqBundleName = reqBundle.getSymbolicName();
+ Version reqBundleVersion = reqBundle.getVersion();
try {
Features fs = featureServiceTracker.waitForService(SERVICE_WAIT_TIMEOUT);
@@ -70,7 +75,7 @@ class ResolverHookImpl implements ResolverHook {
return;
}
- String reqFeat = fs.getFeatureForBundle(reqBundleID);
+ String reqFeat = fs.getFeatureForBundle(reqBundleName, reqBundleVersion);
Set<String> regions = whitelistService.listRegions(reqFeat);
nextCapability:
@@ -80,17 +85,20 @@ class ResolverHookImpl implements ResolverHook {
BundleRevision rev = bc.getRevision();
// A bundle is allowed to wire to itself
- long capBundleID = rev.getBundle().getBundleId();
+ Bundle capBundle = rev.getBundle();
+ long capBundleID = capBundle.getBundleId();
if (capBundleID == reqBundleID)
continue nextCapability;
- String capFeat = fs.getFeatureForBundle(capBundleID);
+ String capBundleName = capBundle.getSymbolicName();
+ Version capBundleVersion = capBundle.getVersion();
+
+ String capFeat = fs.getFeatureForBundle(capBundleName, capBundleVersion);
// Within a single feature everything can wire to everything else
if (reqFeat.equals(capFeat))
continue nextCapability;
-
Object pkg = bc.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
if (pkg instanceof String) {
String packageName = (String) pkg;
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
index eb36749..18ab601 100644
--- 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
@@ -23,6 +23,7 @@ import org.apache.sling.feature.whitelist.WhitelistService;
import org.junit.Test;
import org.mockito.Mockito;
import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
@@ -48,11 +49,16 @@ public class ResolverHookImplTest {
public void testFilterMatches() throws Exception {
String f = "gid:aid:0.0.9";
String f2 = "gid2:aid2:1.0.0-SNAPSHOT";
+ String f3 = "gid3:aid3:1.2.3";
+ String f4 = "gid4:aid4:1.2.3";
Features fs = Mockito.mock(Features.class);
- Mockito.when(fs.getFeatureForBundle(7)).thenReturn(f);
- Mockito.when(fs.getFeatureForBundle(9)).thenReturn(f2);
- Mockito.when(fs.getFeatureForBundle(10)).thenReturn(f2);
+ Mockito.when(fs.getFeatureForBundle("a.b.c", new Version(0,0,0))).thenReturn(f); // b7
+ Mockito.when(fs.getFeatureForBundle("some.other.bundle", new Version(9,9,9,"suffix"))).thenReturn(f2); // b9
+ Mockito.when(fs.getFeatureForBundle("a-bundle", new Version(1,0,0,"SNAPSHOT"))).thenReturn(f2); // b10
+ Mockito.when(fs.getFeatureForBundle("a.b.c", new Version(1,2,3))).thenReturn(f3); // b17
+ Mockito.when(fs.getFeatureForBundle("x.y.z", new Version(9,9,9))).thenReturn(f3); // b19
+ Mockito.when(fs.getFeatureForBundle("zzz", new Version(1,0,0))).thenReturn(f4); // b20
ServiceTracker st = Mockito.mock(ServiceTracker.class);
Mockito.when(st.waitForService(Mockito.anyLong())).thenReturn(fs);
@@ -61,57 +67,60 @@ public class ResolverHookImplTest {
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"));
+ rpm.put("r3", Collections.singleton("xyz"));
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"));
+ frm.put("gid3:aid3:1.2.3", Collections.singleton("r3"));
+ frm.put("gid4:aid4:1.2.3", Collections.singleton("r3"));
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);
+ BundleRequirement req = mockRequirement(17, "a.b.c", new Version(1,2,3));
+ BundleCapability bc1 = mockCapability("org.foo", 19, "x.y.z", new Version(9,9,9));
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);
+ BundleRequirement req2 = mockRequirement(9, "some.other.bundle", new Version(9,9,9,"suffix"));
+ BundleCapability bc2 = mockCapability("org.bar", 17, "a.b.c", new Version(1,2,3));
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);
+ BundleRequirement req3 = mockRequirement(9, "some.other.bundle", new Version(9,9,9,"suffix"));
+ BundleCapability bc3 = mockCapability("org.bar", 9, "some.other.bundle", new Version(9,9,9,"suffix"));
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);
+ BundleRequirement req4 = mockRequirement(9, "some.other.bundle", new Version(9,9,9,"suffix"));
+ BundleCapability bc4 = mockCapability("org.bar", 10, "a-bundle", new Version(1,0,0,"SNAPSHOT"));
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
+ // Check that we can 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);
+ BundleRequirement req5 = mockRequirement(17, "a.b.c", new Version(1,2,3));
+ BundleCapability bc5 = mockCapability("org.bar.tar", 9, "some.other.bundle", new Version(9,9,9,"suffix"));
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
+ // Check that we can 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);
+ BundleRequirement req6 = mockRequirement(7, "a.b.c", new Version(0,0,0));
+ BundleCapability bc6 = mockCapability("org.bar.tar", 17, "a.b.c", new Version(1,2,3));
Collection<BundleCapability> c6 = new ArrayList<>(Arrays.asList(bc6));
rh.filterMatches(req6, c6);
assertEquals(Collections.singletonList(bc6), c6);
@@ -119,18 +128,27 @@ public class ResolverHookImplTest {
// 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);
+ BundleCapability bc7 = mockCapability("org.bar", 17, "a.b.c", new Version(1,2,3));
Collection<BundleCapability> c7 = new ArrayList<>(Arrays.asList(bc7));
rh.filterMatches(req7, c7);
assertEquals(Collections.singletonList(bc7), c7);
+
+ // Check that we can get the capability from another provider in the same region
+ BundleRequirement req8 = mockRequirement(20, "zzz", new Version(1,0,0));
+ BundleCapability bc8 = mockCapability("xyz", 19, "x.y.z", new Version(9,9,9));
+ Collection<BundleCapability> c8 = new ArrayList<>(Arrays.asList(bc8));
+ rh.filterMatches(req8, c8);
+ assertEquals(Collections.singletonList(bc8), c8);
}
- private BundleCapability mockCapability(String pkg, long bundleID) {
+ private BundleCapability mockCapability(String pkg, long bundleID, String bsn, Version version) {
Map<String, Object> attrs =
Collections.singletonMap(PackageNamespace.PACKAGE_NAMESPACE, pkg);
Bundle bundle = Mockito.mock(Bundle.class);
Mockito.when(bundle.getBundleId()).thenReturn(bundleID);
+ Mockito.when(bundle.getSymbolicName()).thenReturn(bsn);
+ Mockito.when(bundle.getVersion()).thenReturn(version);
BundleRevision br = Mockito.mock(BundleRevision.class);
Mockito.when(br.getBundle()).thenReturn(bundle);
@@ -142,9 +160,11 @@ public class ResolverHookImplTest {
return cap;
}
- private BundleRequirement mockRequirement(long bundleID) {
+ private BundleRequirement mockRequirement(long bundleID, String bsn, Version version) {
Bundle bundle = Mockito.mock(Bundle.class);
Mockito.when(bundle.getBundleId()).thenReturn(bundleID);
+ Mockito.when(bundle.getSymbolicName()).thenReturn(bsn);
+ Mockito.when(bundle.getVersion()).thenReturn(version);
BundleRevision br = Mockito.mock(BundleRevision.class);
Mockito.when(br.getBundle()).thenReturn(bundle);