Mercurial > hg > release > thermostat-0.4
changeset 516:dc7425e6574c
fix activator test and introduce MultipleServiceTracker
reviewed-by: neugens
review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-August/002570.html
A bundle which requires multiple externally-provided services needs to do some
osgi gymnastics. This introduces a single class to perform this behaviour, and
as a side effect greatly simplifies the testing of activators that need this
behaviour.
author | Jon VanAlten <jon.vanalten@redhat.com> |
---|---|
date | Thu, 02 Aug 2012 13:11:13 -0400 |
parents | ac3d23577264 |
children | 4565a2c69167 |
files | common/core/src/main/java/com/redhat/thermostat/common/MultipleServiceTracker.java common/core/src/test/java/com/redhat/thermostat/common/MultipleServiceTrackerTest.java distribution/config/bundles.properties launcher/pom.xml launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java launcher/src/test/java/com/redhat/thermostat/launcher/LauncherTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java main/src/main/resources/com/redhat/thermostat/main/impl/bootstrapbundles.properties |
diffstat | 9 files changed, 400 insertions(+), 127 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/MultipleServiceTracker.java Thu Aug 02 13:11:13 2012 -0400 @@ -0,0 +1,153 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; + +/** + * + * This class is intended to be used within BundleActivator implementations that require + * some action be taken only after certain services have appeared. It is not actually + * an extension to the ServiceTracker class, but embeds a number of ServiceTracker objects + * (one per required service) nonetheless. + * + */ +public class MultipleServiceTracker { + + public interface Action { + public void doIt(); + } + + class InternalServiceTrackerCustomizer implements ServiceTrackerCustomizer { + + private static final String OBJECT_CLASS = "objectClass"; + private ServiceTracker tracker; + + void setTracker(ServiceTracker tracker) { + this.tracker = tracker; + } + + @Override + public Object addingService(ServiceReference reference) { + ensureTracker(); + services.put(getServiceClassName(reference), context.getService(reference)); + if (allServicesReady()) { + action.doIt(); + } + return tracker.addingService(reference); + } + + @Override + public void modifiedService(ServiceReference reference, Object service) { + // We don't actually need to do anything here. + ensureTracker(); + tracker.modifiedService(reference, service); + } + + @Override + public void removedService(ServiceReference reference, Object service) { + ensureTracker(); + services.put(getServiceClassName(reference), null); + tracker.removedService(reference, service); + } + + private void ensureTracker() { + if (tracker == null) { + // This class is used only internally, and is initialized within the constructor. The trackers that could + // be generating events cannot be opened except by calling open on the enclosing class, so this should + // never ever ever ever happen. + throw new IllegalStateException("Trackers should not be opened before this guy has been set."); + } + } + + private Object getServiceClassName(ServiceReference reference) { + return ((String[]) reference.getProperty(OBJECT_CLASS))[0]; + } + } + + private Map<Object, Object> services; + private Collection<ServiceTracker> trackers; + private Action action; + private BundleContext context; + + public MultipleServiceTracker(BundleContext context, Class[] classes, Action action) { + action.getClass(); + context.getClass(); + classes.getClass(); // Harmless call to cause NPE if passed null. + this.context = context; + services = new HashMap<>(); + trackers = new ArrayList<>(); + for (Class clazz: classes) { + InternalServiceTrackerCustomizer tc = new InternalServiceTrackerCustomizer(); + ServiceTracker tracker = new ServiceTracker(context, clazz.getName(), tc); + tc.setTracker(tracker); + trackers.add(tracker); + services.put(clazz.getName(), null); + } + this.action = action; + } + + public void open() { + for (ServiceTracker tracker : trackers) { + tracker.open(); + } + } + + public void close() { + for (ServiceTracker tracker: trackers) { + tracker.close(); + } + } + + private boolean allServicesReady() { + for (Entry<Object, Object> entry: services.entrySet()) { + if (entry.getValue() == null) { + return false; + } + } + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/test/java/com/redhat/thermostat/common/MultipleServiceTrackerTest.java Thu Aug 02 13:11:13 2012 -0400 @@ -0,0 +1,139 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import com.redhat.thermostat.common.MultipleServiceTracker.Action; +import com.redhat.thermostat.common.MultipleServiceTracker.InternalServiceTrackerCustomizer; + +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.verifyNew; +import static org.powermock.api.mockito.PowerMockito.whenNew; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MultipleServiceTracker.class, InternalServiceTrackerCustomizer.class}) +public class MultipleServiceTrackerTest { + + private Action action; + private BundleContext context; + private ServiceTracker objectTracker, stringTracker; + private ServiceReference objectReference, stringReference; + + @Before + public void setUp() throws Exception { + action = mock(Action.class); + context = mock(BundleContext.class); + + objectReference = mock(ServiceReference.class); + String[] objObjectClassProperty = {Object.class.getName()}; + when(objectReference.getProperty(eq("objectClass"))).thenReturn(objObjectClassProperty); + when(context.getService(objectReference)).thenReturn(new Object()); + objectTracker = mock(ServiceTracker.class); + whenNew(ServiceTracker.class). + withParameterTypes(BundleContext.class, String.class, ServiceTrackerCustomizer.class). + withArguments(eq(context), eq(Object.class.getName()), + isA(ServiceTrackerCustomizer.class)).thenReturn(objectTracker); + + stringReference = mock(ServiceReference.class); + String[] stringObjectClassProperty = {String.class.getName()}; + when(stringReference.getProperty(eq("objectClass"))).thenReturn(stringObjectClassProperty); + when(context.getService(stringReference)).thenReturn("foo"); + stringTracker = mock(ServiceTracker.class); + whenNew(ServiceTracker.class). + withParameterTypes(BundleContext.class, String.class, ServiceTrackerCustomizer.class). + withArguments(eq(context), eq(String.class.getName()), + isA(ServiceTrackerCustomizer.class)).thenReturn(stringTracker); + } + + @Test + public void testSingleClass() throws Exception { + + Class[] deps = { Object.class }; + MultipleServiceTracker tracker = new MultipleServiceTracker(context, deps, action); + + ArgumentCaptor<ServiceTrackerCustomizer> customizerCaptor = ArgumentCaptor.forClass(ServiceTrackerCustomizer.class); + verifyNew(ServiceTracker.class).withArguments(eq(context), + eq(Object.class.getName()), + customizerCaptor.capture()); + ServiceTrackerCustomizer customizer = customizerCaptor.getValue(); + + tracker.open(); + verify(objectTracker).open(); + + customizer.addingService(objectReference); + verify(action).doIt(); + } + + @Test + public void testMultipleClasses() throws Exception { + Class[] deps = { Object.class, String.class }; + MultipleServiceTracker tracker = new MultipleServiceTracker(context, deps, action); + + ArgumentCaptor<ServiceTrackerCustomizer> customizerCaptor = ArgumentCaptor.forClass(ServiceTrackerCustomizer.class); + verifyNew(ServiceTracker.class).withArguments(eq(context), + eq(Object.class.getName()), + customizerCaptor.capture()); + verifyNew(ServiceTracker.class).withArguments(eq(context), + eq(String.class.getName()), + customizerCaptor.capture()); + ServiceTrackerCustomizer customizer = customizerCaptor.getValue(); + + tracker.open(); + verify(objectTracker).open(); + verify(stringTracker).open(); + + customizer.addingService(objectReference); + customizer.addingService(stringReference); + verify(action).doIt(); + } + + +}
--- a/distribution/config/bundles.properties Thu Aug 02 13:11:13 2012 -0400 +++ b/distribution/config/bundles.properties Thu Aug 02 13:11:13 2012 -0400 @@ -1,4 +1,5 @@ launcher = thermostat-launcher-@project.version@.jar, \ + thermostat-keyring-@project.version@.jar, \ thermostat-common-core-@project.version@.jar, \ thermostat-osgi-process-handler-@project.version@.jar, \ thermostat-tools-@project.version@.jar, \
--- a/launcher/pom.xml Thu Aug 02 13:11:13 2012 -0400 +++ b/launcher/pom.xml Thu Aug 02 13:11:13 2012 -0400 @@ -119,5 +119,8 @@ <scope>test</scope> </dependency> </dependencies> - + + <properties> + <argLine>-XX:-UseSplitVerifier</argLine> + </properties> </project>
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java Thu Aug 02 13:11:13 2012 -0400 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java Thu Aug 02 13:11:13 2012 -0400 @@ -39,24 +39,45 @@ import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; -import org.osgi.util.tracker.ServiceTracker; import com.redhat.thermostat.bundles.OSGiRegistryService; import com.redhat.thermostat.common.CommandLoadingBundleActivator; +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.MultipleServiceTracker.Action; import com.redhat.thermostat.common.cli.CommandContextFactory; import com.redhat.thermostat.launcher.Launcher; import com.redhat.thermostat.utils.keyring.Keyring; public class Activator extends CommandLoadingBundleActivator { + class RegisterLauncherAction implements Action { + + private BundleContext context; + + RegisterLauncherAction(BundleContext context) { + this.context = context; + } + @Override + public void doIt() { + ServiceReference reference = context.getServiceReference(OSGiRegistryService.class); + OSGiRegistryService bundleService = (OSGiRegistryService) context.getService(reference); + LauncherImpl launcher = new LauncherImpl(context, + new CommandContextFactory(context), bundleService); + launcherServiceRegistration = context.registerService(Launcher.class.getName(), launcher, null); + } + + } + + @SuppressWarnings("rawtypes") private ServiceRegistration launcherServiceRegistration; - private ServiceTracker bundleRegistryServiceTracker, keyringServiceTracker; + @SuppressWarnings("rawtypes") + private MultipleServiceTracker tracker; @Override public void start(final BundleContext context) throws Exception { super.start(context); - keyringServiceTracker = new KeyringServiceTracker(context); - keyringServiceTracker.open(); + tracker = new MultipleServiceTracker(context, new Class[] {OSGiRegistryService.class, Keyring.class}, new RegisterLauncherAction(context)); + tracker.open(); } @Override @@ -65,46 +86,8 @@ if (launcherServiceRegistration != null) { launcherServiceRegistration.unregister(); } - if (bundleRegistryServiceTracker != null) { - bundleRegistryServiceTracker.close(); - } - if (keyringServiceTracker != null) { - keyringServiceTracker.close(); - } - } - - private class KeyringServiceTracker extends ServiceTracker { - public KeyringServiceTracker(BundleContext context) { - super(context, Keyring.class.getName(), null); - } - - @Override - public Object addingService(ServiceReference reference) { - bundleRegistryServiceTracker = new OSGiRegistryServiceTracker(context); - bundleRegistryServiceTracker.open(); - - return super.addingService(reference); + if (tracker != null) { + tracker.close(); } } - - private class OSGiRegistryServiceTracker extends ServiceTracker { - - private CommandContextFactory cmdContextFactory; - - public OSGiRegistryServiceTracker(BundleContext context) { - super(context, OSGiRegistryService.class.getName(), null); - this.cmdContextFactory = new CommandContextFactory(context); - } - - @Override - public Object addingService(ServiceReference reference) { - OSGiRegistryService bundleService = (OSGiRegistryService) context.getService(reference); - LauncherImpl launcher = new LauncherImpl(cmdContextFactory, bundleService); - launcher.setBundleContext(context); - launcherServiceRegistration = context.registerService(Launcher.class.getName(), launcher, null); - - return super.addingService(reference); - } - } - }
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java Thu Aug 02 13:11:13 2012 -0400 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java Thu Aug 02 13:11:13 2012 -0400 @@ -56,7 +56,6 @@ import com.redhat.thermostat.common.cli.CommandContextFactory; import com.redhat.thermostat.common.cli.CommandException; import com.redhat.thermostat.common.cli.CommandRegistry; -import com.redhat.thermostat.common.cli.OSGiContext; import com.redhat.thermostat.common.config.ClientPreferences; import com.redhat.thermostat.common.config.InvalidConfigurationException; import com.redhat.thermostat.common.storage.ConnectionException; @@ -66,7 +65,7 @@ import com.redhat.thermostat.launcher.Launcher; import com.redhat.thermostat.utils.keyring.Keyring; -public class LauncherImpl implements Launcher, OSGiContext { +public class LauncherImpl implements Launcher { private static final String UNKNOWN_COMMAND_MESSAGE = "unknown command '%s'\n"; @@ -82,17 +81,14 @@ private BundleContext context; private OSGiRegistryService registry; - public LauncherImpl(CommandContextFactory cmdCtxFactory, OSGiRegistryService registry) { + public LauncherImpl(BundleContext context, CommandContextFactory cmdCtxFactory, + OSGiRegistryService registry) { + this.context = context; this.cmdCtxFactory = cmdCtxFactory; this.registry = registry; } @Override - public void setBundleContext(BundleContext context) { - this.context = context; - } - - @Override public synchronized void run() { usageCount++; try {
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/LauncherTest.java Thu Aug 02 13:11:13 2012 -0400 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/LauncherTest.java Thu Aug 02 13:11:13 2012 -0400 @@ -256,11 +256,9 @@ }); ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(errorCmd)); - LauncherImpl launcher = new LauncherImpl(ctxFactory, registry); + LauncherImpl launcher = new LauncherImpl(bundleContext, ctxFactory, registry); Keyring keyring = mock(Keyring.class); launcher.setPreferences(new ClientPreferences(keyring)); - - launcher.setBundleContext(bundleContext); launcher.setArgs(new String[] { "error" }); launcher.run(); assertEquals("test error\n", ctxFactory.getError()); @@ -268,12 +266,10 @@ } private void runAndVerifyCommand(String[] args, String expected) { - LauncherImpl launcher = new LauncherImpl(ctxFactory, registry); + LauncherImpl launcher = new LauncherImpl(bundleContext, ctxFactory, registry); Keyring keyring = mock(Keyring.class); launcher.setPreferences(new ClientPreferences(keyring)); - - launcher.setBundleContext(bundleContext); launcher.setArgs(args); launcher.run(); assertEquals(expected, ctxFactory.getOutput()); @@ -282,8 +278,7 @@ @Test public void verifyStorageCommandSetsUpDAOFactory() { - LauncherImpl launcher = new LauncherImpl(ctxFactory, registry); - launcher.setBundleContext(bundleContext); + LauncherImpl launcher = new LauncherImpl(bundleContext, ctxFactory, registry); Keyring keyring = mock(Keyring.class); launcher.setPreferences(new ClientPreferences(keyring)); @@ -294,8 +289,7 @@ @Test public void verifyStorageCommandSetsUpDAOFactoryWithAuth() { - LauncherImpl launcher = new LauncherImpl(ctxFactory, registry); - launcher.setBundleContext(bundleContext); + LauncherImpl launcher = new LauncherImpl(bundleContext, ctxFactory, registry); Keyring keyring = mock(Keyring.class); launcher.setPreferences(new ClientPreferences(keyring)); @@ -307,8 +301,7 @@ public void verifyPrefsAreUsed() { ClientPreferences prefs = mock(ClientPreferences.class); when(prefs.getConnectionUrl()).thenReturn("mongo://fluff:12345"); - LauncherImpl l = new LauncherImpl(ctxFactory, registry); - l.setBundleContext(bundleContext); + LauncherImpl l = new LauncherImpl(bundleContext, ctxFactory, registry); l.setPreferences(prefs); l.setArgs(new String[] { "test3" }); l.run();
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java Thu Aug 02 13:11:13 2012 -0400 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java Thu Aug 02 13:11:13 2012 -0400 @@ -37,93 +37,97 @@ package com.redhat.thermostat.launcher.internal; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.doNothing; +import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.powermock.api.mockito.PowerMockito.verifyNew; +import static org.powermock.api.mockito.PowerMockito.whenNew; import java.util.Dictionary; -import java.util.HashMap; import java.util.Hashtable; -import java.util.Map; -import java.util.Map.Entry; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceEvent; -import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import com.redhat.thermostat.bundles.OSGiRegistryService; +import com.redhat.thermostat.common.CommandLoadingBundleActivator; +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.MultipleServiceTracker.Action; import com.redhat.thermostat.common.cli.Command; import com.redhat.thermostat.launcher.Launcher; +import com.redhat.thermostat.launcher.internal.Activator.RegisterLauncherAction; +import com.redhat.thermostat.utils.keyring.Keyring; +@RunWith(PowerMockRunner.class) +@PrepareForTest({Activator.class, CommandLoadingBundleActivator.class, RegisterLauncherAction.class, BundleActivator.class}) public class ActivatorTest { + private BundleContext context; + private MultipleServiceTracker tracker; + private ServiceReference registryServiceReference, helpCommandReference; + private ServiceRegistration launcherServiceRegistration, helpCommandRegistration; + private OSGiRegistryService registryService; + private Command helpCommand; + + @Before + public void setUp() throws Exception { + context = mock(BundleContext.class); + + registryServiceReference = mock(ServiceReference.class); + launcherServiceRegistration = mock(ServiceRegistration.class); + registryService = mock(OSGiRegistryService.class); + when(context.getServiceReference(eq(OSGiRegistryService.class))).thenReturn(registryServiceReference); + when(context.getService(eq(registryServiceReference))).thenReturn(registryService); + when(context.registerService(eq(Launcher.class.getName()), any(), (Dictionary) isNull())). + thenReturn(launcherServiceRegistration); + + helpCommandRegistration = mock(ServiceRegistration.class); + helpCommandReference = mock(ServiceReference.class); + helpCommand = mock(Command.class); + when(helpCommandRegistration.getReference()).thenReturn(helpCommandReference); + when(context.registerService(eq(Command.class.getName()), any(), isA(Dictionary.class))). + thenReturn(helpCommandRegistration); + when(context.getService(helpCommandReference)).thenReturn(helpCommand); + + tracker = mock(MultipleServiceTracker.class); + whenNew(MultipleServiceTracker.class). + withParameterTypes(BundleContext.class, Class[].class, Action.class). + withArguments(eq(context), eq(new Class[] {OSGiRegistryService.class, Keyring.class}), + isA(Action.class)).thenReturn(tracker); + } + @Test - public void testRegisterServices() throws Exception { - final Map<ServiceRegistration, Object> regs = new HashMap<>(); - BundleContext bCtx = mock(BundleContext.class); - - when(bCtx.registerService(anyString(), any(), any(Dictionary.class))).then(new Answer<ServiceRegistration>() { + public void testActivatorLifecycle() throws Exception { + Activator activator = new Activator(); - @Override - public ServiceRegistration answer(InvocationOnMock invocation) throws Throwable { - ServiceRegistration reg = mock(ServiceRegistration.class); - when(reg.getReference()).thenReturn(mock(ServiceReference.class)); - regs.put(reg, invocation.getArguments()[1]); - return reg; - } - }); - when(bCtx.getService(isA(ServiceReference.class))).then(new Answer<Object>() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - ServiceReference ref = (ServiceReference) invocation.getArguments()[0]; - for (Entry<ServiceRegistration,Object> registration: regs.entrySet()) { - if (registration.getKey().getReference().equals(ref)) { - return registration.getValue(); - } - } - return null; - } - }); - - ArgumentCaptor<ServiceListener> serviceCaptor = ArgumentCaptor.forClass(ServiceListener.class); - doNothing().when(bCtx).addServiceListener(serviceCaptor.capture()); + activator.start(context); - Activator activator = new Activator(); - activator.start(bCtx); - - verify(bCtx).addServiceListener(serviceCaptor.capture(), anyString()); - ServiceListener listener = serviceCaptor.getValue(); - - ServiceReference reference = mock(ServiceReference.class); - ServiceEvent event = mock(ServiceEvent.class); - when(event.getServiceReference()).thenReturn(reference); - when(event.getType()).thenReturn(ServiceEvent.REGISTERED); - - listener.serviceChanged(event); - verify(event).getServiceReference(); - - - Hashtable<String, Object> props = new Hashtable<>(); props.put(Command.NAME, "help"); - verify(bCtx).registerService(eq(Command.class.getName()), isA(HelpCommand.class), eq(props)); + verify(context).registerService(eq(Command.class.getName()), isA(HelpCommand.class), eq(props)); - verify(bCtx).registerService(eq(Launcher.class.getName()), isA(Launcher.class), any(Dictionary.class)); - - activator.stop(bCtx); + ArgumentCaptor<Action> actionCaptor = ArgumentCaptor.forClass(Action.class); + verifyNew(MultipleServiceTracker.class).withArguments(eq(context), + eq(new Class[] {OSGiRegistryService.class, Keyring.class}), + actionCaptor.capture()); + Action action = actionCaptor.getValue(); - for (ServiceRegistration reg : regs.keySet()) { - verify(reg).unregister(); - } + action.doIt(); + verify(context).registerService(eq(Launcher.class.getName()), isA(Launcher.class), (Dictionary) isNull()); + + activator.stop(context); + verify(launcherServiceRegistration).unregister(); + verify(tracker).close(); } - }
--- a/main/src/main/resources/com/redhat/thermostat/main/impl/bootstrapbundles.properties Thu Aug 02 13:11:13 2012 -0400 +++ b/main/src/main/resources/com/redhat/thermostat/main/impl/bootstrapbundles.properties Thu Aug 02 13:11:13 2012 -0400 @@ -1,4 +1,5 @@ -bundles=thermostat-common-core-${project.version}.jar, \ +bundles=thermostat-keyring-${project.version}.jar, \ + thermostat-common-core-${project.version}.jar, \ thermostat-bundles-${project.version}.jar, \ thermostat-tools-${project.version}.jar, \ thermostat-launcher-${project.version}.jar, \