format and commands

Signed-off-by: Emmanuel Bigeon <emmanuel@bigeon.fr>
This commit is contained in:
Emmanuel Bigeon 2018-10-16 18:53:39 -04:00
parent 1df33afdbe
commit 216cd41dc8
7 changed files with 124 additions and 59 deletions

View File

@ -94,12 +94,14 @@ import net.bigeon.gclc.manager.ConsoleOutput;
* @author Emmanuel Bigeon */
public class CommandForeground extends ParametrizedCommand {
/** Number of milliseconds in a second. */
private static final int MILLIS_IN_A_SEC = 1000;
/** The class logger. */
private static final Logger LOGGER = Logger
private static final Logger LOGGER = Logger
.getLogger(CommandForeground.class.getName());
/** The task pool to fetch task from. */
private final TaskPool pool;
private final TaskPool pool;
/** Add the fork command.
*

View File

@ -91,15 +91,19 @@ import net.bigeon.gclc.manager.ConsoleOutput;
* @author Emmanuel Bigeon */
public class CommandFork extends Command {
/** The task pool containing the tasks. */
private final TaskPool pool;
/** The command provider. */
private final ICommandProvider provider;
/** The number of lines stored in the commands. */
private final int lines;
/** Add the fork command.
*
* @param name the command name
* @param provider the allowed command collection */
public CommandFork(final String name, ICommandProvider provider, TaskPool pool) {
public CommandFork(final String name, final ICommandProvider provider,
final TaskPool pool) {
this(name, provider, pool, -1);
}
@ -107,17 +111,20 @@ public class CommandFork extends Command {
*
* @param name the command name
* @param provider the allowed command collection */
public CommandFork(final String name, ICommandProvider provider, TaskPool pool,
int lines) {
public CommandFork(final String name, final ICommandProvider provider,
final TaskPool pool, final int lines) {
super(name);
this.provider = provider;
this.pool = pool;
this.lines = lines;
}
/* (non-Javadoc)
* @see net.bigeon.gclc.command.ICommand#execute(net.bigeon.gclc.manager.
* ConsoleOutput, net.bigeon.gclc.manager.ConsoleInput, java.lang.String[]) */
@Override
public void execute(final ConsoleOutput out, final ConsoleInput in, String... args)
throws CommandRunException {
public void execute(final ConsoleOutput out, final ConsoleInput in,
final String... args) throws CommandRunException {
if (args.length < 1) {
throw new CommandRunException("No command to fork");
}

View File

@ -77,23 +77,28 @@ import net.bigeon.gclc.manager.ConsoleOutput;
import net.bigeon.gclc.process.io.ConnectingConsoleInput;
import net.bigeon.gclc.process.io.ConnectingConsoleOutput;
/**
* <p>
* TODO
/** A task that is made to run into a thread.
*
* @author Emmanuel Bigeon */
public abstract class ForkTask implements Task {
/** THe listeners. */
private final Set<InterruptionListener> listeners = new HashSet<>();
/** The running state. */
private boolean running = false;
protected final ConnectingConsoleInput in = new ConnectingConsoleInput();
/** The connecting input for this task */
protected final ConnectingConsoleInput in = new ConnectingConsoleInput();
/** The connecting output for this task */
protected final ConnectingConsoleOutput out;
/** The exception of the run. */
private CommandRunException exception;
private final Object runLock = new Object();
/** The synchronization lock. */
private final Object runLock = new Object();
/** @param lines the number of print to store in the output */
public ForkTask(int lines) {
/** Create the task.
*
* @param lines the number of print to store in the output */
public ForkTask(final int lines) {
out = new ConnectingConsoleOutput(ConnectingConsoleOutput.PERSIST, lines);
}
@ -128,10 +133,13 @@ public abstract class ForkTask implements Task {
}
}
/** @param out the console output
/** Join the task.
*
* @param out the console output
* @param in the console input
* @param timeout the maximal wait (0 for ever) */
public final void join(final ConsoleOutput out, final ConsoleInput in, long timeout) {
* @param timeout the maximal time to join for (0 for ever) */
public final void join(final ConsoleOutput out, final ConsoleInput in,
final long timeout) {
synchronized (runLock) {
this.out.connect(out);
this.in.connect(in);
@ -140,7 +148,6 @@ public abstract class ForkTask implements Task {
runLock.wait(timeout);
}
} catch (final InterruptedException e) {
// TODO log.
Thread.currentThread().interrupt();
}
this.out.disconnect();

View File

@ -75,19 +75,30 @@ import net.bigeon.gclc.manager.ConsoleInput;
import net.bigeon.gclc.tools.ConstantString;
import net.bigeon.gclc.tools.StringProvider;
/** @author Emmanuel Bigeon */
/** A console input that can be connected to and diconnected from.
*
* @author Emmanuel Bigeon */
public final class ConnectingConsoleInput implements ConsoleInput {
/** The empty string provider. */
private static final ConstantString EMPTY_STRING = new ConstantString("");
/** The logger. */
private static final Logger LOGGER = Logger
.getLogger(ConnectingConsoleInput.class.getName());
/** If the input is closed. */
private boolean close = false;
/** The prompt string. */
private StringProvider prompt = EMPTY_STRING;
/** If the input is currently in prompting state. */
private boolean prompting = false;
/** The synchronization lock for the rompting status. */
private final Object promptLock = new Object();
/** The synchronization lock for the connection status. */
private final Object connectionLock = new Object();
/** The connected console input. */
private ConsoleInput connected = null;
/** The connection state. */
private boolean disconnection = false;
/* (non-Javadoc)
@ -97,6 +108,9 @@ public final class ConnectingConsoleInput implements ConsoleInput {
close = true;
}
/** Connect an input.
*
* @param input the input to connect */
public void connect(final ConsoleInput input) {
disconnect();
synchronized (promptLock) {
@ -105,6 +119,7 @@ public final class ConnectingConsoleInput implements ConsoleInput {
}
}
/** Disconnect the current input. */
public void disconnect() {
synchronized (connectionLock) {
if (connected != null) {

View File

@ -75,26 +75,37 @@ import java.util.logging.Logger;
import net.bigeon.gclc.manager.ConsoleOutput;
/** @author Emmanuel Bigeon */
/** A console output that can be connected and disconnected from.
*
* @author Emmanuel Bigeon */
public class ConnectingConsoleOutput implements ConsoleOutput {
/** The logger. */
private static final Logger LOGGER = Logger
.getLogger(ConnectingConsoleOutput.class.getName());
/** If the undelivered message should be stored. */
/** The flag indicating that the un-delivered message should be stored. */
public static final int QUEUE = 1;
/** If the messages should be stored in all cases. */
/** The flag indicating that the messages should be stored in all cases. */
public static final int PERSIST = 1 << 1;
/** The connected output console */
private ConsoleOutput output;
/** If the console is closed */
private boolean close = false;
/** If the messages should be stored. */
private final boolean persistent;
/** If the message should be stored until delivery. */
private final boolean queued;
/** The messages. */
private final Deque<String> messages;
/** The number of stored messages. */
private final int lines;
/** @param style the type of redirected output
/** Create the console output.
*
* @param style the type of redirected output
* @param lines the number of lines to store */
public ConnectingConsoleOutput(int style, int lines) {
public ConnectingConsoleOutput(final int style, final int lines) {
super();
this.lines = lines;
queued = (style & QUEUE) != 0;
@ -106,7 +117,10 @@ public class ConnectingConsoleOutput implements ConsoleOutput {
}
}
private synchronized void addMessage(String text) {
/** Add a message.
*
* @param text the message */
private synchronized void addMessage(final String text) {
if (persistent || queued && output == null) {
if (messages.size() == lines) {
messages.poll();
@ -130,7 +144,10 @@ public class ConnectingConsoleOutput implements ConsoleOutput {
close = true;
}
public synchronized void connect(ConsoleOutput output) {
/** Connect an output.
*
* @param output the output */
public synchronized void connect(final ConsoleOutput output) {
this.output = output;
for (final String string : messages) {
try {
@ -145,6 +162,7 @@ public class ConnectingConsoleOutput implements ConsoleOutput {
}
}
/** Disconnect the currently connected output. */
public synchronized void disconnect() {
output = null;
}
@ -159,7 +177,7 @@ public class ConnectingConsoleOutput implements ConsoleOutput {
/* (non-Javadoc)
* @see fr.bigeon.gclc.manager.ConsoleOutput#print(java.lang.String) */
@Override
public void print(String text) {
public void print(final String text) {
addMessage(text);
}
@ -173,7 +191,7 @@ public class ConnectingConsoleOutput implements ConsoleOutput {
/* (non-Javadoc)
* @see fr.bigeon.gclc.manager.ConsoleOutput#println(java.lang.String) */
@Override
public void println(String message) {
public void println(final String message) {
addMessage(message + System.lineSeparator());
}
}

View File

@ -54,9 +54,12 @@ import net.bigeon.gclc.utils.ReadingRunnable;
/** A console input where the stream can be plugged.
* <p>
* This pluggable console input accepts an input and output to be connected to
* it. The connexion cannot be concurrent, which mean that any connected stream
* it. The connection cannot be concurrent, which mean that any connected stream
* must be disconnected before a new call to
* {@link #connect(InputStream, PrintStream)} is done.
* <p>
* On connection, if the prompt is in wait, this console input will provide the
* prompting message.
*
* @author Emmanuel Bigeon */
public final class PluggableConsoleInput implements ConsoleInput {
@ -109,15 +112,15 @@ public final class PluggableConsoleInput implements ConsoleInput {
throws IOException {
synchronized (connexionLock) {
if (connected) {
// Cannot be connected to several sources
throw new IOException("Input already connected to an input stream"); //$NON-NLS-1$
}
output = out;
if (prompting) {
// print the hint, to indicate we are waiting for a user input.
out.print(hint);
out.flush();
}
final InputStreamReader streamReader = new InputStreamReader(stream,
StandardCharsets.UTF_8);
final BufferedReader reader = new BufferedReader(streamReader);
@ -189,19 +192,11 @@ public final class PluggableConsoleInput implements ConsoleInput {
if (closed) {
throw new IOException();
}
prompting = true;
hint = message;
synchronized (connexionLock) {
hint = message;
if (connected) {
output.print(message);
output.flush();
}
}
preparePrompt(message);
String res = null;
while (res == null && !interrupted) {
try {
// Wait for a message or a connection with message
res = waitMessageOrConnexion(TIMEOUT, TIMEOUT / TENTH);
} catch (final InterruptedException e) {
LOGGER.log(Level.FINE, "Interruption of thread", e); //$NON-NLS-1$
@ -215,6 +210,22 @@ public final class PluggableConsoleInput implements ConsoleInput {
return res;
}
/** Prepare the new prompt.
*
* @param message the message to indicate request of prompt. */
private void preparePrompt(final String message) {
prompting = true;
// hold the message
synchronized (connexionLock) {
hint = message;
if (connected) {
// print the message
output.print(message);
output.flush();
}
}
}
/* (non-Javadoc)
* @see fr.bigeon.gclc.manager.ConsoleInput#prompt(java.lang.String, long) */
@Override
@ -222,15 +233,7 @@ public final class PluggableConsoleInput implements ConsoleInput {
if (closed) {
throw new IOException();
}
prompting = true;
synchronized (connexionLock) {
hint = message;
if (connected) {
output.print(message);
output.flush();
}
}
preparePrompt(message);
String res = null;
final long tic = System.currentTimeMillis();
long time = System.currentTimeMillis() - tic;
@ -250,11 +253,16 @@ public final class PluggableConsoleInput implements ConsoleInput {
return res;
}
/* (non-Javadoc)
* @see net.bigeon.gclc.manager.ConsoleInput#setPrompt(java.lang.String) */
@Override
public void setPrompt(String prompt) {
public void setPrompt(final String prompt) {
setPrompt(new ConstantString(prompt));
}
/* (non-Javadoc)
* @see net.bigeon.gclc.manager.ConsoleInput#setPrompt(net.bigeon.gclc.tools.
* StringProvider) */
@Override
public void setPrompt(final StringProvider prompt) {
this.prompt = prompt;

View File

@ -51,7 +51,11 @@ import net.bigeon.gclc.exception.CommandRunExceptionType;
import net.bigeon.gclc.manager.ConsoleInput;
import net.bigeon.gclc.manager.ConsoleOutput;
/** A command that will execute a system command.
/** A command that will execute system commands.
* <p>
* Note that this class may induce security issues in the code as it can execute
* arbitrary system commands. It is recommended that it be used only in private
* applications or application used by aware parties.
*
* @author Emmanuel Bigeon */
public class ExecSystemCommand extends Command {
@ -91,10 +95,11 @@ public class ExecSystemCommand extends Command {
} catch (final IOException e2) {
throw new CommandRunException("Unable to run process", e2);
}
// Stream forwarding to the application's console
final InputStream is = proc.getInputStream();
final Thread th = new Thread(new Runnable() {
/* (non-Javadoc)
* @see java.lang.Runnable#run() */
@Override
public void run() {
try {
@ -109,10 +114,11 @@ public class ExecSystemCommand extends Command {
});
th.start();
in.setPrompt(""); //$NON-NLS-1$
// Forwar console input to the process.
final OutputStream os = proc.getOutputStream();
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os))) {
while (th.isAlive()) {
String user = in.prompt();
final String user = in.prompt();
if (!user.isEmpty()) {
writer.write(user + EOL);
}
@ -123,14 +129,16 @@ public class ExecSystemCommand extends Command {
}
}
/** @param is the input stream
/** Read the input until its end.
*
* @param is the input stream
* @throws CommandRunException if the manager was closed while writing the
* stream */
protected void readToEnd(final ConsoleOutput out, final InputStream is)
throws CommandRunException {
int c;
try {
while ((c = is.read()) != -1) {
while ((c = is.read()) >= 0) {
printCharacter(out, (char) c);
}
} catch (final IOException e) {
@ -143,7 +151,7 @@ public class ExecSystemCommand extends Command {
* @param out the console
* @param c the character
* @throws CommandRunException if the console failed to print the character. */
private void printCharacter(final ConsoleOutput out, char c)
private static void printCharacter(final ConsoleOutput out, final char c)
throws CommandRunException {
try {
out.print(Character.toString(c));