This is an automated email from the ASF dual-hosted git repository. amichai pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/aries-rsa.git
commit f2d25032e8c6039dbbc51131904c78d1e6933024 Author: Amichai Rothman <[email protected]> AuthorDate: Wed Mar 10 00:29:58 2021 +0200 ARIES-2043 - Fix LocalDiscovery not updated when listener scope changes --- .../aries/rsa/discovery/local/LocalDiscovery.java | 9 ++++ .../rsa/discovery/local/LocalDiscoveryTest.java | 53 ++++++++++++++++------ 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/discovery/local/src/main/java/org/apache/aries/rsa/discovery/local/LocalDiscovery.java b/discovery/local/src/main/java/org/apache/aries/rsa/discovery/local/LocalDiscovery.java index 0181bb2..63e5cf2 100644 --- a/discovery/local/src/main/java/org/apache/aries/rsa/discovery/local/LocalDiscovery.java +++ b/discovery/local/src/main/java/org/apache/aries/rsa/discovery/local/LocalDiscovery.java @@ -125,6 +125,15 @@ public class LocalDiscovery implements BundleListener { } } + void updatedListener(ServiceReference<EndpointEventListener> endpointListenerRef, EndpointEventListener endpointListener) { + // if service properties have been updated, the filter (scope) + // might have changed so we remove and re-add the listener + synchronized (listenerToFilters) { + unbindListener(endpointListener); + bindListener(endpointListenerRef, endpointListener); + } + } + private Map<String, Collection<EndpointEventListener>> getMatchingListeners(EndpointDescription endpoint) { // return a copy of matched filters/listeners so that caller doesn't need to hold locks while triggering events Map<String, Collection<EndpointEventListener>> matched = new HashMap<>(); diff --git a/discovery/local/src/test/java/org/apache/aries/rsa/discovery/local/LocalDiscoveryTest.java b/discovery/local/src/test/java/org/apache/aries/rsa/discovery/local/LocalDiscoveryTest.java index c18b8e0..871b016 100644 --- a/discovery/local/src/test/java/org/apache/aries/rsa/discovery/local/LocalDiscoveryTest.java +++ b/discovery/local/src/test/java/org/apache/aries/rsa/discovery/local/LocalDiscoveryTest.java @@ -132,36 +132,38 @@ public class LocalDiscoveryTest { public void testEndpointListenerService() throws Exception { LocalDiscovery ld = new LocalDiscovery(); - Bundle bundle = createBundle(); + Bundle bundle = createBundle(); // created with two endpoint descriptions, ClassA and ClassB BundleEvent event = new BundleEvent(BundleEvent.STARTED, bundle); ld.bundleChanged(event); assertEquals(2, ld.endpointDescriptions.size()); - ServiceReference<EndpointEventListener> sr = epListenerWithScope("(objectClass=org.example.ClassA)"); + assertEquals("Precondition failed", 0, ld.listenerToFilters.size()); + assertEquals("Precondition failed", 0, ld.filterToListeners.size()); EndpointEventListener el = EasyMock.createMock(EndpointEventListener.class); + + ServiceReference<EndpointEventListener> sr = epListenerWithScope("(objectClass=org.example.ClassA)"); el.endpointChanged(EasyMock.anyObject(EndpointEvent.class), EasyMock.eq("(objectClass=org.example.ClassA)")); EasyMock.expectLastCall(); + EasyMock.replay(el); - // Add the EndpointListener Service - assertEquals("Precondition failed", 0, ld.listenerToFilters.size()); - assertEquals("Precondition failed", 0, ld.filterToListeners.size()); + // add the EndpointListener service ld.bindListener(sr, el); + EasyMock.verify(el); + assertEquals(1, ld.listenerToFilters.size()); assertEquals(Collections.singletonList("(objectClass=org.example.ClassA)"), ld.listenerToFilters.get(el)); assertEquals(1, ld.filterToListeners.size()); assertEquals(Collections.singletonList(el), ld.filterToListeners.get("(objectClass=org.example.ClassA)")); - EasyMock.verify(el); - - // Modify the EndpointListener Service - // no need to reset the mock for this... - ServiceReference<EndpointEventListener> sr2 = epListenerWithScope("(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))"); + // unbind the listener, modify its scope, and bind again EasyMock.reset(el); + + ServiceReference<EndpointEventListener> sr2 = epListenerWithScope("(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))"); final Set<String> actualEndpoints = new HashSet<>(); el.endpointChanged(EasyMock.anyObject(EndpointEvent.class), EasyMock.eq("(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))")); @@ -173,22 +175,45 @@ public class LocalDiscoveryTest { return null; } }).times(2); + EasyMock.replay(el); ld.unbindListener(el); ld.bindListener(sr2, el); + + EasyMock.verify(el); + assertEquals(1, ld.listenerToFilters.size()); - assertEquals(Arrays.asList("(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))"), + assertEquals(Collections.singletonList("(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))"), ld.listenerToFilters.get(el)); assertEquals(1, ld.filterToListeners.size()); assertEquals(Collections.singletonList(el), ld.filterToListeners.get("(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))")); - - EasyMock.verify(el); Set<String> expectedEndpoints = new HashSet<>(Arrays.asList("org.example.ClassA", "org.example.ClassB")); assertEquals(expectedEndpoints, actualEndpoints); - // Remove the EndpointListener Service + // now change the scope via updated service properties on a registered service + + EasyMock.reset(el); + + ServiceReference<EndpointEventListener> sr3 = epListenerWithScope("(objectClass=org.example.ClassC)"); + actualEndpoints.clear(); + el.endpointChanged(EasyMock.anyObject(EndpointEvent.class), + EasyMock.eq("(objectClass=org.example.ClassC)")); + EasyMock.expectLastCall().andThrow(new AssertionError()).anyTimes(); + + EasyMock.replay(el); + + ld.updatedListener(sr3, el); + + EasyMock.verify(el); + + assertEquals(1, ld.listenerToFilters.size()); + assertEquals(Collections.singletonList("(objectClass=org.example.ClassC)"), ld.listenerToFilters.get(el)); + assertEquals(1, ld.filterToListeners.size()); + assertEquals(Collections.singletonList(el), ld.filterToListeners.get("(objectClass=org.example.ClassC)")); + + // remove the EndpointListener service ld.unbindListener(el); assertEquals(0, ld.listenerToFilters.size()); assertEquals(0, ld.filterToListeners.size());
