diff --git a/gclc/src/main/java/fr/bigeon/gclc/ConsoleApplication.java b/gclc/src/main/java/fr/bigeon/gclc/ConsoleApplication.java index 69a8fa4..35ec554 100644 --- a/gclc/src/main/java/fr/bigeon/gclc/ConsoleApplication.java +++ b/gclc/src/main/java/fr/bigeon/gclc/ConsoleApplication.java @@ -48,9 +48,9 @@ import fr.bigeon.gclc.command.HelpExecutor; import fr.bigeon.gclc.command.ICommand; import fr.bigeon.gclc.command.ICommandProvider; import fr.bigeon.gclc.command.SubedCommand; -import fr.bigeon.gclc.command.UnrecognizedCommand; import fr.bigeon.gclc.exception.CommandParsingException; import fr.bigeon.gclc.exception.CommandRunException; +import fr.bigeon.gclc.exception.CommandRunExceptionType; import fr.bigeon.gclc.exception.InvalidCommandName; import fr.bigeon.gclc.i18n.Messages; import fr.bigeon.gclc.manager.ConsoleManager; @@ -100,7 +100,7 @@ public class ConsoleApplication implements ICommandProvider { this.header = welcome; this.footer = goodbye; this.manager = manager; - root = new SubedCommand(new String(), new UnrecognizedCommand(manager)); + root = new SubedCommand(new String()); } /** @param manager the manager @@ -208,6 +208,9 @@ public class ConsoleApplication implements ICommandProvider { manager.println(Messages .getString("ConsoleApplication.cmd.failed", cmd)); //$NON-NLS-1$ manager.println(e.getLocalizedMessage()); + if (e.getType() == CommandRunExceptionType.USAGE) { + e.getSource().help(getManager()); + } } } } diff --git a/gclc/src/main/java/fr/bigeon/gclc/command/CommandProvider.java b/gclc/src/main/java/fr/bigeon/gclc/command/CommandProvider.java index 503bce9..df77293 100644 --- a/gclc/src/main/java/fr/bigeon/gclc/command/CommandProvider.java +++ b/gclc/src/main/java/fr/bigeon/gclc/command/CommandProvider.java @@ -83,7 +83,7 @@ public class CommandProvider implements ICommandProvider { } } throw new CommandRunException( - Messages.getString("CommandProvider.unrecognized", cmd)); //$NON-NLS-1$ + Messages.getString("CommandProvider.unrecognized", cmd), null); //$NON-NLS-1$ } /* (non-Javadoc) diff --git a/gclc/src/main/java/fr/bigeon/gclc/command/HelpExecutor.java b/gclc/src/main/java/fr/bigeon/gclc/command/HelpExecutor.java index 6eee60b..885a756 100644 --- a/gclc/src/main/java/fr/bigeon/gclc/command/HelpExecutor.java +++ b/gclc/src/main/java/fr/bigeon/gclc/command/HelpExecutor.java @@ -41,6 +41,7 @@ package fr.bigeon.gclc.command; import java.io.IOException; import fr.bigeon.gclc.exception.CommandRunException; +import fr.bigeon.gclc.exception.CommandRunExceptionType; import fr.bigeon.gclc.manager.ConsoleManager; import fr.bigeon.gclc.prompt.CLIPrompterMessages; @@ -77,7 +78,8 @@ public class HelpExecutor extends Command { try { cmd.help(consoleManager, args); } catch (IOException e) { - throw new CommandRunException("Console manager closed", e); //$NON-NLS-1$ + throw new CommandRunException(CommandRunExceptionType.INTERACTION, + "Console manager closed", e, this); //$NON-NLS-1$ } } diff --git a/gclc/src/main/java/fr/bigeon/gclc/command/ParametrizedCommand.java b/gclc/src/main/java/fr/bigeon/gclc/command/ParametrizedCommand.java index aad57a7..77f995a 100644 --- a/gclc/src/main/java/fr/bigeon/gclc/command/ParametrizedCommand.java +++ b/gclc/src/main/java/fr/bigeon/gclc/command/ParametrizedCommand.java @@ -45,6 +45,7 @@ import java.util.List; import java.util.Map; import fr.bigeon.gclc.exception.CommandRunException; +import fr.bigeon.gclc.exception.CommandRunExceptionType; import fr.bigeon.gclc.manager.ConsoleManager; /**

@@ -122,7 +123,8 @@ public abstract class ParametrizedCommand extends Command { boolParams.keySet(), stringParams.keySet(), strict); if (!parameters.parseArgs(args)) { // ERROR the parameters could not be correctly parsed - throw new CommandRunException("Unable to read arguments"); //$NON-NLS-1$ + throw new CommandRunException(CommandRunExceptionType.USAGE, + "Unable to read arguments", this); //$NON-NLS-1$ } final List toProvide = new ArrayList<>(); for (final String string : params.keySet()) { @@ -152,7 +154,8 @@ public abstract class ParametrizedCommand extends Command { } } catch (IOException e) { throw new CommandRunException( - "Interactive command but manager closed...", e); //$NON-NLS-1$ + CommandRunExceptionType.INTERACTION, + "Interactive command but manager closed...", e, this); //$NON-NLS-1$ } parameters.set(string, value); } diff --git a/gclc/src/main/java/fr/bigeon/gclc/command/ScriptExecution.java b/gclc/src/main/java/fr/bigeon/gclc/command/ScriptExecution.java new file mode 100644 index 0000000..11b1143 --- /dev/null +++ b/gclc/src/main/java/fr/bigeon/gclc/command/ScriptExecution.java @@ -0,0 +1,111 @@ +/** + * gclc:fr.bigeon.gclc.command.ScriptExecution.java + * Created on: Jun 12, 2016 + */ +package fr.bigeon.gclc.command; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.List; + +import fr.bigeon.gclc.ConsoleApplication; +import fr.bigeon.gclc.GCLCConstants; +import fr.bigeon.gclc.exception.CommandParsingException; +import fr.bigeon.gclc.exception.CommandRunException; +import fr.bigeon.gclc.exception.CommandRunExceptionType; + +/**

+ * TODO + * + * @author Emmanuel Bigeon */ +public class ScriptExecution extends Command { + + private final ConsoleApplication application; + private final String commentPrefix; + + /** @param name + * @param application + * @param commentPrefix */ + public ScriptExecution(String name, ConsoleApplication application, + String commentPrefix) { + super(name); + this.application = application; + this.commentPrefix = commentPrefix; + } + + /* (non-Javadoc) + * @see fr.bigeon.gclc.command.ICommand#execute(java.lang.String[]) */ + @Override + public void execute(String... args) throws CommandRunException { + if (args.length == 0) { + throw new CommandRunException(CommandRunExceptionType.USAGE, + "Expecting a file", this); + } + List argsList = Arrays.asList(args); + String scriptFile = argsList.remove(0); + Object[] params = argsList.toArray(); + try (FileReader fReader = new FileReader(new File(scriptFile)); + BufferedReader reader = new BufferedReader(fReader)) { + String cmd; + for (int i = 1; i < args.length; i++) { + params[i - 1] = args[i]; + } + while ((cmd = reader.readLine()) != null) { + if (cmd.startsWith(" ") || cmd.startsWith("\t")) { + throw new CommandRunException( + "Invalid command in script (line starts with space character)", + this); + } + if (cmd.isEmpty() || cmd.startsWith(commentPrefix)) { + continue; + } + String cmdLine = MessageFormat.format(cmd, params); + List ps = GCLCConstants.splitCommand(cmdLine); + String command = ps.remove(0); + application.executeSub(command, ps.toArray(new String[0])); + } + } catch (CommandParsingException e) { + throw new CommandRunException("Invalid command in script (" + + e.getLocalizedMessage() + ")", + e, this); + } catch (IOException e) { + throw new CommandRunException( + "Unable to read script (" + e.getLocalizedMessage() + ")", + e, this); + } + } + + /* (non-Javadoc) + * @see fr.bigeon.gclc.command.Command#usageDetail() */ + @Override + protected String usageDetail() { + StringBuilder builder = new StringBuilder(); + builder.append( + " scriptfile: path to the file containing the script to execute."); + builder.append(System.lineSeparator()); + builder.append(System.lineSeparator()); + builder.append( + " The script file must contain one line commands. The lines must never"); + builder.append(System.lineSeparator()); + builder.append( + "start with whitespace characters. The lines starting with"); + builder.append(System.lineSeparator()); + builder.append("\"" + commentPrefix + + "\" will be ignored as well as empty lines."); + builder.append(System.lineSeparator()); + + return builder.toString(); + } + + /* (non-Javadoc) + * @see fr.bigeon.gclc.command.ICommand#tip() */ + @Override + public String tip() { + return "Execute a script"; + } + +} diff --git a/gclc/src/main/java/fr/bigeon/gclc/command/SubedCommand.java b/gclc/src/main/java/fr/bigeon/gclc/command/SubedCommand.java index dc3e26b..46de380 100644 --- a/gclc/src/main/java/fr/bigeon/gclc/command/SubedCommand.java +++ b/gclc/src/main/java/fr/bigeon/gclc/command/SubedCommand.java @@ -40,6 +40,7 @@ import java.io.IOException; import java.util.Arrays; import fr.bigeon.gclc.exception.CommandRunException; +import fr.bigeon.gclc.exception.CommandRunExceptionType; import fr.bigeon.gclc.exception.InvalidCommandName; import fr.bigeon.gclc.manager.ConsoleManager; @@ -114,10 +115,16 @@ public class SubedCommand implements ICommandProvider, ICommand { if (noArgCommand != null) { noArgCommand.execute(args); } else { - throw new CommandRunException("Unrecognized command"); //$NON-NLS-1$ + throw new CommandRunException("Unrecognized command", this); //$NON-NLS-1$ } } else { - executeSub(args[0], Arrays.copyOfRange(args, 1, args.length)); + + try { + executeSub(args[0], Arrays.copyOfRange(args, 1, args.length)); + } catch (CommandRunException e) { + throw new CommandRunException(CommandRunExceptionType.USAGE, + e.getLocalizedMessage(), e, this); + } } } diff --git a/gclc/src/main/java/fr/bigeon/gclc/command/UnrecognizedCommand.java b/gclc/src/main/java/fr/bigeon/gclc/command/UnrecognizedCommand.java deleted file mode 100644 index 777f7b4..0000000 --- a/gclc/src/main/java/fr/bigeon/gclc/command/UnrecognizedCommand.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright Bigeon Emmanuel (2014) - * - * emmanuel@bigeon.fr - * - * This software is a computer program whose purpose is to - * provide a generic framework for console applications. - * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. - */ -/** - * gclc:fr.bigeon.gclc.UnrecognizedCommand.java - * Created on: Dec 23, 2014 - */ -package fr.bigeon.gclc.command; - -import java.io.IOException; - -import fr.bigeon.gclc.exception.CommandRunException; -import fr.bigeon.gclc.manager.ConsoleManager; -import fr.bigeon.gclc.prompt.CLIPrompterMessages; - -/**

- * The error message for unrecognized commands - * - * @author Emmanuel BIGEON */ -public final class UnrecognizedCommand implements ICommand { - /** The unrecognized command key */ - private static final String UNRECOGNIZED_CMD = "unrecognized.cmd"; //$NON-NLS-1$ - /** The unrecognized command key */ - private static final String EXPECTED_CMD = "expected.cmd"; //$NON-NLS-1$ - /** The manager */ - private final ConsoleManager manager; - - /** @param manager the console manager to use */ - public UnrecognizedCommand(ConsoleManager manager) { - if (manager == null) { - throw new NullPointerException("The argument cannot be null"); //$NON-NLS-1$ - } - this.manager = manager; - } - - @Override - public void execute(String... args) throws CommandRunException { - - try { - if (args.length > 0) { - manager.println(CLIPrompterMessages.getString(UNRECOGNIZED_CMD, - (Object[]) args)); - } else { - manager.println(CLIPrompterMessages.getString(EXPECTED_CMD)); - } - } catch (IOException e) { - throw new CommandRunException("Manager closed", e); //$NON-NLS-1$ - } - } - - /* (non-Javadoc) - * @see fr.bigeon.gclc.command.ICommand#getCommandName() */ - @Override - public String getCommandName() { - return ""; //$NON-NLS-1$ - } - - @Override - public void help(@SuppressWarnings("hiding") ConsoleManager manager, - String... args) { - // Nothing to do (no help provided as this is not a user command - // (usually) - } - - @Override - public String tip() { - return null; - } -} \ No newline at end of file diff --git a/gclc/src/main/java/fr/bigeon/gclc/command/package-info.java b/gclc/src/main/java/fr/bigeon/gclc/command/package-info.java index d24d6b3..76163a6 100644 --- a/gclc/src/main/java/fr/bigeon/gclc/command/package-info.java +++ b/gclc/src/main/java/fr/bigeon/gclc/command/package-info.java @@ -44,8 +44,6 @@ * {@link fr.bigeon.gclc.command.SubedCommand} for a command that is declined in * a set of sub commands, the {@link fr.bigeon.gclc.command.HelpExecutor} for * help display of other commands and the - * {@link fr.bigeon.gclc.command.UnrecognizedCommand} that should not be - * directly accessible to the user, but will be used in case of error in typing. * * @author Emmanuel BIGEON */ package fr.bigeon.gclc.command; \ No newline at end of file diff --git a/gclc/src/main/java/fr/bigeon/gclc/exception/CommandRunException.java b/gclc/src/main/java/fr/bigeon/gclc/exception/CommandRunException.java index d4713ee..c28a8d1 100644 --- a/gclc/src/main/java/fr/bigeon/gclc/exception/CommandRunException.java +++ b/gclc/src/main/java/fr/bigeon/gclc/exception/CommandRunException.java @@ -38,6 +38,8 @@ */ package fr.bigeon.gclc.exception; +import fr.bigeon.gclc.command.ICommand; + /**

* An exception thrown when a command failed to run correctly. * @@ -49,15 +51,43 @@ public class CommandRunException extends Exception { */ private static final long serialVersionUID = 1L; + private final CommandRunExceptionType type; + /** The command that caused the error */ + private final ICommand source; + /** @param message a message */ - public CommandRunException(String message) { + public CommandRunException(String message, ICommand source) { super(message); + type = CommandRunExceptionType.EXECUTION; + this.source = source; } /** @param message a message * @param cause the cause */ - public CommandRunException(String message, Throwable cause) { + public CommandRunException(String message, Throwable cause, + ICommand source) { super(message, cause); + type = CommandRunExceptionType.EXECUTION; + this.source = source; + } + + /** @param type the type of exception + * @param message the message */ + public CommandRunException(CommandRunExceptionType type, String message, + ICommand source) { + super(message); + this.type = type; + this.source = source; + } + + /** @param type the type of exception + * @param message a message + * @param cause the cause */ + public CommandRunException(CommandRunExceptionType type, String message, + Throwable cause, ICommand source) { + super(message, cause); + this.type = type; + this.source = source; } /* (non-Javadoc) @@ -71,4 +101,13 @@ public class CommandRunException extends Exception { return super.getLocalizedMessage(); } + /** @return the source */ + public ICommand getSource() { + return source; + } + + /** @return the type */ + public CommandRunExceptionType getType() { + return type; + } } diff --git a/gclc/src/main/java/fr/bigeon/gclc/exception/CommandRunExceptionType.java b/gclc/src/main/java/fr/bigeon/gclc/exception/CommandRunExceptionType.java new file mode 100644 index 0000000..bbe04d8 --- /dev/null +++ b/gclc/src/main/java/fr/bigeon/gclc/exception/CommandRunExceptionType.java @@ -0,0 +1,21 @@ +/** + * gclc:fr.bigeon.gclc.exception.CommandRunExceptionType.java + * Created on: Jun 12, 2016 + */ +package fr.bigeon.gclc.exception; + +/** + *

+ * TODO + * + * @author Emmanuel Bigeon + * + */ +public enum CommandRunExceptionType { + /** Type of exception due to a wrong usage */ + USAGE, + /** Type of exception due to a problem in execution */ + EXECUTION, + /** Type of exception due to the impossibility to interact with user */ + INTERACTION; +} diff --git a/gclc/src/test/java/fr/bigeon/gclc/ConsoleTestApplication.java b/gclc/src/test/java/fr/bigeon/gclc/ConsoleTestApplication.java index babe0ef..ad75001 100644 --- a/gclc/src/test/java/fr/bigeon/gclc/ConsoleTestApplication.java +++ b/gclc/src/test/java/fr/bigeon/gclc/ConsoleTestApplication.java @@ -36,7 +36,6 @@ package fr.bigeon.gclc; import java.io.IOException; -import fr.bigeon.gclc.ConsoleApplication; import fr.bigeon.gclc.command.Command; import fr.bigeon.gclc.command.ExitCommand; import fr.bigeon.gclc.command.HelpExecutor; @@ -74,7 +73,8 @@ public class ConsoleTestApplication extends ConsoleApplication { try { manager.println("Test command ran fine"); } catch (IOException e) { - throw new CommandRunException("manager closed", e); + throw new CommandRunException("manager closed", e, + this); } } }); @@ -92,9 +92,11 @@ public class ConsoleTestApplication extends ConsoleApplication { Thread.sleep(TWO_SECONDS); manager.println("done!"); } catch (IOException e) { - throw new CommandRunException("manager closed", e); + throw new CommandRunException("manager closed", e, + this); } catch (InterruptedException e) { - throw new CommandRunException("wait interrupted", e); + throw new CommandRunException("wait interrupted", e, + this); } } });