blob: 79c485e5c8e41bfefdd5c273b1d00538f48e3c67 [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.core;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.hamcrest.Matchers.array;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.apache.aries.rsa.core.event.EventProducer;
import org.apache.aries.rsa.spi.DistributionProvider;
import org.apache.aries.rsa.spi.Endpoint;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.easymock.IMocksControl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
import org.osgi.service.remoteserviceadmin.EndpointDescription;
import org.osgi.service.remoteserviceadmin.ExportReference;
import org.osgi.service.remoteserviceadmin.ExportRegistration;
import org.osgi.service.remoteserviceadmin.ImportRegistration;
import org.osgi.service.remoteserviceadmin.RemoteConstants;
@SuppressWarnings({
"rawtypes", "unchecked"
})
public class RemoteServiceAdminCoreTest {
private static final String MYCONFIG = "myconfig";
private IMocksControl c;
private BundleContext rsaContext;
private RemoteServiceAdminCore rsaCore;
private BundleContext apiContext;
private DummyProvider provider;
@Before
public void setup() throws InvalidSyntaxException {
c = EasyMock.createControl();
rsaContext = c.createMock(BundleContext.class);
Bundle b = createDummyRsaBundle(rsaContext);
expect(rsaContext.getProperty(Constants.FRAMEWORK_VERSION)).andReturn("1111").anyTimes();
expect(rsaContext.getProperty(Constants.FRAMEWORK_UUID)).andReturn("some_uuid1").anyTimes();
expect(rsaContext.getBundle()).andReturn(b).anyTimes();
apiContext = c.createMock(BundleContext.class);
provider = new DummyProvider();
PackageUtil packageUtil = new PackageUtil(rsaContext) {
@Override
public String getVersion(Class<?> iClass) {
return "1.0.0";
}
};
EventProducer eventProducer = new EventProducer(rsaContext) {
protected void notifyListeners(org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent rsae) {
// skip
}
};
rsaCore = new RemoteServiceAdminCore(rsaContext, apiContext, eventProducer, provider, packageUtil) {
protected void createServiceListener() {}
};
}
@Test
public void testDontExportOwnServiceProxies() throws InvalidSyntaxException {
Map<String, Object> sProps = new HashMap<>();
sProps.put("objectClass", new String[] {"a.b.C"});
sProps.put(RemoteConstants.SERVICE_IMPORTED, true);
sProps.put("service.exported.interfaces", "*");
ServiceReference sref = mockServiceReference(sProps);
c.replay();
List<ExportRegistration> exRefs = rsaCore.exportService(sref, null);
assertNotNull(exRefs);
assertEquals(0, exRefs.size());
assertEquals(rsaCore.getExportedServices().size(), 0);
c.verify();
}
@Test
public void testDoNotImportUnsupportedConfig() {
EndpointDescription endpoint = createEndpointDesc("unsupportedConfiguration");
c.replay();
assertNull(rsaCore.importService(endpoint));
assertEquals(0, rsaCore.getImportedEndpoints().size());
c.verify();
}
@Test
public void testImport() {
expect(apiContext.registerService(EasyMock.aryEq(new String[]{"es.schaaf.my.class"}), anyObject(), anyObject())).andReturn(null);
c.replay();
EndpointDescription endpoint2 = createEndpointDesc(MYCONFIG);
ImportRegistration ireg = rsaCore.importService(endpoint2);
assertNotNull(ireg);
assertEquals(1, rsaCore.getImportedEndpoints().size());
// lets import the same endpoint once more -> should get a copy of the ImportRegistration
ImportRegistration ireg2 = rsaCore.importService(endpoint2);
assertNotNull(ireg2);
assertEquals(2, rsaCore.getImportedEndpoints().size());
assertEquals(ireg.getImportReference(), (rsaCore.getImportedEndpoints().toArray())[0]);
assertEquals(ireg.getImportReference().getImportedEndpoint(), ireg2.getImportReference()
.getImportedEndpoint());
// remove the registration
// first call shouldn't remove the import
ireg2.close();
assertEquals(1, rsaCore.getImportedEndpoints().size());
// second call should really close and remove the import
ireg.close();
assertEquals(0, rsaCore.getImportedEndpoints().size());
c.verify();
}
@Test
public void testImportWithMultipleInterfaces() {
expect(apiContext.registerService(EasyMock.aryEq(new String[]{"es.schaaf.my.class", "java.lang.Runnable"}), anyObject(), anyObject())).andReturn(null);
c.replay();
Map<String, Object> p = new HashMap<>();
p.put(RemoteConstants.ENDPOINT_ID, "http://google.de");
p.put(Constants.OBJECTCLASS, new String[] {
"es.schaaf.my.class",
"java.lang.Runnable"
});
p.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, MYCONFIG);
EndpointDescription endpoint = new EndpointDescription(p);
ImportRegistration ireg = rsaCore.importService(endpoint);
assertNotNull(ireg);
assertEquals(1, rsaCore.getImportedEndpoints().size());
// lets import the same endpoint once more -> should get a copy of the ImportRegistration
ImportRegistration ireg2 = rsaCore.importService(endpoint);
assertNotNull(ireg2);
assertEquals(2, rsaCore.getImportedEndpoints().size());
assertEquals(ireg.getImportReference(), (rsaCore.getImportedEndpoints().toArray())[0]);
assertEquals(ireg.getImportReference().getImportedEndpoint(), ireg2.getImportReference()
.getImportedEndpoint());
EndpointDescription importedEndpoint = ireg.getImportReference().getImportedEndpoint();
assertEquals(2, importedEndpoint.getInterfaces().size());
c.verify();
}
@Test
public void testExport() throws Exception {
final Map<String, Object> sProps = new HashMap<>();
sProps.put("objectClass", new String[] {"java.lang.Runnable"});
sProps.put("service.id", 51L);
sProps.put("myProp", "myVal");
sProps.put("service.exported.interfaces", "*");
ServiceReference sref = mockServiceReference(sProps);
provider.endpoint = createEndpoint(sProps);
ServiceReference sref2 = mockServiceReference(sProps);
c.replay();
// Export the service for the first time
List<ExportRegistration> eregs = rsaCore.exportService(sref, null);
assertEquals(1, eregs.size());
ExportRegistration ereg = eregs.iterator().next();
assertNull(ereg.getException());
assertSame(sref, ereg.getExportReference().getExportedService());
EndpointDescription endpoint = ereg.getExportReference().getExportedEndpoint();
Map<String, Object> edProps = endpoint.getProperties();
assertEquals("http://something", edProps.get("endpoint.id"));
assertNotNull(edProps.get("service.imported"));
assertThat((String[]) edProps.get("objectClass"), array(equalTo("java.lang.Runnable")));
assertThat((String[]) edProps.get("service.imported.configs"), array(equalTo(MYCONFIG)));
// Ask to export the same service again, this should not go through the whole process again but simply return
// a copy of the first instance.
List<ExportRegistration> eregs2 = rsaCore.exportService(sref2, null);
assertEquals(1, eregs2.size());
ExportRegistration ereg2 = eregs2.iterator().next();
assertNull(ereg2.getException());
assertEquals(ereg.getExportReference().getExportedEndpoint().getProperties(),
ereg2.getExportReference().getExportedEndpoint().getProperties());
assertNumExports(2);
ereg.close();
assertNumExports(1);
ereg2.close();
assertNumExports(0);
}
private void assertNumExports(int expectedNum) {
assertThat("Number of export references", rsaCore.getExportedServices().size(), equalTo(expectedNum));
}
@Test
public void testExportWrongConfig() throws Exception {
final Map<String, Object> sProps = new HashMap<>();
sProps.put("objectClass", new String[] {"java.lang.Runnable"});
sProps.put("service.id", 51L);
sProps.put("myProp", "myVal");
sProps.put("service.exported.interfaces", "*");
sProps.put(RemoteConstants.SERVICE_EXPORTED_CONFIGS, "org.apache.cxf.ws");
ServiceReference sref = mockServiceReference(sProps);
c.replay();
List<ExportRegistration> ereg = rsaCore.exportService(sref, null);
// Service should not be exported as the exported config does not match
assertEquals(0, ereg.size());
c.verify();
}
@Test
public void testExportOneConfigSupported() throws Exception {
final Map<String, Object> sProps = new HashMap<>();
sProps.put("objectClass", new String[] {"java.lang.Runnable"});
sProps.put("service.id", 51L);
sProps.put("myProp", "myVal");
sProps.put("service.exported.interfaces", "*");
sProps.put(RemoteConstants.SERVICE_EXPORTED_CONFIGS, new String[]{MYCONFIG, "aconfig"});
ServiceReference sref = mockServiceReference(sProps);
provider.endpoint = createEndpoint(sProps);
c.replay();
List<ExportRegistration> ereg = rsaCore.exportService(sref, null);
assertEquals(1, ereg.size());
ExportRegistration first = ereg.iterator().next();
EndpointDescription exportedEndpoint = first.getExportReference().getExportedEndpoint();
assertThat(exportedEndpoint.getConfigurationTypes(), contains(MYCONFIG));
}
@Test
public void testExportException() throws Exception {
final Map<String, Object> sProps = new HashMap<>();
sProps.put("objectClass", new String[] {"java.lang.Runnable"});
sProps.put("service.id", 51L);
sProps.put("service.exported.interfaces", "*");
ServiceReference sref = mockServiceReference(sProps);
c.replay();
provider.ex = new TestException();
List<ExportRegistration> ereg = rsaCore.exportService(sref, sProps);
assertEquals(1, ereg.size());
assertTrue(ereg.get(0).getException() instanceof TestException);
Collection<ExportReference> exportedServices = rsaCore.getExportedServices();
assertEquals("No service was exported", 0, exportedServices.size());
c.verify();
}
@Test
public void testCreateEndpointProps() {
c.replay();
Map<String, Object> sd = new HashMap<>();
sd.put(org.osgi.framework.Constants.SERVICE_ID, 42);
Map<String, Object> props = rsaCore.createEndpointProps(sd, new Class[]{String.class});
Assert.assertFalse(props.containsKey(org.osgi.framework.Constants.SERVICE_ID));
assertEquals(42, props.get(RemoteConstants.ENDPOINT_SERVICE_ID));
assertEquals("some_uuid1", props.get(RemoteConstants.ENDPOINT_FRAMEWORK_UUID));
assertEquals(Arrays.asList("java.lang.String"),
Arrays.asList((Object[]) props.get(org.osgi.framework.Constants.OBJECTCLASS)));
assertEquals("1.0.0", props.get("endpoint.package.version.java.lang"));
c.verify();
}
private Endpoint createEndpoint(final Map<String, Object> sProps) throws IOException {
Map<String, Object> eProps = new HashMap<>(sProps);
eProps.put("endpoint.id", "http://something");
eProps.put("service.imported.configs", new String[] {MYCONFIG});
final EndpointDescription epd = new EndpointDescription(eProps);
Endpoint er = c.createMock(Endpoint.class);
expect(er.description()).andReturn(epd).anyTimes();
er.close();
expectLastCall();
return er;
}
private Bundle createDummyRsaBundle(BundleContext bc) {
Bundle b = c.createMock(Bundle.class);
expect(b.getBundleContext()).andReturn(bc).anyTimes();
expect(b.getSymbolicName()).andReturn("rsabundle").anyTimes();
expect(b.getBundleId()).andReturn(10L).anyTimes();
expect(b.getVersion()).andReturn(new Version("1.0.0")).anyTimes();
expect(b.getHeaders()).andReturn(new Hashtable<>()).anyTimes();
return b;
}
private ServiceReference mockServiceReference(final Map<String, Object> sProps) {
BundleContext bc = c.createMock(BundleContext.class);
Bundle sb = c.createMock(Bundle.class);
expect(sb.getBundleContext()).andReturn(bc).anyTimes();
expect(bc.getBundle()).andReturn(sb).anyTimes();
String[] propKeys = sProps.keySet().toArray(new String[] {});
ServiceReference sref = c.createMock(ServiceReference.class);
expect(sref.getBundle()).andReturn(sb).anyTimes();
expect(sref.getPropertyKeys()).andReturn(propKeys).anyTimes();
expect(sref.getProperty(EasyMock.anyObject())).andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
return sProps.get(EasyMock.getCurrentArguments()[0]);
}
}).anyTimes();
Runnable svcObject = c.createMock(Runnable.class);
expect(bc.getService(sref)).andReturn(svcObject).anyTimes();
return sref;
}
private EndpointDescription createEndpointDesc(String configType) {
Map<String, Object> p = new HashMap<>();
p.put(RemoteConstants.ENDPOINT_ID, "http://google.de");
p.put(Constants.OBJECTCLASS, new String[] {
"es.schaaf.my.class"
});
p.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, configType);
return new EndpointDescription(p);
}
@SuppressWarnings("serial")
private static class TestException extends RuntimeException {
}
class DummyProvider implements DistributionProvider {
Endpoint endpoint;
RuntimeException ex;
@Override
public String[] getSupportedTypes() {
return new String[]{MYCONFIG};
}
@Override
public Endpoint exportService(Object serviceO, BundleContext serviceContext,
Map<String, Object> effectiveProperties, Class[] exportedInterfaces) {
if (ex != null) {
throw ex;
}
return endpoint;
}
@Override
public Object importEndpoint(ClassLoader cl, BundleContext consumerContext, Class[] interfaces,
EndpointDescription endpoint) {
return null;
}
}
}