| /** |
| * 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.aries.rsa.discovery.local; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertSame; |
| |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Dictionary; |
| import java.util.HashSet; |
| import java.util.Hashtable; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.easymock.EasyMock; |
| import org.easymock.IAnswer; |
| import org.junit.Test; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleEvent; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.remoteserviceadmin.EndpointDescription; |
| import org.osgi.service.remoteserviceadmin.EndpointEvent; |
| import org.osgi.service.remoteserviceadmin.EndpointEventListener; |
| |
| public class LocalDiscoveryTest { |
| |
| @Test |
| public void testPreExistingBundles() throws Exception { |
| Bundle b1 = EasyMock.createMock(Bundle.class); |
| EasyMock.expect(b1.getState()).andReturn(Bundle.RESOLVED); |
| EasyMock.replay(b1); |
| Bundle b2 = EasyMock.createMock(Bundle.class); |
| EasyMock.expect(b2.getState()).andReturn(Bundle.ACTIVE); |
| Dictionary<String, String> headers = new Hashtable<>(); |
| headers.put("Remote-Service", "OSGI-INF/remote-service/"); |
| EasyMock.expect(b2.getHeaders()).andReturn(headers); |
| |
| URL rs3URL = getClass().getResource("/ed3.xml"); |
| URL rs4URL = getClass().getResource("/ed4.xml"); |
| List<URL> urls = Arrays.asList(rs3URL, rs4URL); |
| EasyMock.expect(b2.findEntries("OSGI-INF/remote-service", "*.xml", false)) |
| .andReturn(Collections.enumeration(urls)); |
| EasyMock.replay(b2); |
| |
| Bundle[] bundles = new Bundle[] {b1, b2}; |
| |
| LocalDiscovery ld = new LocalDiscovery(); |
| ld.processExistingBundles(bundles); |
| |
| assertEquals(3, ld.endpointDescriptions.size()); |
| Set<String> expected = new HashSet<>( |
| Arrays.asList("http://somewhere:12345", "http://somewhere:1", "http://somewhere")); |
| Set<String> actual = new HashSet<>(); |
| for (Map.Entry<EndpointDescription, Bundle> entry : ld.endpointDescriptions.entrySet()) { |
| assertSame(b2, entry.getValue()); |
| actual.add(entry.getKey().getId()); |
| } |
| assertEquals(expected, actual); |
| } |
| |
| @Test |
| public void testBundleChanged() throws Exception { |
| LocalDiscovery ld = new LocalDiscovery(); |
| |
| Bundle bundle = EasyMock.createMock(Bundle.class); |
| EasyMock.expect(bundle.getSymbolicName()).andReturn("testing.bundle").anyTimes(); |
| EasyMock.expect(bundle.getState()).andReturn(Bundle.ACTIVE); |
| Dictionary<String, String> headers = new Hashtable<>(); |
| headers.put("Remote-Service", "OSGI-INF/rsa/"); |
| EasyMock.expect(bundle.getHeaders()).andReturn(headers); |
| EasyMock.expect(bundle.findEntries("OSGI-INF/rsa", "*.xml", false)) |
| .andReturn(Collections.enumeration( |
| Collections.singleton(getClass().getResource("/ed3.xml")))); |
| EasyMock.replay(bundle); |
| |
| BundleEvent be0 = new BundleEvent(BundleEvent.INSTALLED, bundle); |
| ld.bundleChanged(be0); |
| assertEquals(0, ld.endpointDescriptions.size()); |
| |
| ServiceReference<EndpointEventListener> sr = epListenerWithScope("(objectClass=*)"); |
| |
| EndpointEventListener endpointListener = EasyMock.createMock(EndpointEventListener.class); |
| endpointListener.endpointChanged(EasyMock.anyObject(EndpointEvent.class), EasyMock.eq("(objectClass=*)")); |
| EasyMock.expectLastCall(); |
| EasyMock.replay(endpointListener); |
| ld.addListener(sr, endpointListener); |
| |
| // Start the bundle |
| BundleEvent be = new BundleEvent(BundleEvent.STARTED, bundle); |
| ld.bundleChanged(be); |
| assertEquals(1, ld.endpointDescriptions.size()); |
| EndpointDescription endpoint = ld.endpointDescriptions.keySet().iterator().next(); |
| assertEquals("http://somewhere:12345", endpoint.getId()); |
| assertSame(bundle, ld.endpointDescriptions.get(endpoint)); |
| |
| EasyMock.verify(endpointListener); |
| |
| // Stop the bundle |
| EasyMock.reset(endpointListener); |
| endpointListener.endpointChanged(EasyMock.anyObject(EndpointEvent.class), EasyMock.eq("(objectClass=*)")); |
| EasyMock.expectLastCall(); |
| EasyMock.replay(endpointListener); |
| |
| BundleEvent be1 = new BundleEvent(BundleEvent.STOPPED, bundle); |
| ld.bundleChanged(be1); |
| assertEquals(0, ld.endpointDescriptions.size()); |
| |
| EasyMock.verify(endpointListener); |
| } |
| |
| @Test |
| public void testEndpointListenerService() throws Exception { |
| LocalDiscovery ld = new LocalDiscovery(); |
| |
| Bundle bundle = createBundle(); |
| BundleEvent event = new BundleEvent(BundleEvent.STARTED, bundle); |
| ld.bundleChanged(event); |
| assertEquals(2, ld.endpointDescriptions.size()); |
| |
| ServiceReference<EndpointEventListener> sr = epListenerWithScope("(objectClass=org.example.ClassA)"); |
| |
| EndpointEventListener el = EasyMock.createMock(EndpointEventListener.class); |
| 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()); |
| ld.addListener(sr, 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))"); |
| |
| EasyMock.reset(el); |
| final Set<String> actualEndpoints = new HashSet<>(); |
| el.endpointChanged(EasyMock.anyObject(EndpointEvent.class), |
| EasyMock.eq("(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))")); |
| EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { |
| public Object answer() throws Throwable { |
| EndpointEvent event = (EndpointEvent) EasyMock.getCurrentArguments()[0]; |
| EndpointDescription endpoint = event.getEndpoint(); |
| actualEndpoints.addAll(endpoint.getInterfaces()); |
| return null; |
| } |
| }).times(2); |
| EasyMock.replay(el); |
| |
| ld.removeListener(el); |
| ld.addListener(sr2, el); |
| assertEquals(1, ld.listenerToFilters.size()); |
| assertEquals(Arrays.asList("(|(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 |
| ld.removeListener(el); |
| assertEquals(0, ld.listenerToFilters.size()); |
| assertEquals(0, ld.filterToListeners.size()); |
| } |
| |
| @Test |
| public void testRegisterTracker() throws Exception { |
| LocalDiscovery ld = new LocalDiscovery(); |
| |
| final Map<String, Object> props = new Hashtable<>(); |
| props.put(EndpointEventListener.ENDPOINT_LISTENER_SCOPE, "(objectClass=Aaaa)"); |
| @SuppressWarnings("unchecked") |
| ServiceReference<EndpointEventListener> sr = EasyMock.createMock(ServiceReference.class); |
| EasyMock.expect(sr.getPropertyKeys()).andReturn(props.keySet().toArray(new String[] {})).anyTimes(); |
| EasyMock.expect(sr.getProperty((String) EasyMock.anyObject())).andAnswer(new IAnswer<Object>() { |
| public Object answer() throws Throwable { |
| return props.get(EasyMock.getCurrentArguments()[0]); |
| } |
| }).anyTimes(); |
| EasyMock.replay(sr); |
| |
| EndpointEventListener endpointListener = EasyMock.createMock(EndpointEventListener.class); |
| EasyMock.replay(endpointListener); |
| |
| assertEquals("Precondition failed", 0, ld.listenerToFilters.size()); |
| assertEquals("Precondition failed", 0, ld.filterToListeners.size()); |
| ld.addListener(sr, endpointListener); |
| |
| assertEquals(1, ld.listenerToFilters.size()); |
| assertEquals(Collections.singletonList("(objectClass=Aaaa)"), ld.listenerToFilters.get(endpointListener)); |
| assertEquals(1, ld.filterToListeners.size()); |
| assertEquals(Collections.singletonList(endpointListener), ld.filterToListeners.get("(objectClass=Aaaa)")); |
| |
| // Add another one with the same scope filter |
| @SuppressWarnings("unchecked") |
| ServiceReference<EndpointEventListener> sr2 = EasyMock.createMock(ServiceReference.class); |
| EasyMock.expect(sr2.getPropertyKeys()).andReturn(props.keySet().toArray(new String[] {})).anyTimes(); |
| EasyMock.expect(sr2.getProperty((String) EasyMock.anyObject())).andAnswer(new IAnswer<Object>() { |
| public Object answer() throws Throwable { |
| return props.get(EasyMock.getCurrentArguments()[0]); |
| } |
| }).anyTimes(); |
| EasyMock.replay(sr2); |
| |
| EndpointEventListener endpointListener2 = EasyMock.createMock(EndpointEventListener.class); |
| EasyMock.replay(endpointListener2); |
| ld.addListener(sr2, endpointListener2); |
| |
| assertEquals(2, ld.listenerToFilters.size()); |
| assertEquals(Collections.singletonList("(objectClass=Aaaa)"), ld.listenerToFilters.get(endpointListener)); |
| assertEquals(Collections.singletonList("(objectClass=Aaaa)"), ld.listenerToFilters.get(endpointListener2)); |
| |
| assertEquals(1, ld.filterToListeners.size()); |
| List<EndpointEventListener> endpointListeners12 = Arrays.asList(endpointListener, endpointListener2); |
| assertEquals(endpointListeners12, ld.filterToListeners.get("(objectClass=Aaaa)")); |
| |
| // Add another listener with a multi-value scope |
| final Map<String, Object> props2 = new Hashtable<>(); |
| props2.put(EndpointEventListener.ENDPOINT_LISTENER_SCOPE, Arrays.asList("(objectClass=X)", "(objectClass=Y)")); |
| @SuppressWarnings("unchecked") |
| ServiceReference<EndpointEventListener> sr3 = EasyMock.createMock(ServiceReference.class); |
| EasyMock.expect(sr3.getPropertyKeys()).andReturn(props2.keySet().toArray(new String[] {})).anyTimes(); |
| EasyMock.expect(sr3.getProperty((String) EasyMock.anyObject())).andAnswer(new IAnswer<Object>() { |
| public Object answer() throws Throwable { |
| return props2.get(EasyMock.getCurrentArguments()[0]); |
| } |
| }).anyTimes(); |
| EasyMock.replay(sr3); |
| |
| EndpointEventListener endpointListener3 = EasyMock.createMock(EndpointEventListener.class); |
| EasyMock.replay(endpointListener3); |
| ld.addListener(sr3, endpointListener3); |
| |
| assertEquals(3, ld.listenerToFilters.size()); |
| assertEquals(Collections.singletonList("(objectClass=Aaaa)"), ld.listenerToFilters.get(endpointListener)); |
| assertEquals(Collections.singletonList("(objectClass=Aaaa)"), ld.listenerToFilters.get(endpointListener2)); |
| assertEquals(Arrays.asList("(objectClass=X)", "(objectClass=Y)"), ld.listenerToFilters.get(endpointListener3)); |
| |
| assertEquals(3, ld.filterToListeners.size()); |
| assertEquals(endpointListeners12, ld.filterToListeners.get("(objectClass=Aaaa)")); |
| assertEquals(Collections.singletonList(endpointListener3), ld.filterToListeners.get("(objectClass=X)")); |
| assertEquals(Collections.singletonList(endpointListener3), ld.filterToListeners.get("(objectClass=Y)")); |
| } |
| |
| @Test |
| public void testClearTracker() throws Exception { |
| LocalDiscovery ld = new LocalDiscovery(); |
| |
| EndpointEventListener endpointListener = EasyMock.createMock(EndpointEventListener.class); |
| ld.listenerToFilters.put(endpointListener, |
| new ArrayList<>(Arrays.asList("(a=b)", "(objectClass=foo.bar.Bheuaark)"))); |
| ld.filterToListeners.put("(a=b)", new ArrayList<>(Arrays.asList(endpointListener))); |
| ld.filterToListeners.put("(objectClass=foo.bar.Bheuaark)", |
| new ArrayList<>(Arrays.asList(endpointListener))); |
| |
| assertEquals(1, ld.listenerToFilters.size()); |
| assertEquals(2, ld.filterToListeners.size()); |
| assertEquals(1, ld.filterToListeners.values().iterator().next().size()); |
| ld.removeListener(EasyMock.createMock(EndpointEventListener.class)); |
| assertEquals(1, ld.listenerToFilters.size()); |
| assertEquals(2, ld.filterToListeners.size()); |
| assertEquals(1, ld.filterToListeners.values().iterator().next().size()); |
| ld.removeListener(endpointListener); |
| assertEquals(0, ld.listenerToFilters.size()); |
| assertEquals(0, ld.filterToListeners.size()); |
| } |
| |
| private ServiceReference<EndpointEventListener> epListenerWithScope(String scope) { |
| final Map<String, Object> props = new Hashtable<>(); |
| props.put(EndpointEventListener.ENDPOINT_LISTENER_SCOPE, new String[] {scope}); |
| return mockService(props); |
| } |
| |
| private ServiceReference<EndpointEventListener> mockService(final Map<String, Object> props) { |
| @SuppressWarnings("unchecked") |
| ServiceReference<EndpointEventListener> sr = EasyMock.createMock(ServiceReference.class); |
| EasyMock.expect(sr.getPropertyKeys()).andReturn(props.keySet().toArray(new String[] {})).anyTimes(); |
| EasyMock.expect(sr.getProperty((String) EasyMock.anyObject())).andAnswer(new IAnswer<Object>() { |
| public Object answer() throws Throwable { |
| return props.get(EasyMock.getCurrentArguments()[0]); |
| } |
| }).anyTimes(); |
| |
| EasyMock.replay(sr); |
| return sr; |
| } |
| |
| private Bundle createBundle() { |
| Bundle bundle = EasyMock.createMock(Bundle.class); |
| EasyMock.expect(bundle.getState()).andReturn(Bundle.ACTIVE); |
| Dictionary<String, String> headers = new Hashtable<>(); |
| headers.put("Remote-Service", "OSGI-INF/rsa/ed4.xml"); |
| EasyMock.expect(bundle.getHeaders()).andReturn(headers); |
| EasyMock.expect(bundle.findEntries("OSGI-INF/rsa", "ed4.xml", false)) |
| .andReturn(Collections.enumeration( |
| Collections.singleton(getClass().getResource("/ed4.xml")))); |
| EasyMock.replay(bundle); |
| return bundle; |
| } |
| } |