Changed exit mechanism on gclc
This commit is contained in:
parent
9660d675b6
commit
48c51b3a16
@ -87,7 +87,7 @@ of Emmanuel Bigeon. -->
|
||||
<dependency>
|
||||
<groupId>fr.bigeon</groupId>
|
||||
<artifactId>gclc</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.bigeon</groupId>
|
||||
|
@ -71,6 +71,10 @@ public class ThreadedServerConsoleManager implements ConsoleManager {
|
||||
private BufferedReader input;
|
||||
/** the prompting status */
|
||||
private boolean doPrompt;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private boolean closed = false;
|
||||
|
||||
/** Create the console manager.
|
||||
*
|
||||
@ -159,6 +163,14 @@ public class ThreadedServerConsoleManager implements ConsoleManager {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// Do nothing
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.manager.ConsoleManager#isClosed() */
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -116,6 +116,13 @@ public class ConsoleRunnableTest {
|
||||
public void close() throws IOException {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.manager.ConsoleManager#isClosed() */
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return i == cmds.length;
|
||||
}
|
||||
}
|
||||
|
||||
/** Test method for
|
||||
@ -136,7 +143,7 @@ public class ConsoleRunnableTest {
|
||||
Object lock = new Object();
|
||||
ConsoleApplication app = new ConsoleTestApplication(
|
||||
new ConsoleManagerTestImplementation(
|
||||
new String[] {"test", ConsoleTestApplication.EXIT}));
|
||||
new String[] {"test", ConsoleTestApplication.EXIT})); //$NON-NLS-1$
|
||||
ConsoleRunnable runnable = new ConsoleRunnable(app, lock);
|
||||
|
||||
Thread th = new Thread(runnable);
|
||||
@ -151,7 +158,7 @@ public class ConsoleRunnableTest {
|
||||
Object lock = new Object();
|
||||
ConsoleApplication app = new ConsoleTestApplication(
|
||||
new ConsoleManagerTestImplementation(
|
||||
new String[] {"test", ConsoleTestApplication.EXIT}));
|
||||
new String[] {"test", ConsoleTestApplication.EXIT})); //$NON-NLS-1$
|
||||
ConsoleRunnable runnable = new ConsoleRunnable(app, lock);
|
||||
runnable.stop();
|
||||
Thread th = new Thread(runnable);
|
||||
@ -166,7 +173,7 @@ public class ConsoleRunnableTest {
|
||||
Object lock = new Object();
|
||||
ConsoleApplication app = new ConsoleTestApplication(
|
||||
new ConsoleManagerTestImplementation(
|
||||
new String[] {"test", ConsoleTestApplication.EXIT}));
|
||||
new String[] {"test", ConsoleTestApplication.EXIT})); //$NON-NLS-1$
|
||||
ConsoleRunnable runnable = new ConsoleRunnable(app, lock);
|
||||
runnable.run();
|
||||
}
|
||||
|
@ -34,12 +34,15 @@
|
||||
*/
|
||||
package fr.bigeon.gclc.socket;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import fr.bigeon.gclc.ConsoleApplication;
|
||||
import fr.bigeon.gclc.command.Command;
|
||||
import fr.bigeon.gclc.command.ICommand;
|
||||
import fr.bigeon.gclc.command.ExitCommand;
|
||||
import fr.bigeon.gclc.command.HelpExecutor;
|
||||
import fr.bigeon.gclc.exception.CommandRunException;
|
||||
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
import fr.bigeon.gclc.prompt.CLIPrompterMessages;
|
||||
|
||||
/** A test-purpose application
|
||||
*
|
||||
@ -56,7 +59,7 @@ public class ConsoleTestApplication extends ConsoleApplication {
|
||||
"See you");
|
||||
try {
|
||||
add(new ExitCommand(EXIT, this));
|
||||
addHelpCommand("help");
|
||||
add(new HelpExecutor("help", manager, this.getRoot()));
|
||||
add(new Command("test") {
|
||||
|
||||
@Override
|
||||
@ -65,63 +68,16 @@ public class ConsoleTestApplication extends ConsoleApplication {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String... args) {
|
||||
public void execute(String... args) throws CommandRunException {
|
||||
try {
|
||||
manager.println("Test command ran fine");
|
||||
} catch (IOException e) {
|
||||
throw new CommandRunException("manager closed", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (final InvalidCommandName e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>
|
||||
* A command to exit a {@link ConsoleApplication}.
|
||||
*
|
||||
* @author Emmanuel BIGEON */
|
||||
class ExitCommand implements ICommand {
|
||||
/** The exit command manual message key */
|
||||
private static final String EXIT_MAN = "exit.man"; //$NON-NLS-1$
|
||||
/** The tip of the exit command */
|
||||
private static final String EXIT_TIP = "exit.tip"; //$NON-NLS-1$
|
||||
/** The application that will be exited when this command runs */
|
||||
private final ConsoleApplication app;
|
||||
/** The exit command name */
|
||||
private final String name;
|
||||
|
||||
/** @param name the name of the command
|
||||
* @param app the application to exit */
|
||||
public ExitCommand(String name, ConsoleApplication app) {
|
||||
this.name = name;
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
/** The actions to take before exiting */
|
||||
public void beforeExit() {
|
||||
// Do nothing by default
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void execute(String... args) {
|
||||
beforeExit();
|
||||
app.exit();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.command.ICommand#getCommandName() */
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void help(ConsoleManager helpManager, String... args) {
|
||||
helpManager.println(
|
||||
CLIPrompterMessages.getString(EXIT_MAN, (Object[]) args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tip() {
|
||||
return CLIPrompterMessages.getString(EXIT_TIP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,12 +51,17 @@
|
||||
<dependency>
|
||||
<groupId>fr.bigeon</groupId>
|
||||
<artifactId>gclc</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.swt.gtk.linux</groupId>
|
||||
<artifactId>x86_64</artifactId>
|
||||
<version>3.3.0-v3346</version>
|
||||
<groupId>org.eclipse.swt</groupId>
|
||||
<artifactId>org.eclipse.swt.gtk.linux.x86_64</artifactId>
|
||||
<version>4.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.swt</groupId>
|
||||
<artifactId>org.eclipse.swt.win32.win32.x86_64</artifactId>
|
||||
<version>4.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.bigeon</groupId>
|
||||
|
@ -100,9 +100,9 @@ public class SWTConsole extends Composite implements ConsoleManager {
|
||||
if (e.keyCode == SWT.ARROW_UP &&
|
||||
currentIndex < commands.size() - 1) {
|
||||
currentIndex++;
|
||||
consoleInput.setText(
|
||||
commands.get(commands.size() - currentIndex - 1));
|
||||
consoleInput.setSelection(consoleInput.getText().length());
|
||||
String cmd = commands.get(commands.size() - currentIndex - 1);
|
||||
consoleInput.setText(cmd);
|
||||
consoleInput.setSelection(cmd.length());
|
||||
}
|
||||
|
||||
// Lower arrow retrieves next commands
|
||||
@ -111,9 +111,10 @@ public class SWTConsole extends Composite implements ConsoleManager {
|
||||
currentIndex--;
|
||||
consoleInput.setText(new String());
|
||||
} else if (currentIndex > 0) {
|
||||
consoleInput.setText(commands
|
||||
.get(commands.size() - (--currentIndex) - 1));
|
||||
consoleInput.setSelection(consoleInput.getText().length());
|
||||
String cmd = commands
|
||||
.get(commands.size() - (--currentIndex) - 1);
|
||||
consoleInput.setText(cmd);
|
||||
consoleInput.setSelection(cmd.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -245,8 +246,11 @@ public class SWTConsole extends Composite implements ConsoleManager {
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.ConsoleManager#prompt() */
|
||||
@Override
|
||||
public String prompt() {
|
||||
public String prompt() throws IOException {
|
||||
synchronized (promptLock) {
|
||||
if (isDisposed()) {
|
||||
throw new IOException();
|
||||
}
|
||||
try {
|
||||
Display.getDefault().syncExec(new Runnable() {
|
||||
@SuppressWarnings("synthetic-access")
|
||||
@ -268,8 +272,11 @@ public class SWTConsole extends Composite implements ConsoleManager {
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.ConsoleManager#prompt(java.lang.String) */
|
||||
@Override
|
||||
public String prompt(final String message) {
|
||||
public String prompt(final String message) throws IOException {
|
||||
synchronized (promptLock) {
|
||||
if (isDisposed()) {
|
||||
throw new IOException();
|
||||
}
|
||||
try {
|
||||
Display.getDefault().syncExec(new Runnable() {
|
||||
@SuppressWarnings("synthetic-access")
|
||||
@ -284,6 +291,9 @@ public class SWTConsole extends Composite implements ConsoleManager {
|
||||
});
|
||||
prompting = true;
|
||||
promptLock.wait();
|
||||
if (isDisposed()) {
|
||||
throw new IOException();
|
||||
}
|
||||
} catch (final InterruptedException e) {
|
||||
command = null;
|
||||
} finally {
|
||||
@ -292,7 +302,8 @@ public class SWTConsole extends Composite implements ConsoleManager {
|
||||
@Override
|
||||
public void run() {
|
||||
lblPromptlabel.setText(prompt);
|
||||
lblPromptlabel.pack();
|
||||
// relayout
|
||||
SWTConsole.this.layout();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -317,7 +328,8 @@ public class SWTConsole extends Composite implements ConsoleManager {
|
||||
@Override
|
||||
public void run() {
|
||||
lblPromptlabel.setText(prompt);
|
||||
lblPromptlabel.pack();
|
||||
// relayout
|
||||
SWTConsole.this.layout();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -325,9 +337,22 @@ public class SWTConsole extends Composite implements ConsoleManager {
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.manager.ConsoleManager#close() */
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() {
|
||||
synchronized (promptLock) {
|
||||
promptLock.notify();
|
||||
}
|
||||
if (consoleInput.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
consoleInput.setEnabled(false);
|
||||
consoleOutput.setEnabled(false);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.manager.ConsoleManager#isClosed() */
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return isDisposed();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -79,4 +79,12 @@ public class SWTConsoleShell extends Shell {
|
||||
public ConsoleManager getManager() {
|
||||
return console;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.swt.widgets.Shell#dispose() */
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
console.close();
|
||||
}
|
||||
}
|
||||
|
@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright E. Bigeon (2015)
|
||||
*
|
||||
* emmanuel@bigeon.fr
|
||||
*
|
||||
* This software is a computer program whose purpose is to
|
||||
* provide a swt window 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.
|
||||
*/
|
||||
package fr.bigeon.gclc.swt;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
/** Unit test for simple App. */
|
||||
public class AppTest extends TestCase {
|
||||
protected static final long TWO_SECONDS = 2000;
|
||||
|
||||
/** Create the test case
|
||||
*
|
||||
* @param testName name of the test case */
|
||||
public AppTest(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
/** @return the suite of tests being tested */
|
||||
public static Test suite() {
|
||||
return new TestSuite(AppTest.class);
|
||||
}
|
||||
|
||||
/** Rigourous Test :-) */
|
||||
@SuppressWarnings("static-method")
|
||||
public void testApp() {
|
||||
// Display display = new Display();
|
||||
// final Shell shell = new Shell(display);
|
||||
// shell.setLayout(new GridLayout(1, false));
|
||||
// SWTConsole swtConsole = new SWTConsole(shell, SWT.NONE);
|
||||
// swtConsole.setLayoutData(
|
||||
// new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
|
||||
// final ConsoleApplication appl = new ConsoleApplication(swtConsole,
|
||||
// "exit", "Hello", "See you");
|
||||
// try {
|
||||
// appl.add(new Command("long") {
|
||||
//
|
||||
// @Override
|
||||
// public String tip() {
|
||||
// return "a long running command";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void execute(String... args) {
|
||||
// try {
|
||||
// Thread.sleep(TWO_SECONDS);
|
||||
// } catch (InterruptedException e) {
|
||||
// // TODO Auto-generated catch block
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// } catch (InvalidCommandName e) {
|
||||
// // TODO Auto-generated catch block
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// shell.pack();
|
||||
// shell.open();
|
||||
// Thread applThread = new Thread(new Runnable() {
|
||||
//
|
||||
// @Override
|
||||
// public void run() {
|
||||
// appl.start();
|
||||
// Display.getDefault().syncExec(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// shell.dispose();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// applThread.start();
|
||||
// while (!shell.isDisposed()) {
|
||||
// if (!display.readAndDispatch()) {
|
||||
// display.sleep();
|
||||
// }
|
||||
// }
|
||||
// display.dispose();
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* gclc-swt:fr.bigeon.gclc.swt.SWTConsoleShellTest.java
|
||||
* Created on: Jun 8, 2016
|
||||
*/
|
||||
package fr.bigeon.gclc.swt;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.junit.Test;
|
||||
|
||||
import fr.bigeon.gclc.ConsoleApplication;
|
||||
import fr.bigeon.gclc.command.Command;
|
||||
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* TODO
|
||||
*
|
||||
* @author Emmanuel Bigeon
|
||||
*
|
||||
*/
|
||||
public class SWTConsoleShellTest {
|
||||
|
||||
protected static final long TWO_SECONDS = 2000;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
Display display = new Display();
|
||||
final SWTConsoleShell shell = new SWTConsoleShell(display);
|
||||
ConsoleManager swtConsole = shell.getManager();
|
||||
try {
|
||||
final ConsoleApplication appl = new ConsoleApplication(swtConsole,
|
||||
"exit", "Hello", "See you");
|
||||
appl.add(new Command("long") {
|
||||
|
||||
@Override
|
||||
public String tip() {
|
||||
return "a long running command";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String... args) {
|
||||
try {
|
||||
Thread.sleep(TWO_SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
// shell.pack();
|
||||
shell.open();
|
||||
Thread applThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
appl.start();
|
||||
}
|
||||
});
|
||||
Thread testThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(TWO_SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
Display.getDefault().syncExec(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
shell.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
applThread.start();
|
||||
testThread.start();
|
||||
while (!shell.isDisposed()) {
|
||||
if (!display.readAndDispatch()) {
|
||||
display.sleep();
|
||||
}
|
||||
}
|
||||
// display.dispose();
|
||||
assertTrue(appl.getManager().isClosed());
|
||||
Thread.sleep(TWO_SECONDS);
|
||||
assertFalse(appl.isRunning());
|
||||
} catch (InvalidCommandName e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -36,7 +36,7 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>gclc</artifactId>
|
||||
<version>1.1.3-SNAPSHOT</version>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<url>http://www.bigeon.fr/emmanuel</url>
|
||||
<properties>
|
||||
|
@ -36,12 +36,14 @@
|
||||
* Created on: Sep 6, 2014 */
|
||||
package fr.bigeon.gclc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import fr.bigeon.gclc.command.ExitCommand;
|
||||
import fr.bigeon.gclc.command.HelpExecutor;
|
||||
import fr.bigeon.gclc.command.ICommand;
|
||||
import fr.bigeon.gclc.command.ICommandProvider;
|
||||
@ -53,7 +55,6 @@ import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||
import fr.bigeon.gclc.i18n.Messages;
|
||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
import fr.bigeon.gclc.manager.SystemConsoleManager;
|
||||
import fr.bigeon.gclc.prompt.CLIPrompterMessages;
|
||||
|
||||
/** <p>
|
||||
* A {@link ConsoleApplication} is an application that require the user to input
|
||||
@ -64,7 +65,7 @@ import fr.bigeon.gclc.prompt.CLIPrompterMessages;
|
||||
* <pre>
|
||||
* {@link ConsoleApplication} app = new {@link ConsoleApplication#ConsoleApplication(String, String, String) ConsoleApplication("exit", "welcome", "see you latter")};
|
||||
* app.{@link ConsoleApplication#add(ICommand) add}("my_command", new {@link ICommand MyCommand()});
|
||||
* app.start();
|
||||
* app.{@link ConsoleApplication#start start}();
|
||||
* </pre>
|
||||
* <p>
|
||||
* That will launch in the console application that will display "welcome",
|
||||
@ -107,7 +108,10 @@ public class ConsoleApplication implements ICommandProvider {
|
||||
* @param welcome the header message to display on launch of this
|
||||
* application
|
||||
* @param goodbye the message to display on exit
|
||||
* @throws InvalidCommandName if the exit command name is invalid */
|
||||
* @throws InvalidCommandName if the exit command name is invalid
|
||||
* @deprecated since 1.2.0, use the {@link #add(ICommand)} method to add the
|
||||
* exit command */
|
||||
@Deprecated
|
||||
public ConsoleApplication(ConsoleManager manager, String exit,
|
||||
String welcome, String goodbye) throws InvalidCommandName {
|
||||
this(manager, welcome, goodbye);
|
||||
@ -118,7 +122,12 @@ public class ConsoleApplication implements ICommandProvider {
|
||||
* @param welcome the header message to display on launch of this
|
||||
* application
|
||||
* @param goodbye the message to display on exit
|
||||
* @throws InvalidCommandName if the exit command name is invalid */
|
||||
* @throws InvalidCommandName if the exit command name is invalid
|
||||
* @deprecated since 1.2.0, use the {@link #add(ICommand)} method to add the
|
||||
* command and create this console using the
|
||||
* {@link #ConsoleApplication(ConsoleManager, String, String)}
|
||||
* method with a {@link SystemConsoleManager} as argument */
|
||||
@Deprecated
|
||||
public ConsoleApplication(String exit, String welcome,
|
||||
String goodbye) throws InvalidCommandName {
|
||||
this(new SystemConsoleManager(), welcome, goodbye);
|
||||
@ -134,12 +143,19 @@ public class ConsoleApplication implements ICommandProvider {
|
||||
*
|
||||
* @param cmd the handle for help
|
||||
* @return if the help command was added
|
||||
* @throws InvalidCommandName if the help command was not valid */
|
||||
* @throws InvalidCommandName if the help command was not valid
|
||||
* @deprecated since 1.2.0 use the {@link #add(ICommand)} with a
|
||||
* {@link HelpExecutor} instead */
|
||||
@Deprecated
|
||||
public final boolean addHelpCommand(String cmd) throws InvalidCommandName {
|
||||
return root.add(new HelpExecutor(cmd, manager, root));
|
||||
}
|
||||
|
||||
/** @param listener the listener to remove. */
|
||||
/** Add a command request listener.
|
||||
* <p>
|
||||
* A listener can listen several times to the same application.
|
||||
*
|
||||
* @param listener the listener to add. */
|
||||
public final void addListener(CommandRequestListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
@ -149,12 +165,14 @@ public class ConsoleApplication implements ICommandProvider {
|
||||
* fr.bigeon.gclc.command.ICommandProvider#executeSub(java.lang.String,
|
||||
* java.lang.String[]) */
|
||||
@Override
|
||||
public final void executeSub(String command, String... args) {
|
||||
public final void executeSub(String command,
|
||||
String... args) throws CommandRunException {
|
||||
root.executeSub(command, args);
|
||||
}
|
||||
|
||||
/** Exit this running application before next command prompt */
|
||||
public final void exit() {
|
||||
LOGGER.fine("Request exiting application..."); //$NON-NLS-1$
|
||||
running = false;
|
||||
}
|
||||
|
||||
@ -170,11 +188,12 @@ public class ConsoleApplication implements ICommandProvider {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/** @param cmd the command to interpret */
|
||||
public final void interpretCommand(String cmd) {
|
||||
/** @param cmd the command to interpret
|
||||
* @throws IOException if the manager was closed */
|
||||
public final void interpretCommand(String cmd) throws IOException {
|
||||
List<String> args;
|
||||
try {
|
||||
args = splitCommand(cmd);
|
||||
args = GCLCConstants.splitCommand(cmd);
|
||||
} catch (CommandParsingException e1) {
|
||||
manager.println("Command line cannot be parsed"); //$NON-NLS-1$
|
||||
LOGGER.log(Level.INFO, "Invalid user command " + cmd, e1); //$NON-NLS-1$
|
||||
@ -193,63 +212,7 @@ public class ConsoleApplication implements ICommandProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/** Splits a command in the diferrent arguments
|
||||
*
|
||||
* @param cmd the command to split in its parts
|
||||
* @return the list of argument preceded by the command name
|
||||
* @throws CommandParsingException if the parsing of the command failed */
|
||||
private static List<String> splitCommand(String cmd) throws CommandParsingException {
|
||||
final List<String> args = new ArrayList<>();
|
||||
// parse the string to separate arguments
|
||||
int index = 0;
|
||||
int startIndex = 0;
|
||||
boolean escaped = false;
|
||||
boolean inString = false;
|
||||
while (index < cmd.length()) {
|
||||
char c = cmd.charAt(index);
|
||||
index++;
|
||||
if (escaped || c == '\\') {
|
||||
escaped = !escaped;
|
||||
continue;
|
||||
}
|
||||
if (c == ' ' && !inString) {
|
||||
final String arg = cmd.substring(startIndex, index - 1);
|
||||
if (!arg.isEmpty()) {
|
||||
args.add(arg);
|
||||
}
|
||||
startIndex = index;
|
||||
} else if (c == '"') {
|
||||
if (inString) {
|
||||
inString = false;
|
||||
args.add(endOfString(cmd, startIndex, index));
|
||||
index++;
|
||||
startIndex = index;
|
||||
}
|
||||
inString = startIndex == index - 1;
|
||||
}
|
||||
}
|
||||
final String arg = cmd.substring(startIndex, cmd.length());
|
||||
if (!arg.isEmpty()) {
|
||||
args.add(arg);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
/** @param cmd the command to parse
|
||||
* @param startIndex the starting point of the parsing
|
||||
* @param index the index of the current position
|
||||
* @return the argument
|
||||
* @throws CommandParsingException if the end of string does not mark end of
|
||||
* command and is not followed by a space */
|
||||
private static String endOfString(String cmd, int startIndex,
|
||||
int index) throws CommandParsingException {
|
||||
if (index + 1 < cmd.length() && cmd.charAt(index + 1) != ' ') {
|
||||
throw new CommandParsingException("Misplaced quote"); //$NON-NLS-1$
|
||||
}
|
||||
return cmd.substring(startIndex + 1, index - 1);
|
||||
}
|
||||
|
||||
/** @param listener the listener to remove */
|
||||
/** @param listener the listener to remove (once) */
|
||||
public final void removeListener(CommandRequestListener listener) {
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
if (listeners.get(i) == listener) {
|
||||
@ -261,13 +224,14 @@ public class ConsoleApplication implements ICommandProvider {
|
||||
|
||||
/** Launches the prompting application */
|
||||
public final void start() {
|
||||
try {
|
||||
running = true;
|
||||
if (header != null) {
|
||||
manager.println(header);
|
||||
}
|
||||
running = true;
|
||||
do {
|
||||
final String cmd = manager.prompt();
|
||||
if (cmd.isEmpty()) {
|
||||
if (cmd == null || cmd.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (final CommandRequestListener listener : listeners) {
|
||||
@ -278,56 +242,23 @@ public class ConsoleApplication implements ICommandProvider {
|
||||
if (footer != null) {
|
||||
manager.println(footer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>
|
||||
* A command to exit a {@link ConsoleApplication}.
|
||||
*
|
||||
* @author Emmanuel BIGEON */
|
||||
class ExitCommand implements ICommand {
|
||||
/** The exit command manual message key */
|
||||
private static final String EXIT_MAN = "exit.man"; //$NON-NLS-1$
|
||||
/** The tip of the exit command */
|
||||
private static final String EXIT = "exit.tip"; //$NON-NLS-1$
|
||||
/** The application that will be exited when this command runs */
|
||||
private final ConsoleApplication app;
|
||||
/** The exit command name */
|
||||
private final String name;
|
||||
|
||||
/** @param name the name of the command
|
||||
* @param app the application to exit */
|
||||
public ExitCommand(String name, ConsoleApplication app) {
|
||||
this.name = name;
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
/** The actions to take before exiting */
|
||||
public void beforeExit() {
|
||||
// Do nothing by default
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void execute(String... args) {
|
||||
beforeExit();
|
||||
app.exit();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.command.ICommand#getCommandName() */
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void help(ConsoleManager manager, String... args) {
|
||||
manager.println(
|
||||
CLIPrompterMessages.getString(EXIT_MAN, (Object[]) args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tip() {
|
||||
return CLIPrompterMessages.getString(EXIT);
|
||||
LOGGER.fine("Exiting application."); //$NON-NLS-1$
|
||||
} catch (IOException e) {
|
||||
// The manager was closed
|
||||
running = false;
|
||||
LOGGER.log(Level.WARNING,
|
||||
"The console manager was closed. Closing the application as no one can reach it.", //$NON-NLS-1$
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/** @return if the application is running */
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
/** @return the root */
|
||||
public SubedCommand getRoot() {
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
129
gclc/src/main/java/fr/bigeon/gclc/GCLCConstants.java
Normal file
129
gclc/src/main/java/fr/bigeon/gclc/GCLCConstants.java
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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.GCLCConstants.java
|
||||
* Created on: Jun 8, 2016
|
||||
*/
|
||||
package fr.bigeon.gclc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import fr.bigeon.gclc.exception.CommandParsingException;
|
||||
|
||||
/** A Utility class for GCLC
|
||||
* <p>
|
||||
* This class offers a method to split a line or arguments into the list of
|
||||
* arguments.
|
||||
*
|
||||
* @author Emmanuel Bigeon */
|
||||
public class GCLCConstants {
|
||||
|
||||
/** Hide utility class constructor */
|
||||
private GCLCConstants() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
/** Splits a command in the diferrent arguments
|
||||
*
|
||||
* @param cmd the command to split in its parts
|
||||
* @return the list of argument preceded by the command name
|
||||
* @throws CommandParsingException if the parsing of the command failed */
|
||||
public static List<String> splitCommand(String cmd) throws CommandParsingException {
|
||||
final List<String> args = new ArrayList<>();
|
||||
// parse the string to separate arguments
|
||||
int index = 0;
|
||||
int startIndex = 0;
|
||||
boolean escaped = false;
|
||||
boolean inString = false;
|
||||
while (index < cmd.length()) {
|
||||
char c = cmd.charAt(index);
|
||||
index++;
|
||||
if (escaped || c == '\\') {
|
||||
escaped = !escaped;
|
||||
continue;
|
||||
}
|
||||
if (c == ' ' && !inString) {
|
||||
final String arg = cmd.substring(startIndex, index - 1);
|
||||
if (!arg.isEmpty()) {
|
||||
args.add(removeEscaped(arg));
|
||||
}
|
||||
startIndex = index;
|
||||
} else if (c == '"') {
|
||||
if (inString) {
|
||||
args.add(endOfString(cmd, startIndex, index));
|
||||
index++;
|
||||
startIndex = index;
|
||||
}
|
||||
inString = startIndex == index - 1;
|
||||
}
|
||||
}
|
||||
final String arg = cmd.substring(startIndex, cmd.length());
|
||||
if (!arg.isEmpty()) {
|
||||
args.add(arg);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
/** @param arg the string to remove excaping character from
|
||||
* @return the string without escape character */
|
||||
private static String removeEscaped(String arg) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int index = 0;
|
||||
int endIndex = arg.indexOf('\\');
|
||||
while (endIndex != -1) {
|
||||
builder.append(arg.subSequence(index, endIndex));
|
||||
index = endIndex + 1;
|
||||
endIndex = arg.indexOf('\\', index + 1);
|
||||
}
|
||||
builder.append(arg.substring(index));
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/** @param cmd the command to parse
|
||||
* @param startIndex the starting point of the parsing
|
||||
* @param index the index of the current position
|
||||
* @return the argument
|
||||
* @throws CommandParsingException if the end of string does not mark end of
|
||||
* command and is not followed by a space */
|
||||
private static String endOfString(String cmd, int startIndex,
|
||||
int index) throws CommandParsingException {
|
||||
if (index < cmd.length() && cmd.charAt(index) != ' ') {
|
||||
throw new CommandParsingException("Misplaced quote"); //$NON-NLS-1$
|
||||
}
|
||||
return cmd.substring(startIndex + 1, index - 1);
|
||||
}
|
||||
|
||||
}
|
@ -38,23 +38,25 @@
|
||||
*/
|
||||
package fr.bigeon.gclc.command;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
|
||||
/** <p>
|
||||
* A command to execute. It is mandatory that it has a name and that name cannot
|
||||
* start with minus character or contain space.
|
||||
* start with minus character or contain spaces.
|
||||
* <p>
|
||||
* A command can be executed, with parameters that will be provided as an array
|
||||
* of strings.
|
||||
* <p>
|
||||
* The help mechanism can be overwritten, but is by default doing the following:
|
||||
* The help mechanism is doing the following:
|
||||
* <ul>
|
||||
* <li>Print the command name
|
||||
* <li>Print the {@link #brief()} message
|
||||
* <li>Print a blank line
|
||||
* <li>Print "Usage:"
|
||||
* <li>Print the usage pattern
|
||||
* <li>Print the usage details
|
||||
* <li>Print the {@link #usagePattern() usage pattern}
|
||||
* <li>Print the {@link #usageDetail() usage details}
|
||||
* </ul>
|
||||
* <p>
|
||||
* The default behavior for the brief message is to print the tip preceeded by a
|
||||
@ -92,7 +94,8 @@ public abstract class Command implements ICommand {
|
||||
* @see fr.bigeon.gclc.command.ICommand#help(fr.bigeon.gclc.ConsoleManager,
|
||||
* java.lang.String) */
|
||||
@Override
|
||||
public final void help(ConsoleManager manager, String... args) {
|
||||
public final void help(ConsoleManager manager,
|
||||
String... args) throws IOException {
|
||||
manager.println(getCommandName());
|
||||
manager.println(brief());
|
||||
manager.println();
|
||||
|
@ -39,7 +39,9 @@ package fr.bigeon.gclc.command;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import fr.bigeon.gclc.exception.CommandRunException;
|
||||
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||
import fr.bigeon.gclc.i18n.Messages;
|
||||
|
||||
/** <p>
|
||||
* A command provider is a map of key word to command to execute
|
||||
@ -52,14 +54,11 @@ public class CommandProvider implements ICommandProvider {
|
||||
private static final String SPACE = " "; //$NON-NLS-1$
|
||||
/** The commands map */
|
||||
protected final Set<ICommand> commands;
|
||||
/** The error command to be executed when the command isn't recognized */
|
||||
protected final ICommand error;
|
||||
|
||||
/** @param error the error command */
|
||||
public CommandProvider(ICommand error) {
|
||||
/** Create a command provider */
|
||||
public CommandProvider() {
|
||||
super();
|
||||
commands = new HashSet<>();
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@ -75,14 +74,16 @@ public class CommandProvider implements ICommandProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeSub(String cmd, String... args) {
|
||||
public void executeSub(String cmd,
|
||||
String... args) throws CommandRunException {
|
||||
for (final ICommand command : commands) {
|
||||
if (command.getCommandName().equals(cmd)) {
|
||||
command.execute(args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
error.execute(cmd);
|
||||
throw new CommandRunException(
|
||||
Messages.getString("CommandProvider.unrecognized0", cmd)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
97
gclc/src/main/java/fr/bigeon/gclc/command/ExitCommand.java
Normal file
97
gclc/src/main/java/fr/bigeon/gclc/command/ExitCommand.java
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.ExitCommand.java
|
||||
* Created on: Jun 8, 2016
|
||||
*/
|
||||
package fr.bigeon.gclc.command;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import fr.bigeon.gclc.ConsoleApplication;
|
||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
import fr.bigeon.gclc.prompt.CLIPrompterMessages;
|
||||
|
||||
/** <p>
|
||||
* A command to exit a {@link ConsoleApplication}.
|
||||
*
|
||||
* @author Emmanuel BIGEON */
|
||||
public class ExitCommand implements ICommand {
|
||||
/** The exit command manual message key */
|
||||
private static final String EXIT_MAN = "exit.man"; //$NON-NLS-1$
|
||||
/** The tip of the exit command */
|
||||
private static final String EXIT = "exit.tip"; //$NON-NLS-1$
|
||||
/** The application that will be exited when this command runs */
|
||||
private final ConsoleApplication app;
|
||||
/** The exit command name */
|
||||
private final String name;
|
||||
|
||||
/** @param name the name of the command
|
||||
* @param app the application to exit */
|
||||
public ExitCommand(String name, ConsoleApplication app) {
|
||||
this.name = name;
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
/** The actions to take before exiting */
|
||||
public void beforeExit() {
|
||||
// Do nothing by default
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void execute(String... args) {
|
||||
beforeExit();
|
||||
app.exit();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.command.ICommand#getCommandName() */
|
||||
@Override
|
||||
public final String getCommandName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void help(ConsoleManager manager,
|
||||
String... args) throws IOException {
|
||||
manager.println(
|
||||
CLIPrompterMessages.getString(EXIT_MAN, (Object[]) args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tip() {
|
||||
return CLIPrompterMessages.getString(EXIT);
|
||||
}
|
||||
}
|
@ -38,6 +38,9 @@
|
||||
*/
|
||||
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;
|
||||
|
||||
@ -70,8 +73,12 @@ public class HelpExecutor extends Command {
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.command.Command#execute(java.lang.String[]) */
|
||||
@Override
|
||||
public void execute(String... args) {
|
||||
public void execute(String... args) throws CommandRunException {
|
||||
try {
|
||||
cmd.help(consoleManager, args);
|
||||
} catch (IOException e) {
|
||||
throw new CommandRunException("Console manager closed", e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -38,6 +38,9 @@
|
||||
*/
|
||||
package fr.bigeon.gclc.command;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import fr.bigeon.gclc.exception.CommandRunException;
|
||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
|
||||
/** The contract of commands
|
||||
@ -47,8 +50,10 @@ import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
* @author Emmanuel Bigeon */
|
||||
public interface ICommand {
|
||||
|
||||
/** @param args the arguments of the command (some expect an empty array) */
|
||||
void execute(String... args);
|
||||
/** @param args the arguments of the command (some expect an empty array)
|
||||
* @throws CommandRunException if the execution of the command failed for
|
||||
* any reason */
|
||||
void execute(String... args) throws CommandRunException;
|
||||
|
||||
/** @return the command's name */
|
||||
String getCommandName();
|
||||
@ -68,8 +73,9 @@ public interface ICommand {
|
||||
* </pre>
|
||||
*
|
||||
* @param manager the manager to print the data
|
||||
* @param args the arguments called with the help */
|
||||
void help(ConsoleManager manager, String... args);
|
||||
* @param args the arguments called with the help
|
||||
* @throws IOException if the manager was closed */
|
||||
void help(ConsoleManager manager, String... args) throws IOException;
|
||||
|
||||
/** @return a tip on the command */
|
||||
String tip();
|
||||
|
@ -36,6 +36,7 @@
|
||||
* Created on: Sep 6, 2014 */
|
||||
package fr.bigeon.gclc.command;
|
||||
|
||||
import fr.bigeon.gclc.exception.CommandRunException;
|
||||
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||
|
||||
/** <p>
|
||||
@ -62,8 +63,10 @@ public interface ICommandProvider {
|
||||
* the user for a choice.
|
||||
*
|
||||
* @param command the name of the command the user wishes to execute
|
||||
* @param args the arguments for the command */
|
||||
public void executeSub(String command, String... args);
|
||||
* @param args the arguments for the command
|
||||
* @throws CommandRunException if the command failed to run */
|
||||
public void executeSub(String command,
|
||||
String... args) throws CommandRunException;
|
||||
|
||||
/** <p>
|
||||
* This method provide the command with the given name found. If no command
|
||||
|
@ -38,11 +38,13 @@
|
||||
*/
|
||||
package fr.bigeon.gclc.command;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import fr.bigeon.gclc.exception.CommandRunException;
|
||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
|
||||
/** <p>
|
||||
@ -115,13 +117,12 @@ public abstract class ParametrizedCommand extends Command {
|
||||
* @see fr.bigeon.gclc.command.Command#execute(java.lang.String[]) */
|
||||
@SuppressWarnings("boxing")
|
||||
@Override
|
||||
public final void execute(String... args) {
|
||||
public final void execute(String... args) throws CommandRunException {
|
||||
final CommandParameters parameters = new CommandParameters(
|
||||
boolParams.keySet(), stringParams.keySet(), strict);
|
||||
if (!parameters.parseArgs(args)) {
|
||||
// ERROR the parameters could not be correctly parsed
|
||||
manager.println("Unable to read arguments"); //$NON-NLS-1$
|
||||
return;
|
||||
throw new CommandRunException("Unable to read arguments"); //$NON-NLS-1$
|
||||
}
|
||||
final List<String> toProvide = new ArrayList<>();
|
||||
for (final String string : params.keySet()) {
|
||||
@ -133,13 +134,27 @@ public abstract class ParametrizedCommand extends Command {
|
||||
}
|
||||
}
|
||||
// for each needed parameters that is missing, prompt the user.
|
||||
fillParameters(toProvide, parameters);
|
||||
doExecute(parameters);
|
||||
}
|
||||
|
||||
/** @param parameters the parameter list to complete
|
||||
* @param toProvide the parameters to ask for
|
||||
* @throws CommandRunException if the manager was closed */
|
||||
private void fillParameters(List<String> toProvide,
|
||||
CommandParameters parameters) throws CommandRunException {
|
||||
for (final String string : toProvide) {
|
||||
String value = manager.prompt(string);
|
||||
String value;
|
||||
try {
|
||||
value = manager.prompt(string);
|
||||
while (value.isEmpty()) {
|
||||
value = manager.prompt(string);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new CommandRunException(
|
||||
"Interactive command but manager closed...", e); //$NON-NLS-1$
|
||||
}
|
||||
parameters.set(string, value);
|
||||
}
|
||||
doExecute(parameters);
|
||||
}
|
||||
}
|
||||
|
@ -36,8 +36,10 @@
|
||||
* Created on: Sep 6, 2014 */
|
||||
package fr.bigeon.gclc.command;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import fr.bigeon.gclc.exception.CommandRunException;
|
||||
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
|
||||
@ -61,44 +63,40 @@ public class SubedCommand implements ICommandProvider, ICommand {
|
||||
/** The name of the command */
|
||||
private final String name;
|
||||
|
||||
/** @param name the name of the command
|
||||
* @param error the error to execute when called with wrong usage */
|
||||
public SubedCommand(String name, ICommand error) {
|
||||
/** @param name the name of the command */
|
||||
public SubedCommand(String name) {
|
||||
this.name = name;
|
||||
provider = new CommandProvider(error);
|
||||
provider = new CommandProvider();
|
||||
noArgCommand = null;
|
||||
tip = null;
|
||||
}
|
||||
|
||||
/** @param name the name of the command
|
||||
* @param noArgCommand the command to execute when no extra parameter are
|
||||
* provided
|
||||
* @param error the error to execute when called with wrong usage */
|
||||
public SubedCommand(String name, ICommand error, ICommand noArgCommand) {
|
||||
* provided */
|
||||
public SubedCommand(String name, ICommand noArgCommand) {
|
||||
this.name = name;
|
||||
provider = new CommandProvider(error);
|
||||
provider = new CommandProvider();
|
||||
this.noArgCommand = noArgCommand;
|
||||
tip = null;
|
||||
}
|
||||
|
||||
/** @param name the name of the command
|
||||
* @param noArgCommand the command to execute
|
||||
* @param error the error to execute when called with wrong usage
|
||||
* @param tip the help tip associated */
|
||||
public SubedCommand(String name, ICommand error, ICommand noArgCommand,
|
||||
public SubedCommand(String name, ICommand noArgCommand,
|
||||
String tip) {
|
||||
this.name = name;
|
||||
provider = new CommandProvider(error);
|
||||
provider = new CommandProvider();
|
||||
this.noArgCommand = noArgCommand;
|
||||
this.tip = tip;
|
||||
}
|
||||
|
||||
/** @param name the name of the command
|
||||
* @param error the error to execute when called with wrong usage
|
||||
* @param tip the help tip associated */
|
||||
public SubedCommand(String name, ICommand error, String tip) {
|
||||
public SubedCommand(String name, String tip) {
|
||||
this.name = name;
|
||||
provider = new CommandProvider(error);
|
||||
provider = new CommandProvider();
|
||||
noArgCommand = null;
|
||||
this.tip = tip;
|
||||
}
|
||||
@ -111,12 +109,12 @@ public class SubedCommand implements ICommandProvider, ICommand {
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.acide.Command#execute(java.lang.String[]) */
|
||||
@Override
|
||||
public void execute(String... args) {
|
||||
public void execute(String... args) throws CommandRunException {
|
||||
if (args.length == 0 || args[0].startsWith("-")) { //$NON-NLS-1$
|
||||
if (noArgCommand != null) {
|
||||
noArgCommand.execute(args);
|
||||
} else {
|
||||
provider.error.execute(args);
|
||||
throw new CommandRunException("Unrecognized command"); //$NON-NLS-1$
|
||||
}
|
||||
} else {
|
||||
executeSub(args[0], Arrays.copyOfRange(args, 1, args.length));
|
||||
@ -128,7 +126,8 @@ public class SubedCommand implements ICommandProvider, ICommand {
|
||||
* fr.bigeon.gclc.command.ICommandProvider#executeSub(java.lang.String,
|
||||
* java.lang.String[]) */
|
||||
@Override
|
||||
public void executeSub(String command, String... args) {
|
||||
public void executeSub(String command,
|
||||
String... args) throws CommandRunException {
|
||||
provider.executeSub(command, args);
|
||||
}
|
||||
|
||||
@ -147,14 +146,13 @@ public class SubedCommand implements ICommandProvider, ICommand {
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.command.Command#help() */
|
||||
@Override
|
||||
public void help(ConsoleManager manager, String... args) {
|
||||
public void help(ConsoleManager manager,
|
||||
String... args) throws IOException {
|
||||
if (args.length != 0 && !args[0].startsWith("-")) { //$NON-NLS-1$
|
||||
// Specific
|
||||
final ICommand c = get(args[0]);
|
||||
if (c != null) {
|
||||
c.help(manager, Arrays.copyOfRange(args, 1, args.length));
|
||||
} else {
|
||||
provider.error.execute(args);
|
||||
}
|
||||
} else {
|
||||
// Generic
|
||||
|
@ -38,6 +38,9 @@
|
||||
*/
|
||||
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;
|
||||
|
||||
@ -62,13 +65,18 @@ public final class UnrecognizedCommand implements ICommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String... args) {
|
||||
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)
|
||||
|
@ -42,7 +42,7 @@ package fr.bigeon.gclc.exception;
|
||||
* An exception thrown when a command failed to run correctly.
|
||||
*
|
||||
* @author Emmanuel BIGEON */
|
||||
public class CommandRunException extends RuntimeException {
|
||||
public class CommandRunException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -52,21 +52,32 @@ public interface ConsoleManager {
|
||||
/** @return the prompt prefix */
|
||||
String getPrompt();
|
||||
|
||||
/** @param text the message to print (without line break at the end). */
|
||||
void print(String text);
|
||||
/** @param text the message to print (without line break at the end).
|
||||
* @throws IOException if the manager is closed or could not read the
|
||||
* prompt */
|
||||
void print(String text) throws IOException;
|
||||
|
||||
/** Prints an end of line */
|
||||
void println();
|
||||
/** Prints an end of line
|
||||
*
|
||||
* @throws IOException if the manager is closed or could not read the
|
||||
* prompt */
|
||||
void println() throws IOException;
|
||||
|
||||
/** @param message the message to print */
|
||||
void println(String message);
|
||||
/** @param message the message to print
|
||||
* @throws IOException if the manager is closed or could not read the
|
||||
* prompt */
|
||||
void println(String message) throws IOException;
|
||||
|
||||
/** @return the user inputed string */
|
||||
String prompt();
|
||||
/** @return the user inputed string
|
||||
* @throws IOException if the manager is closed or could not read the
|
||||
* prompt */
|
||||
String prompt() throws IOException;
|
||||
|
||||
/** @param message the message to prompt the user
|
||||
* @return the user inputed string */
|
||||
String prompt(String message);
|
||||
* @return the user inputed string
|
||||
* @throws IOException if the manager is closed or could not read the
|
||||
* prompt */
|
||||
String prompt(String message) throws IOException;
|
||||
|
||||
/** <p>
|
||||
* Set a prompting prefix.
|
||||
@ -74,6 +85,11 @@ public interface ConsoleManager {
|
||||
* @param prompt the prompt */
|
||||
void setPrompt(String prompt);
|
||||
|
||||
/** @throws IOException if the close raised an exception */
|
||||
/** Closes the manager.
|
||||
*
|
||||
* @throws IOException if the close raised an exception */
|
||||
void close() throws IOException;
|
||||
|
||||
/** @return if the manager is closed. */
|
||||
boolean isClosed();
|
||||
}
|
||||
|
@ -38,8 +38,10 @@
|
||||
*/
|
||||
package fr.bigeon.gclc.manager;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@ -64,13 +66,15 @@ public class SystemConsoleManager implements ConsoleManager { // NOSONAR
|
||||
/** The print stream */
|
||||
private final PrintStream out;
|
||||
/** The input stream */
|
||||
private final InputStream in;
|
||||
private final BufferedReader in;
|
||||
|
||||
/** If the manager is closed */
|
||||
private boolean closed = false;
|
||||
|
||||
/** This default constructor relies on the system defined standart output
|
||||
* and input stream. */
|
||||
public SystemConsoleManager() {
|
||||
out = System.out; // NOSONAR
|
||||
in = System.in;
|
||||
this(System.out, System.in);
|
||||
}
|
||||
|
||||
/** @param out the output stream
|
||||
@ -78,7 +82,7 @@ public class SystemConsoleManager implements ConsoleManager { // NOSONAR
|
||||
public SystemConsoleManager(PrintStream out, InputStream in) {
|
||||
super();
|
||||
this.out = out;
|
||||
this.in = in;
|
||||
this.in = new BufferedReader(new InputStreamReader(in));
|
||||
}
|
||||
|
||||
/** @return the prompt */
|
||||
@ -90,47 +94,60 @@ public class SystemConsoleManager implements ConsoleManager { // NOSONAR
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.ConsoleManager#print(java.lang.Object) */
|
||||
@Override
|
||||
public void print(String object) {
|
||||
public void print(String object) throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException();
|
||||
}
|
||||
out.print(object);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.ConsoleManager#println() */
|
||||
@Override
|
||||
public void println() {
|
||||
public void println() throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException();
|
||||
}
|
||||
out.println();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.ConsoleManager#println(java.lang.Object) */
|
||||
@Override
|
||||
public void println(String object) {
|
||||
public void println(String object) throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException();
|
||||
}
|
||||
out.println(object);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.ConsoleManager#prompt() */
|
||||
@Override
|
||||
public String prompt() {
|
||||
public String prompt() throws IOException {
|
||||
return prompt(new String() + prompt);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.ConsoleManager#prompt(java.lang.String) */
|
||||
@Override
|
||||
public String prompt(String message) {
|
||||
public String prompt(String message) throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException();
|
||||
}
|
||||
String result = new String();
|
||||
out.print(message + ' ');
|
||||
char c;
|
||||
try {
|
||||
c = (char) in.read();
|
||||
while (c != System.lineSeparator().charAt(0)) {
|
||||
result += c;
|
||||
c = (char) in.read();
|
||||
}
|
||||
while (in.available() != 0) {
|
||||
in.read();
|
||||
}
|
||||
result = in.readLine();
|
||||
// c = (char) in.read();
|
||||
// while (c != System.lineSeparator().charAt(0)) {
|
||||
// result += c;
|
||||
// c = (char) in.read();
|
||||
// }
|
||||
// while (in.available() != 0) {
|
||||
// in.read();
|
||||
// }
|
||||
} catch (final IOException e) {
|
||||
LOGGER.log(Level.SEVERE, "Unable to read prompt", e); //$NON-NLS-1$
|
||||
}
|
||||
@ -147,7 +164,14 @@ public class SystemConsoleManager implements ConsoleManager { // NOSONAR
|
||||
* @see fr.bigeon.gclc.manager.ConsoleManager#close() */
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
in.close();
|
||||
closed = true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.bigeon.gclc.manager.ConsoleManager#isClosed() */
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
* Created on: Jul 31, 2014 */
|
||||
package fr.bigeon.gclc.prompt;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -80,9 +81,10 @@ public class CLIPrompter {
|
||||
* @param choices the choices
|
||||
* @param cancel the cancel option if it exists
|
||||
* @return the number of choices plus one (or the number of choices if there
|
||||
* is a cancel) */
|
||||
* is a cancel)
|
||||
* @throws IOException if the manager was closed */
|
||||
private static <U> int listChoices(ConsoleManager manager, List<U> choices,
|
||||
String cancel) {
|
||||
String cancel) throws IOException {
|
||||
int index = 0;
|
||||
for (final U u : choices) {
|
||||
manager.println(index++ + ") " + u); //$NON-NLS-1$
|
||||
@ -95,9 +97,10 @@ public class CLIPrompter {
|
||||
|
||||
/** @param manager the manager
|
||||
* @param message the prompting message
|
||||
* @return the choice */
|
||||
* @return the choice
|
||||
* @throws IOException if the manager was closed */
|
||||
public static boolean promptBoolean(ConsoleManager manager,
|
||||
String message) {
|
||||
String message) throws IOException {
|
||||
String result = manager
|
||||
.prompt(message + CLIPrompterMessages.getString(BOOL_CHOICES));
|
||||
boolean first = true;
|
||||
@ -134,11 +137,12 @@ public class CLIPrompter {
|
||||
* @param message the message
|
||||
* @param cancel the cancel option, or null
|
||||
* @param <U> the type of elements
|
||||
* @return the choice */
|
||||
* @return the choice
|
||||
* @throws IOException if the manager was closed */
|
||||
@SuppressWarnings("boxing")
|
||||
public static <U> U promptChoice(ConsoleManager manager, List<String> keys,
|
||||
List<U> choices, String message,
|
||||
String cancel) {
|
||||
String cancel) throws IOException {
|
||||
final Integer index = promptChoice(manager, keys, message, cancel);
|
||||
if (index == null) {
|
||||
return null;
|
||||
@ -153,10 +157,11 @@ public class CLIPrompter {
|
||||
* @param choicesMap the map of label to actual objects
|
||||
* @param message the prompting message
|
||||
* @param cancel the cancel option if it exists (null otherwise)
|
||||
* @return the chosen object */
|
||||
* @return the chosen object
|
||||
* @throws IOException if the manager was closed */
|
||||
public static <U, T> T promptChoice(ConsoleManager manager, List<U> choices,
|
||||
Map<U, T> choicesMap, String message,
|
||||
String cancel) {
|
||||
String cancel) throws IOException {
|
||||
return choicesMap.get(choices.get(
|
||||
promptChoice(manager, choices, message, cancel).intValue()));
|
||||
}
|
||||
@ -166,11 +171,12 @@ public class CLIPrompter {
|
||||
* @param choices the list of choices
|
||||
* @param message the prompting message
|
||||
* @param cancel the cancel option, or null
|
||||
* @return the index of the choice */
|
||||
* @return the index of the choice
|
||||
* @throws IOException if the manager was closed */
|
||||
@SuppressWarnings("boxing")
|
||||
public static <U> Integer promptChoice(ConsoleManager manager,
|
||||
List<U> choices, String message,
|
||||
String cancel) {
|
||||
String cancel) throws IOException {
|
||||
manager.println(message);
|
||||
final int index = listChoices(manager, choices, cancel);
|
||||
String result = ""; //$NON-NLS-1$
|
||||
@ -207,18 +213,21 @@ public class CLIPrompter {
|
||||
* @param choicesMap the map of label to actual objects
|
||||
* @param message the prompting message
|
||||
* @param cancel the cancel option (or null)
|
||||
* @return the chosen object */
|
||||
* @return the chosen object
|
||||
* @throws IOException if the manager was closed */
|
||||
public static <U, T> T promptChoice(ConsoleManager manager,
|
||||
Map<U, T> choicesMap, String message,
|
||||
String cancel) {
|
||||
String cancel) throws IOException {
|
||||
return promptChoice(manager, new ArrayList<>(choicesMap.keySet()),
|
||||
choicesMap, message, cancel);
|
||||
}
|
||||
|
||||
/** @param manager the manager
|
||||
* @param message the prompt message
|
||||
* @return the integer */
|
||||
public static int promptInteger(ConsoleManager manager, String message) {
|
||||
* @return the integer
|
||||
* @throws IOException if the manager was closed */
|
||||
public static int promptInteger(ConsoleManager manager,
|
||||
String message) throws IOException {
|
||||
boolean still = true;
|
||||
int r = 0;
|
||||
while (still) {
|
||||
@ -243,9 +252,10 @@ public class CLIPrompter {
|
||||
*
|
||||
* @param manager the manager
|
||||
* @param message the message
|
||||
* @return the list of user inputs */
|
||||
* @return the list of user inputs
|
||||
* @throws IOException if the manager was closed */
|
||||
public static List<String> promptList(ConsoleManager manager,
|
||||
String message) {
|
||||
String message) throws IOException {
|
||||
return promptList(manager, message,
|
||||
CLIPrompterMessages.getString("promptlist.exit.defaultkey")); //$NON-NLS-1$
|
||||
}
|
||||
@ -255,9 +265,11 @@ public class CLIPrompter {
|
||||
* @param manager the manager
|
||||
* @param message the message
|
||||
* @param ender the ending sequence for the list
|
||||
* @return the list of user inputs */
|
||||
* @return the list of user inputs
|
||||
* @throws IOException if the manager was closed */
|
||||
public static List<String> promptList(ConsoleManager manager,
|
||||
String message, String ender) {
|
||||
String message,
|
||||
String ender) throws IOException {
|
||||
final List<String> strings = new ArrayList<>();
|
||||
manager.println(
|
||||
message + CLIPrompterMessages.getString(LIST_DISP_KEY, ender));
|
||||
@ -275,9 +287,10 @@ public class CLIPrompter {
|
||||
*
|
||||
* @param manager the manager
|
||||
* @param message the prompting message
|
||||
* @return the text */
|
||||
* @return the text
|
||||
* @throws IOException if the manager was closed */
|
||||
public static String promptLongText(ConsoleManager manager,
|
||||
String message) {
|
||||
String message) throws IOException {
|
||||
return promptLongText(manager, message, CLIPrompterMessages
|
||||
.getString("promptlongtext.exit.defaultkey")); //$NON-NLS-1$
|
||||
}
|
||||
@ -287,9 +300,10 @@ public class CLIPrompter {
|
||||
* @param manager the manager
|
||||
* @param message the prompting message
|
||||
* @param ender the ender character
|
||||
* @return the text */
|
||||
* @return the text
|
||||
* @throws IOException if the manager was closed */
|
||||
public static String promptLongText(ConsoleManager manager, String message,
|
||||
String ender) {
|
||||
String ender) throws IOException {
|
||||
manager.println(message + CLIPrompterMessages
|
||||
.getString("promptlongtext.exit.dispkey", ender)); //$NON-NLS-1$
|
||||
String res = manager.prompt(PROMPT);
|
||||
@ -308,11 +322,12 @@ public class CLIPrompter {
|
||||
* @param choices the real choices
|
||||
* @param message the message
|
||||
* @param <U> the type of elements
|
||||
* @return the choice */
|
||||
* @return the choice
|
||||
* @throws IOException if the manager was closed */
|
||||
public static <U> List<U> promptMultiChoice(ConsoleManager manager,
|
||||
List<String> keys,
|
||||
List<U> choices,
|
||||
String message) {
|
||||
String message) throws IOException {
|
||||
final List<Integer> indices = promptMultiChoice(manager, keys, message);
|
||||
final List<U> userChoices = new ArrayList<>();
|
||||
for (final Integer integer : indices) {
|
||||
@ -327,11 +342,12 @@ public class CLIPrompter {
|
||||
* @param choices the list of labels (in order to be displayed)
|
||||
* @param choicesMap the map of label to actual objects
|
||||
* @param message the prompting message
|
||||
* @return the chosen objects (or an empty list) */
|
||||
* @return the chosen objects (or an empty list)
|
||||
* @throws IOException if the manager was closed */
|
||||
public static <U, T> List<T> promptMultiChoice(ConsoleManager manager,
|
||||
List<U> choices,
|
||||
Map<U, T> choicesMap,
|
||||
String message) {
|
||||
String message) throws IOException {
|
||||
final List<Integer> chs = promptMultiChoice(manager, choices, message);
|
||||
final List<T> userChoices = new ArrayList<>();
|
||||
for (final Integer integer : chs) {
|
||||
@ -344,11 +360,12 @@ public class CLIPrompter {
|
||||
* @param <U> the type of choices
|
||||
* @param choices the list of choices
|
||||
* @param message the prompting message
|
||||
* @return the indices of the choices */
|
||||
* @return the indices of the choices
|
||||
* @throws IOException if the manager was closed */
|
||||
@SuppressWarnings("boxing")
|
||||
public static <U> List<Integer> promptMultiChoice(ConsoleManager manager,
|
||||
List<U> choices,
|
||||
String message) {
|
||||
String message) throws IOException {
|
||||
manager.println(message);
|
||||
final int index = listChoices(manager, choices, null);
|
||||
String result = ""; //$NON-NLS-1$
|
||||
@ -404,10 +421,11 @@ public class CLIPrompter {
|
||||
* @param <T> The real choices objects
|
||||
* @param choicesMap the map of label to actual objects
|
||||
* @param message the prompting message
|
||||
* @return the chosen objects */
|
||||
* @return the chosen objects
|
||||
* @throws IOException if the manager was closed */
|
||||
public static <U, T> List<T> promptMultiChoice(ConsoleManager manager,
|
||||
Map<U, T> choicesMap,
|
||||
String message) {
|
||||
String message) throws IOException {
|
||||
return promptMultiChoice(manager, new ArrayList<>(choicesMap.keySet()),
|
||||
choicesMap, message);
|
||||
}
|
||||
@ -415,9 +433,10 @@ public class CLIPrompter {
|
||||
/** @param manager the manager
|
||||
* @param prompt the prompting message
|
||||
* @param reprompt the prompting message after empty input
|
||||
* @return the non empty input */
|
||||
* @return the non empty input
|
||||
* @throws IOException if the manager was closed */
|
||||
public static String promptNonEmpty(ConsoleManager manager, String prompt,
|
||||
String reprompt) {
|
||||
String reprompt) throws IOException {
|
||||
String res = manager.prompt(prompt);
|
||||
while (res.isEmpty()) {
|
||||
res = manager.prompt(reprompt);
|
||||
|
@ -1 +1,2 @@
|
||||
CommandProvider.unrecognized=Unrecognized command '{0}'
|
||||
ConsoleApplication.cmd.failed=The command '{0}' failed due to :
|
||||
|
118
gclc/src/test/java/fr/bigeon/gclc/ConsoleApplicationTest.java
Normal file
118
gclc/src/test/java/fr/bigeon/gclc/ConsoleApplicationTest.java
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.ConsoleApplicationTest.java
|
||||
* Created on: Jun 9, 2016
|
||||
*/
|
||||
package fr.bigeon.gclc;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import fr.bigeon.gclc.manager.SystemConsoleManager;
|
||||
|
||||
/** Test class for ConsoleApplication
|
||||
*
|
||||
* @author Emmanuel Bigeon */
|
||||
@SuppressWarnings("static-method")
|
||||
public class ConsoleApplicationTest {
|
||||
|
||||
protected static final long THREE_SECONDS = 3000;
|
||||
|
||||
/** Test the base of a console application */
|
||||
@Test
|
||||
public void test() {
|
||||
ConsoleTestApplication app = new ConsoleTestApplication(
|
||||
new SystemConsoleManager());
|
||||
app.exit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executionTest() {
|
||||
try {
|
||||
final PipedOutputStream src = new PipedOutputStream();
|
||||
InputStream in = new PipedInputStream(src);
|
||||
|
||||
final PipedInputStream snk = new PipedInputStream();
|
||||
PrintStream out = new PrintStream(new PipedOutputStream(snk));
|
||||
final ConsoleTestApplication app = new ConsoleTestApplication(
|
||||
new SystemConsoleManager(out, in));
|
||||
Thread th = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
app.start();
|
||||
}
|
||||
});
|
||||
|
||||
th.start();
|
||||
|
||||
Thread test = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try (PrintWriter writer = new PrintWriter(src, true)) {
|
||||
writer.println("test");
|
||||
writer.println("long");
|
||||
writer.println("exit");
|
||||
}
|
||||
}
|
||||
});
|
||||
test.start();
|
||||
try {
|
||||
th.join();
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
test.join();
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
fail("pipe creation"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
105
gclc/src/test/java/fr/bigeon/gclc/ConsoleTestApplication.java
Normal file
105
gclc/src/test/java/fr/bigeon/gclc/ConsoleTestApplication.java
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
import fr.bigeon.gclc.exception.CommandRunException;
|
||||
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
|
||||
/** A test-purpose application
|
||||
*
|
||||
* @author Emmanuel Bigeon */
|
||||
public class ConsoleTestApplication extends ConsoleApplication {
|
||||
|
||||
/** Exit command */
|
||||
public static final String EXIT = "exit"; //$NON-NLS-1$
|
||||
/** Two seconds in milliseconds */
|
||||
protected static final long TWO_SECONDS = 2000;
|
||||
|
||||
/** @param manager the manager */
|
||||
@SuppressWarnings("nls")
|
||||
public ConsoleTestApplication(final ConsoleManager manager) {
|
||||
super(manager, "Welcome to the test application. Type help or test.",
|
||||
"See you");
|
||||
try {
|
||||
add(new ExitCommand(EXIT, this));
|
||||
add(new HelpExecutor("help", manager, this.getRoot()));
|
||||
add(new Command("test") {
|
||||
|
||||
@Override
|
||||
public String tip() {
|
||||
return "A test command";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String... args) throws CommandRunException {
|
||||
try {
|
||||
manager.println("Test command ran fine");
|
||||
} catch (IOException e) {
|
||||
throw new CommandRunException("manager closed", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
add(new Command("long") {
|
||||
|
||||
@Override
|
||||
public String tip() {
|
||||
return "A long execution command";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String... args) throws CommandRunException {
|
||||
try {
|
||||
manager.println("Waita minute");
|
||||
Thread.sleep(TWO_SECONDS);
|
||||
manager.println("done!");
|
||||
} catch (IOException e) {
|
||||
throw new CommandRunException("manager closed", e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new CommandRunException("wait interrupted", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (final InvalidCommandName e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
137
gclc/src/test/java/fr/bigeon/gclc/GCLCConstantsTest.java
Normal file
137
gclc/src/test/java/fr/bigeon/gclc/GCLCConstantsTest.java
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.GCLCConstantsTest.java
|
||||
* Created on: Jun 8, 2016
|
||||
*/
|
||||
package fr.bigeon.gclc;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import fr.bigeon.gclc.exception.CommandParsingException;
|
||||
|
||||
/** Test class for {@link GCLCConstants}
|
||||
*
|
||||
* @author Emmanuel Bigeon */
|
||||
@SuppressWarnings({"nls", "static-method"})
|
||||
public class GCLCConstantsTest {
|
||||
|
||||
/**
|
||||
* Test method for {@link fr.bigeon.gclc.GCLCConstants#splitCommand(java.lang.String)}.
|
||||
*/
|
||||
@Test
|
||||
public void testSplitCommand() {
|
||||
List<String> res;
|
||||
try {
|
||||
res = GCLCConstants.splitCommand("aCommand");
|
||||
} catch (CommandParsingException e) {
|
||||
fail("Unable to parse simple command"); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
assertTrue(res.size() == 1);
|
||||
assertTrue(res.get(0).equals("aCommand"));
|
||||
|
||||
try {
|
||||
res = GCLCConstants.splitCommand("aCommand with some arguments");
|
||||
} catch (CommandParsingException e) {
|
||||
fail("Unable to parse command with arguments"); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
assertTrue(res.size() == 4);
|
||||
assertTrue(res.get(0).equals("aCommand"));
|
||||
assertTrue(res.get(1).equals("with"));
|
||||
assertTrue(res.get(2).equals("some"));
|
||||
assertTrue(res.get(3).equals("arguments"));
|
||||
try {
|
||||
res = GCLCConstants.splitCommand("aCommand with some arguments");
|
||||
} catch (CommandParsingException e) {
|
||||
fail("Unable to parse command with arguments and double whitspaces"); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
assertTrue(res.size() == 4);
|
||||
assertTrue(res.get(0).equals("aCommand"));
|
||||
assertTrue(res.get(1).equals("with"));
|
||||
assertTrue(res.get(2).equals("some"));
|
||||
assertTrue(res.get(3).equals("arguments"));
|
||||
try {
|
||||
res = GCLCConstants
|
||||
.splitCommand("aCommand \"with some\" arguments");
|
||||
} catch (CommandParsingException e) {
|
||||
fail("Unable to parse command with string argument"); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
assertTrue(res.size() == 3);
|
||||
assertTrue(res.get(0).equals("aCommand"));
|
||||
assertTrue(res.get(1).equals("with some"));
|
||||
assertTrue(res.get(2).equals("arguments"));
|
||||
try {
|
||||
res = GCLCConstants.splitCommand("aCommand with\\ some arguments");
|
||||
} catch (CommandParsingException e) {
|
||||
fail("Unable to parse command with arguments with escaped whitspaces"); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
assertTrue(res.size() == 3);
|
||||
assertTrue(res.get(0).equals("aCommand"));
|
||||
assertTrue(res.get(1).equals("with some"));
|
||||
assertTrue(res.get(2).equals("arguments"));
|
||||
try {
|
||||
res = GCLCConstants
|
||||
.splitCommand("aCommand wi\\\"th some arguments");
|
||||
} catch (CommandParsingException e) {
|
||||
fail("Unable to parse command with string argument"); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
assertTrue(res.size() == 4);
|
||||
assertTrue(res.get(0).equals("aCommand"));
|
||||
assertTrue(res.get(1).equals("wi\"th"));
|
||||
assertTrue(res.get(2).equals("some"));
|
||||
assertTrue(res.get(3).equals("arguments"));
|
||||
|
||||
// Wrong lines?
|
||||
try {
|
||||
res = GCLCConstants
|
||||
.splitCommand("aCommand with \"some ar\"guments");
|
||||
fail("Parsing argument with string cut");
|
||||
} catch (CommandParsingException e) {
|
||||
// OK
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user