blob: 59b3c3fc8562f2d984b95d447215f7ee483d8ab4 [file] [log] [blame]
/**
* 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;
}
}