Mercurial > hg > release > thermostat-0.7
changeset 727:bfbc04020529
Handle invalid command names
The launcher crashes with a NullPointerException if an invalid
command name is provided. This also happens in the shell. This
is a regression.
Fix it by throwing and handling an exception indicating the command
information is not available for that command.
Reviewed-by: vanaltj
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-October/003832.html
line wrap: on
line diff
--- a/bundles/src/main/java/com/redhat/thermostat/bundles/OSGiRegistry.java Tue Oct 23 14:40:34 2012 -0400 +++ b/bundles/src/main/java/com/redhat/thermostat/bundles/OSGiRegistry.java Tue Oct 23 14:53:20 2012 -0400 @@ -44,6 +44,7 @@ import com.redhat.thermostat.bundles.impl.BundleLoader; import com.redhat.thermostat.common.Configuration; +import com.redhat.thermostat.common.cli.CommandInfoNotFoundException; import com.redhat.thermostat.common.cli.CommandInfoSource; @@ -53,7 +54,7 @@ public abstract void setCommandInfoSource(CommandInfoSource source); - public abstract void addBundlesFor(String commandName) throws BundleException, IOException; + public abstract void addBundlesFor(String commandName) throws BundleException, CommandInfoNotFoundException, IOException; public static void preLoadBundles(Framework framework, List<String> bundleLocations, boolean printOSGiInfo) throws BundleException {
--- a/bundles/src/main/java/com/redhat/thermostat/bundles/impl/OSGiRegistryImpl.java Tue Oct 23 14:40:34 2012 -0400 +++ b/bundles/src/main/java/com/redhat/thermostat/bundles/impl/OSGiRegistryImpl.java Tue Oct 23 14:53:20 2012 -0400 @@ -39,6 +39,7 @@ import com.redhat.thermostat.bundles.OSGiRegistry; import com.redhat.thermostat.common.Configuration; import com.redhat.thermostat.common.ConfigurationException; +import com.redhat.thermostat.common.cli.CommandInfoNotFoundException; import com.redhat.thermostat.common.cli.CommandInfoSource; import java.io.FileNotFoundException; @@ -86,7 +87,7 @@ } @Override - public void addBundlesFor(String commandName) throws BundleException, IOException { + public void addBundlesFor(String commandName) throws BundleException, IOException, CommandInfoNotFoundException { if (configuration.getPrintOSGiInfo()) { System.out.println("Loading additional bundles for: " + commandName); }
--- a/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandInfo.java Tue Oct 23 14:40:34 2012 -0400 +++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandInfo.java Tue Oct 23 14:53:20 2012 -0400 @@ -1,3 +1,39 @@ +/* + * 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.cli; import java.util.List;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandInfoNotFoundException.java Tue Oct 23 14:53:20 2012 -0400 @@ -0,0 +1,52 @@ +/* + * 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.cli; + +public class CommandInfoNotFoundException extends RuntimeException { + + private String commandName = null; + + public CommandInfoNotFoundException(String commandName) { + super("data for command '" + commandName + "' not found"); + + this.commandName = commandName; + } + + public String getCommandName() { + return commandName; + } +}
--- a/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandInfoSource.java Tue Oct 23 14:40:34 2012 -0400 +++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandInfoSource.java Tue Oct 23 14:53:20 2012 -0400 @@ -41,7 +41,7 @@ public interface CommandInfoSource { - public CommandInfo getCommandInfo(String name); + public CommandInfo getCommandInfo(String name) throws CommandInfoNotFoundException; public Collection<CommandInfo> getCommandInfos();
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/CommandInfoSourceImpl.java Tue Oct 23 14:40:34 2012 -0400 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/CommandInfoSourceImpl.java Tue Oct 23 14:53:20 2012 -0400 @@ -47,6 +47,7 @@ import java.util.logging.Logger; import com.redhat.thermostat.common.cli.CommandInfo; +import com.redhat.thermostat.common.cli.CommandInfoNotFoundException; import com.redhat.thermostat.common.cli.CommandInfoSource; public class CommandInfoSourceImpl implements CommandInfoSource { @@ -92,10 +93,16 @@ return fileName.substring(0, dotIndex); } - public CommandInfo getCommandInfo(String name) { - return commands.get(name); + @Override + public CommandInfo getCommandInfo(String name) throws CommandInfoNotFoundException { + CommandInfo cmdInfo = commands.get(name); + if (cmdInfo == null) { + throw new CommandInfoNotFoundException(name); + } + return cmdInfo; } + @Override public Collection<CommandInfo> getCommandInfos() { return commands.values(); }
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/HelpCommand.java Tue Oct 23 14:40:34 2012 -0400 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/HelpCommand.java Tue Oct 23 14:53:20 2012 -0400 @@ -52,6 +52,7 @@ import com.redhat.thermostat.common.cli.Arguments; import com.redhat.thermostat.common.cli.CommandContext; import com.redhat.thermostat.common.cli.CommandInfo; +import com.redhat.thermostat.common.cli.CommandInfoNotFoundException; import com.redhat.thermostat.common.cli.CommandInfoSource; import com.redhat.thermostat.common.cli.SimpleCommand; import com.redhat.thermostat.common.cli.TableRenderer; @@ -102,12 +103,13 @@ BundleContext context = FrameworkUtil.getBundle(getClass()).getBundleContext(); ServiceReference infosRef = context.getServiceReference(CommandInfoSource.class); CommandInfoSource infos = (CommandInfoSource) context.getService(infosRef); - CommandInfo info = infos.getCommandInfo(cmdName); - context.ungetService(infosRef); - if (info != null) { + try { + CommandInfo info = infos.getCommandInfo(cmdName); printHelp(ctx, info); - } else { + } catch (CommandInfoNotFoundException notFound) { printCommandSummaries(ctx); + } finally { + context.ungetService(infosRef); } }
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java Tue Oct 23 14:40:34 2012 -0400 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java Tue Oct 23 14:53:20 2012 -0400 @@ -59,6 +59,7 @@ import com.redhat.thermostat.common.cli.CommandContext; import com.redhat.thermostat.common.cli.CommandContextFactory; import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.cli.CommandInfoNotFoundException; import com.redhat.thermostat.common.cli.CommandRegistry; import com.redhat.thermostat.common.config.ClientPreferences; import com.redhat.thermostat.common.config.InvalidConfigurationException; @@ -201,6 +202,10 @@ out.println("Could not load necessary bundles for: " + cmdName); e.printStackTrace(out); return; + } catch (CommandInfoNotFoundException commandNotFound) { + out.print(String.format(UNKNOWN_COMMAND_MESSAGE, cmdName)); + runHelpCommand(); + return; } Command cmd = getCommand(cmdName);
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/LauncherTest.java Tue Oct 23 14:40:34 2012 -0400 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/LauncherTest.java Tue Oct 23 14:53:20 2012 -0400 @@ -38,12 +38,14 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Matchers.any; +import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -61,6 +63,7 @@ import org.junit.runner.RunWith; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; @@ -79,6 +82,7 @@ import com.redhat.thermostat.common.cli.CommandContext; import com.redhat.thermostat.common.cli.CommandException; import com.redhat.thermostat.common.cli.CommandInfo; +import com.redhat.thermostat.common.cli.CommandInfoNotFoundException; import com.redhat.thermostat.common.cli.CommandInfoSource; import com.redhat.thermostat.common.config.ClientPreferences; import com.redhat.thermostat.common.locale.LocaleResources; @@ -316,6 +320,19 @@ } @Test + public void testCommandInfoNotFound() throws CommandInfoNotFoundException, BundleException, IOException { + doThrow(new CommandInfoNotFoundException("foo")).when(registry).addBundlesFor("foo"); + String expected = "unknown command 'foo'\n" + + "list of commands:\n\n" + + " help print help information\n" + + " basic nothing that means anything\n" + + " test1 description 1\n" + + " test2 description 2\n" + + " test3 description 3\n"; + runAndVerifyCommand(new String[] {"foo"}, expected); + } + + @Test public void testMainExceptionInCommand() { TestCommand errorCmd = new TestCommand("error", new TestCommand.Handle() {