You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2010/09/08 13:00:12 UTC
svn commit: r994983 - in /karaf/trunk/shell/console/src:
main/java/org/apache/felix/gogo/commands/
main/java/org/apache/felix/gogo/commands/basic/
main/java/org/apache/karaf/shell/console/jline/
test/java/org/apache/felix/gogo/commands/
Author: gnodet
Date: Wed Sep 8 11:00:12 2010
New Revision: 994983
URL: http://svn.apache.org/viewvc?rev=994983&view=rev
Log:
KARAF-159: improve error message when an invalid syntax is used
Added:
karaf/trunk/shell/console/src/main/java/org/apache/felix/gogo/commands/CommandException.java
Modified:
karaf/trunk/shell/console/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java
karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/jline/Console.java
karaf/trunk/shell/console/src/test/java/org/apache/felix/gogo/commands/TestCommands.java
Added: karaf/trunk/shell/console/src/main/java/org/apache/felix/gogo/commands/CommandException.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/console/src/main/java/org/apache/felix/gogo/commands/CommandException.java?rev=994983&view=auto
==============================================================================
--- karaf/trunk/shell/console/src/main/java/org/apache/felix/gogo/commands/CommandException.java (added)
+++ karaf/trunk/shell/console/src/main/java/org/apache/felix/gogo/commands/CommandException.java Wed Sep 8 11:00:12 2010
@@ -0,0 +1,64 @@
+/*
+ * 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.felix.gogo.commands;
+
+import org.fusesource.jansi.Ansi;
+
+/**
+ * Base class for exceptions thrown when executing commands.
+ */
+public class CommandException extends Exception {
+
+ private String help;
+
+ public CommandException() {
+ }
+
+ public CommandException(String message) {
+ super(message);
+ }
+
+ public CommandException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CommandException(Throwable cause) {
+ super(cause);
+ }
+
+ public CommandException(String help, String message) {
+ super(message);
+ this.help = help;
+ }
+
+ public CommandException(String help, String message, Throwable cause) {
+ super(message, cause);
+ this.help = help;
+ }
+
+ public String getNiceHelp() {
+ return help != null ? help
+ : Ansi.ansi()
+ .fg(Ansi.Color.RED)
+ .a("Error executing command: ")
+ .a(getMessage() != null ? getMessage() : getClass().getName())
+ .fg(Ansi.Color.DEFAULT).toString();
+ }
+
+}
Modified: karaf/trunk/shell/console/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/console/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java?rev=994983&r1=994982&r2=994983&view=diff
==============================================================================
--- karaf/trunk/shell/console/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java (original)
+++ karaf/trunk/shell/console/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java Wed Sep 8 11:00:12 2010
@@ -27,12 +27,14 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jline.Terminal;
+import org.apache.felix.gogo.commands.CommandException;
import org.apache.felix.gogo.commands.Option;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.gogo.commands.basic.ActionPreparator;
import org.apache.felix.gogo.commands.converter.DefaultConverter;
+import org.apache.felix.gogo.commands.converter.GenericType;
import org.fusesource.jansi.Ansi;
import org.osgi.service.command.CommandSession;
@@ -156,7 +158,24 @@ public class DefaultActionPreparator imp
}
}
if (option == null) {
- throw new IllegalArgumentException("Undefined option: " + param);
+ Command command = action.getClass().getAnnotation(Command.class);
+ throw new CommandException(
+ Ansi.ansi()
+ .fg(Ansi.Color.RED)
+ .a("Error executing command ")
+ .a(command.scope())
+ .a(":")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(command.name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(" undefined option ")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(param)
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .fg(Ansi.Color.DEFAULT)
+ .toString(),
+ "Undefined option: " + param
+ );
}
Field field = options.get(option);
if (value == null && (field.getType() == boolean.class || field.getType() == Boolean.class)) {
@@ -166,7 +185,24 @@ public class DefaultActionPreparator imp
value = it.next();
}
if (value == null) {
- throw new IllegalArgumentException("Missing value for option " + param);
+ Command command = action.getClass().getAnnotation(Command.class);
+ throw new CommandException(
+ Ansi.ansi()
+ .fg(Ansi.Color.RED)
+ .a("Error executing command ")
+ .a(command.scope())
+ .a(":")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(command.name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(" missing value for option ")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(param)
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .fg(Ansi.Color.DEFAULT)
+ .toString(),
+ "Missing value for option: " + param
+ );
}
if (option.multiValued()) {
List<Object> l = (List<Object>) optionValues.get(option);
@@ -181,7 +217,21 @@ public class DefaultActionPreparator imp
} else {
processOptions = false;
if (argIndex >= orderedArguments.size()) {
- throw new IllegalArgumentException("Too many arguments specified");
+ Command command = action.getClass().getAnnotation(Command.class);
+ throw new CommandException(
+ Ansi.ansi()
+ .fg(Ansi.Color.RED)
+ .a("Error executing command ")
+ .a(command.scope())
+ .a(":")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(command.name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(": too many arguments specified")
+ .fg(Ansi.Color.DEFAULT)
+ .toString(),
+ "Too many arguments specified"
+ );
}
Argument argument = orderedArguments.get(argIndex);
if (!argument.multiValued()) {
@@ -202,24 +252,116 @@ public class DefaultActionPreparator imp
// Check required arguments / options
for (Option option : options.keySet()) {
if (option.required() && optionValues.get(option) == null) {
- throw new IllegalArgumentException("Option " + option.name() + " is required");
+ Command command = action.getClass().getAnnotation(Command.class);
+ throw new CommandException(
+ Ansi.ansi()
+ .fg(Ansi.Color.RED)
+ .a("Error executing command ")
+ .a(command.scope())
+ .a(":")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(command.name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(": option ")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(option.name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(" is required")
+ .fg(Ansi.Color.DEFAULT)
+ .toString(),
+ "Option " + option.name() + " is required"
+ );
}
}
for (Argument argument : arguments.keySet()) {
if (argument.required() && argumentValues.get(argument) == null) {
- throw new IllegalArgumentException("Argument " + argument.name() + " is required");
+ Command command = action.getClass().getAnnotation(Command.class);
+ throw new CommandException(
+ Ansi.ansi()
+ .fg(Ansi.Color.RED)
+ .a("Error executing command ")
+ .a(command.scope())
+ .a(":")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(command.name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(": argument ")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(argument.name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(" is required")
+ .fg(Ansi.Color.DEFAULT)
+ .toString(),
+ "Argument " + argument.name() + " is required"
+ );
}
}
// Convert and inject values
for (Map.Entry<Option, Object> entry : optionValues.entrySet()) {
Field field = options.get(entry.getKey());
- Object value = convert(action, session, entry.getValue(), field.getGenericType());
+ Object value;
+ try {
+ value = convert(action, session, entry.getValue(), field.getGenericType());
+ } catch (Exception e) {
+ Command command = action.getClass().getAnnotation(Command.class);
+ throw new CommandException(
+ Ansi.ansi()
+ .fg(Ansi.Color.RED)
+ .a("Error executing command ")
+ .a(command.scope())
+ .a(":")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(command.name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(": unable to convert option ")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(entry.getKey().name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(" with value '")
+ .a(entry.getValue())
+ .a("' to type ")
+ .a(new GenericType(field.getGenericType()).toString())
+ .fg(Ansi.Color.DEFAULT)
+ .toString(),
+ "Unable to convert option " + entry.getKey().name() + " with value '"
+ + entry.getValue() + "' to type " + new GenericType(field.getGenericType()).toString(),
+ e
+ );
+ }
field.setAccessible(true);
field.set(action, value);
}
for (Map.Entry<Argument, Object> entry : argumentValues.entrySet()) {
Field field = arguments.get(entry.getKey());
- Object value = convert(action, session, entry.getValue(), field.getGenericType());
+ Object value;
+ try {
+ value = convert(action, session, entry.getValue(), field.getGenericType());
+ } catch (Exception e) {
+ Command command = action.getClass().getAnnotation(Command.class);
+ throw new CommandException(
+ Ansi.ansi()
+ .fg(Ansi.Color.RED)
+ .a("Error executing command ")
+ .a(command.scope())
+ .a(":")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(command.name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(": unable to convert argument ")
+ .a(Ansi.Attribute.INTENSITY_BOLD)
+ .a(entry.getKey().name())
+ .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
+ .a(" with value '")
+ .a(entry.getValue())
+ .a("' to type ")
+ .a(new GenericType(field.getGenericType()).toString())
+ .fg(Ansi.Color.DEFAULT)
+ .toString(),
+ "Unable to convert argument " + entry.getKey().name() + " with value '"
+ + entry.getValue() + "' to type " + new GenericType(field.getGenericType()).toString(),
+ e
+ );
+ }
field.setAccessible(true);
field.set(action, value);
}
Modified: karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/jline/Console.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/jline/Console.java?rev=994983&r1=994982&r2=994983&view=diff
==============================================================================
--- karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/jline/Console.java (original)
+++ karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/jline/Console.java Wed Sep 8 11:00:12 2010
@@ -39,6 +39,7 @@ import jline.AnsiWindowsTerminal;
import jline.ConsoleReader;
import jline.Terminal;
import jline.UnsupportedTerminal;
+import org.apache.felix.gogo.commands.CommandException;
import org.apache.karaf.shell.console.CloseShellException;
import org.apache.karaf.shell.console.Completer;
import org.apache.karaf.shell.console.completer.CommandsCompleter;
@@ -184,15 +185,20 @@ public class Console implements Runnable
try {
LOGGER.info("Exception caught while executing command", t);
session.put(LAST_EXCEPTION, t);
- session.getConsole().print(Ansi.ansi().fg(Ansi.Color.RED).toString());
+ if (t instanceof CommandException) {
+ session.getConsole().println(((CommandException) t).getNiceHelp());
+ }
if ( isPrintStackTraces()) {
+ session.getConsole().print(Ansi.ansi().fg(Ansi.Color.RED).toString());
t.printStackTrace(session.getConsole());
+ session.getConsole().print(Ansi.ansi().fg(Ansi.Color.DEFAULT).toString());
}
- else {
+ else if (!(t instanceof CommandException)) {
+ session.getConsole().print(Ansi.ansi().fg(Ansi.Color.RED).toString());
session.getConsole().println("Error executing command: "
+ (t.getMessage() != null ? t.getMessage() : t.getClass().getName()));
+ session.getConsole().print(Ansi.ansi().fg(Ansi.Color.DEFAULT).toString());
}
- session.getConsole().print(Ansi.ansi().fg(Ansi.Color.DEFAULT).toString());
} catch (Exception ignore) {
// ignore
}
Modified: karaf/trunk/shell/console/src/test/java/org/apache/felix/gogo/commands/TestCommands.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/console/src/test/java/org/apache/felix/gogo/commands/TestCommands.java?rev=994983&r1=994982&r2=994983&view=diff
==============================================================================
--- karaf/trunk/shell/console/src/test/java/org/apache/felix/gogo/commands/TestCommands.java (original)
+++ karaf/trunk/shell/console/src/test/java/org/apache/felix/gogo/commands/TestCommands.java Wed Sep 8 11:00:12 2010
@@ -61,7 +61,7 @@ public class TestCommands extends TestCa
c.execute("my-action");
fail("Action should have thrown an exception because of a missing argument");
}
- catch (IllegalArgumentException e)
+ catch (CommandException e)
{
}