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)
         {
         }