Mercurial > hg > release > thermostat-2.0
changeset 2326:f3e9a2a84291
Add tab completion to storage-populator -c
Corrected patch to replace revision 52d7d3d03fa7.
Reviewed-by: jerboaa, jaziz
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-May/019019.html
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-June/019105.html
line wrap: on
line diff
--- a/common/test/src/main/java/com/redhat/thermostat/testutils/Asserts.java Wed Jun 01 16:30:42 2016 -0400 +++ b/common/test/src/main/java/com/redhat/thermostat/testutils/Asserts.java Wed Jun 01 16:34:12 2016 -0400 @@ -63,9 +63,16 @@ } public static <T, U extends T> void assertServiceIsRegistered(StubBundleContext context, Class<T> service, Class<U> implementation) { - if (!(context.isServiceRegistered(service.getName(), implementation))) { + if (!context.isServiceRegistered(service.getName(), implementation)) { throw new AssertionError("Service " + implementation.getName() + " is not registered under the API " + service.getName()); } } + + public static <T, U extends T> void assertServiceIsNotRegistered(StubBundleContext context, Class<T> service, Class<U> implementation) { + if (context.isServiceRegistered(service.getName(), implementation)) { + throw new AssertionError("Service " + implementation.getName() + " is registered under the API " + service.getName()); + } + } + }
--- a/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/StoragePopulatorCommand.java Wed Jun 01 16:30:42 2016 -0400 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/StoragePopulatorCommand.java Wed Jun 01 16:34:12 2016 -0400 @@ -70,6 +70,8 @@ public class StoragePopulatorCommand extends AbstractCommand { + public static final String COMMAND_NAME = "storage-populator"; + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); private static final Logger logger = LoggingUtils.getLogger(StoragePopulatorCommand.class); @@ -191,8 +193,12 @@ * Package-private to allow overriding for testing. */ File getConfigFile(Arguments args) { - return new File(paths.getSystemPluginConfigurationDirectory().getAbsolutePath() + - "/storage-populator/" + args.getArgument(CONFIG_FILE_NAME)); + return new File(getConfigFileDirectoryPath(paths) + args.getArgument(CONFIG_FILE_NAME)); + } + + public static String getConfigFileDirectoryPath(CommonPaths paths) { + return paths.getSystemPluginConfigurationDirectory().getAbsolutePath() + + "/storage-populator/"; } /**
--- a/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/Activator.java Wed Jun 01 16:30:42 2016 -0400 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/Activator.java Wed Jun 01 16:34:12 2016 -0400 @@ -39,6 +39,7 @@ import java.util.Hashtable; import java.util.Map; +import com.redhat.thermostat.common.cli.CompleterService; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; @@ -51,13 +52,19 @@ import com.redhat.thermostat.storage.dao.VmInfoDAO; import com.redhat.thermostat.storage.populator.StoragePopulatorCommand; import com.redhat.thermostat.thread.dao.ThreadDao; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; public class Activator implements BundleActivator { - private MultipleServiceTracker tracker; + private MultipleServiceTracker cmdDepsTracker; + private ServiceTracker<CommonPaths, CommonPaths> completerDepsTracker; + private ServiceRegistration completerRegistration; @Override - public void start(BundleContext context) throws Exception { + public void start(final BundleContext context) throws Exception { final StoragePopulatorCommand command = new StoragePopulatorCommand(); Hashtable<String,String> properties = new Hashtable<>(); @@ -73,7 +80,7 @@ ThreadDao.class, }; - tracker = new MultipleServiceTracker(context, deps, new MultipleServiceTracker.Action() { + cmdDepsTracker = new MultipleServiceTracker(context, deps, new MultipleServiceTracker.Action() { @Override public void dependenciesAvailable(Map<String, Object> services) { @@ -98,12 +105,42 @@ command.setServicesUnavailable(); } }); - tracker.open(); + cmdDepsTracker.open(); + + final StoragePopulatorCompleterService completerService = new StoragePopulatorCompleterService(); + completerDepsTracker = new ServiceTracker<>(context, CommonPaths.class, new ServiceTrackerCustomizer<CommonPaths, CommonPaths>() { + @Override + public CommonPaths addingService(ServiceReference<CommonPaths> serviceReference) { + CommonPaths paths = context.getService(serviceReference); + completerService.setCommonPaths(paths); + return paths; + } + + @Override + public void modifiedService(ServiceReference<CommonPaths> serviceReference, CommonPaths paths) { + } + + @Override + public void removedService(ServiceReference<CommonPaths> serviceReference, CommonPaths paths) { + completerService.setCommonPaths(null); + } + }); + completerDepsTracker.open(); + + completerRegistration = context.registerService(CompleterService.class.getName(), completerService, null); } @Override public void stop(BundleContext context) throws Exception { - tracker.close(); + if (cmdDepsTracker != null) { + cmdDepsTracker.close(); + } + if (completerDepsTracker != null) { + completerDepsTracker.close(); + } + if (completerRegistration != null) { + completerRegistration.unregister(); + } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/StoragePopulatorCompleterService.java Wed Jun 01 16:34:12 2016 -0400 @@ -0,0 +1,71 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import com.redhat.thermostat.common.cli.AbstractCompleterService; +import com.redhat.thermostat.common.cli.CliCommandOption; +import com.redhat.thermostat.common.cli.CompletionFinderTabCompleter; +import com.redhat.thermostat.common.cli.DirectoryContentsCompletionFinder; +import com.redhat.thermostat.common.cli.TabCompleter; +import com.redhat.thermostat.shared.config.CommonPaths; +import com.redhat.thermostat.storage.populator.StoragePopulatorCommand; + +import java.io.File; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +public class StoragePopulatorCompleterService extends AbstractCompleterService { + + static final CliCommandOption CONFIG_OPTION = new CliCommandOption("c", "config", true, "the json config file to use", true); + + @Override + public Set<String> getCommands() { + return Collections.singleton(StoragePopulatorCommand.COMMAND_NAME); + } + + @Override + public Map<CliCommandOption, ? extends TabCompleter> getOptionCompleters() { + CompletionFinderTabCompleter completer = new CompletionFinderTabCompleter(new StoragePopulatorConfigFinder(dependencyServices)); + return Collections.singletonMap(CONFIG_OPTION, completer); + } + + public void setCommonPaths(CommonPaths paths) { + setService(CommonPaths.class, paths); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/StoragePopulatorConfigFinder.java Wed Jun 01 16:34:12 2016 -0400 @@ -0,0 +1,86 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import com.redhat.thermostat.common.cli.CompletionFinder; +import com.redhat.thermostat.common.cli.CompletionInfo; +import com.redhat.thermostat.common.cli.DependencyServices; +import com.redhat.thermostat.common.cli.DirectoryContentsCompletionFinder; +import com.redhat.thermostat.shared.config.CommonPaths; +import com.redhat.thermostat.storage.populator.StoragePopulatorCommand; + +import java.io.File; +import java.io.FileFilter; +import java.util.Collections; +import java.util.List; + +public class StoragePopulatorConfigFinder implements CompletionFinder { + + private DependencyServices dependencyServices; + private DirectoryContentsCompletionFinder directoryFinder; + + public StoragePopulatorConfigFinder(DependencyServices dependencyServices) { + this.dependencyServices = dependencyServices; + } + + /* Testing hook only */ + void setDirectoryFinder(DirectoryContentsCompletionFinder directoryFinder) { + this.directoryFinder = directoryFinder; + } + + @Override + public List<CompletionInfo> findCompletions() { + if (!dependencyServices.hasService(CommonPaths.class)) { + return Collections.emptyList(); + } + if (directoryFinder == null) { + CommonPaths paths = dependencyServices.getService(CommonPaths.class); + String configDirectory = StoragePopulatorCommand.getConfigFileDirectoryPath(paths); + directoryFinder = new DirectoryContentsCompletionFinder(new File(configDirectory)); + directoryFinder.setFileFilter(new StoragePopulatorConfigFilter()); + } + return directoryFinder.findCompletions(); + } + + static class StoragePopulatorConfigFilter implements FileFilter { + @Override + public boolean accept(File file) { + return file.isFile() && file.getName().toLowerCase().endsWith(".json"); + } + } + +}
--- a/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/ActivatorTest.java Wed Jun 01 16:30:42 2016 -0400 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/ActivatorTest.java Wed Jun 01 16:34:12 2016 -0400 @@ -37,12 +37,16 @@ package com.redhat.thermostat.storage.populator.internal; import static com.redhat.thermostat.testutils.Asserts.assertCommandIsRegistered; +import static com.redhat.thermostat.testutils.Asserts.assertServiceIsNotRegistered; +import static com.redhat.thermostat.testutils.Asserts.assertServiceIsRegistered; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import com.redhat.thermostat.common.cli.CompleterService; +import com.redhat.thermostat.shared.config.CommonPaths; import org.junit.Test; import com.redhat.thermostat.storage.populator.StoragePopulatorCommand; -import com.redhat.thermostat.storage.populator.internal.Activator; import com.redhat.thermostat.testutils.StubBundleContext; public class ActivatorTest { @@ -53,8 +57,10 @@ activator.start(ctx); assertCommandIsRegistered(ctx, "storage-populator", StoragePopulatorCommand.class); + assertServiceIsRegistered(ctx, CompleterService.class, StoragePopulatorCompleterService.class); activator.stop(ctx); assertEquals(0, ctx.getServiceListeners().size()); } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/StoragePopulatorCompleterServiceTest.java Wed Jun 01 16:34:12 2016 -0400 @@ -0,0 +1,85 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import com.redhat.thermostat.common.cli.CliCommandOption; +import com.redhat.thermostat.common.cli.TabCompleter; +import com.redhat.thermostat.shared.config.CommonPaths; +import com.redhat.thermostat.storage.populator.StoragePopulatorCommand; +import org.junit.Before; +import org.junit.Test; + +import java.util.Collections; +import java.util.Map; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +public class StoragePopulatorCompleterServiceTest { + + private StoragePopulatorCompleterService service; + + @Before + public void setup() { + service = new StoragePopulatorCompleterService(); + service.setCommonPaths(mock(CommonPaths.class)); + } + + @Test + public void testOnlyProvidesCompletionForStoragePopulatorCommand() { + assertThat(service.getCommands(), is(equalTo(Collections.singleton(StoragePopulatorCommand.COMMAND_NAME)))); + } + + @Test + public void testProvidesCompleterOnlyForConfigOption() { + Map<CliCommandOption, ? extends TabCompleter> completerMap = service.getOptionCompleters(); + assertThat(completerMap.keySet(), is(equalTo(Collections.singleton(StoragePopulatorCompleterService.CONFIG_OPTION)))); + assertThat(completerMap.get(StoragePopulatorCompleterService.CONFIG_OPTION), is(not(equalTo(null)))); + } + + @Test + public void testConfigOptionProperties() { + assertThat(StoragePopulatorCompleterService.CONFIG_OPTION.getOpt(), is("c")); + assertThat(StoragePopulatorCompleterService.CONFIG_OPTION.getLongOpt(), is("config")); + assertThat(StoragePopulatorCompleterService.CONFIG_OPTION.hasArg(), is(true)); + assertThat(StoragePopulatorCompleterService.CONFIG_OPTION.isRequired(), is(true)); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/StoragePopulatorConfigFinderTest.java Wed Jun 01 16:34:12 2016 -0400 @@ -0,0 +1,86 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import com.redhat.thermostat.common.cli.CompletionInfo; +import com.redhat.thermostat.common.cli.DependencyServices; +import com.redhat.thermostat.common.cli.DirectoryContentsCompletionFinder; +import com.redhat.thermostat.shared.config.CommonPaths; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class StoragePopulatorConfigFinderTest { + + private DependencyServices dependencyServices; + private StoragePopulatorConfigFinder finder; + private DirectoryContentsCompletionFinder directoryFinder; + + @Before + public void setup() { + dependencyServices = mock(DependencyServices.class); + when(dependencyServices.hasService(CommonPaths.class)).thenReturn(true); + when(dependencyServices.getService(CommonPaths.class)).thenReturn(mock(CommonPaths.class)); + finder = new StoragePopulatorConfigFinder(dependencyServices); + directoryFinder = mock(DirectoryContentsCompletionFinder.class); + finder.setDirectoryFinder(directoryFinder); + } + + @Test + public void testDelegatesFindCompletions() { + finder.findCompletions(); + verify(directoryFinder).findCompletions(); + } + + @Test + public void testReturnsEmptyResultWithoutDelegationIfCommonPathsUnavailable() { + when(dependencyServices.hasService(CommonPaths.class)).thenReturn(false); + when(dependencyServices.getService(CommonPaths.class)).thenReturn(null); + List<CompletionInfo> result = finder.findCompletions(); + verifyZeroInteractions(directoryFinder); + assertThat(result.size(), is(0)); + } + +}