Fork process
Signed-off-by: Emmanuel Bigeon <emmanuel@bigeon.fr>
This commit is contained in:
parent
eae7e0d69f
commit
00c0e86d72
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
|
* mailto:emmanuel@bigeon.fr
|
||||||
|
*
|
||||||
|
* 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-process:fr.bigeon.gclc.process.CommandFork.java
|
||||||
|
* Created on: Nov 13, 2017
|
||||||
|
*/
|
||||||
|
package fr.bigeon.gclc.process;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.command.CommandParameters;
|
||||||
|
import fr.bigeon.gclc.command.ParametrizedCommand;
|
||||||
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
|
import fr.bigeon.gclc.exception.CommandRunExceptionType;
|
||||||
|
import fr.bigeon.gclc.exception.InvalidParameterException;
|
||||||
|
import fr.bigeon.gclc.manager.ConsoleInput;
|
||||||
|
import fr.bigeon.gclc.manager.ConsoleOutput;
|
||||||
|
|
||||||
|
/** A command that is launched inside an internal terminal.
|
||||||
|
* <p>
|
||||||
|
* Several things are to be considered before adding this command to an
|
||||||
|
* application:
|
||||||
|
* <ul>
|
||||||
|
* <li>The commands will be able to run in parallel.
|
||||||
|
* <li>The managing of the commands will be handled through piped systems and
|
||||||
|
* buffered in so switching to a forked command will actually print again all
|
||||||
|
* the command history to the output console.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon */
|
||||||
|
public class CommandForeground extends ParametrizedCommand {
|
||||||
|
|
||||||
|
private final TaskPool pool;
|
||||||
|
|
||||||
|
/** Add the fork command.
|
||||||
|
*
|
||||||
|
* @param name the command name
|
||||||
|
* @param pool The pool to get joinable tasks from */
|
||||||
|
public CommandForeground(final String name, TaskPool pool) {
|
||||||
|
super(name, false);
|
||||||
|
this.pool = pool;
|
||||||
|
addParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void addParameters() {
|
||||||
|
try {
|
||||||
|
addStringParameter("pid", false);
|
||||||
|
addStringParameter("delai", false);
|
||||||
|
} catch (final InvalidParameterException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.ParametrizedCommand#doExecute(fr.bigeon.gclc.
|
||||||
|
* manager.ConsoleOutput, fr.bigeon.gclc.manager.ConsoleInput,
|
||||||
|
* fr.bigeon.gclc.command.CommandParameters) */
|
||||||
|
@Override
|
||||||
|
protected void doExecute(final ConsoleOutput out, final ConsoleInput in,
|
||||||
|
final CommandParameters parameters) throws CommandRunException {
|
||||||
|
String string = parameters.get("pid");
|
||||||
|
final List<String> additionals = parameters.getAdditionals();
|
||||||
|
if (string == null && !additionals.isEmpty()) {
|
||||||
|
string = additionals.get(0);
|
||||||
|
}
|
||||||
|
if (string == null) {
|
||||||
|
throw new CommandRunException(CommandRunExceptionType.USAGE,
|
||||||
|
"Missing process id", this);
|
||||||
|
}
|
||||||
|
// Join the command.
|
||||||
|
final Task cmd = pool.get(string);
|
||||||
|
if (!(cmd instanceof ForkTask)) {
|
||||||
|
throw new CommandRunException("No such forked process", this);
|
||||||
|
}
|
||||||
|
long delai = 0;
|
||||||
|
final String delaiOpt = parameters.get("delai");
|
||||||
|
if (delaiOpt != null) {
|
||||||
|
delai = Long.parseLong(delaiOpt) * 1000;
|
||||||
|
}
|
||||||
|
if (delai < 0) {
|
||||||
|
throw new CommandRunException("Join delai cannot be negative", this);
|
||||||
|
}
|
||||||
|
((ForkTask) cmd).join(out, in, delai);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.ICommand#tip() */
|
||||||
|
@Override
|
||||||
|
public String tip() {
|
||||||
|
return "Join the execution of a command, for a given amount of time";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.Command#usageDetail() */
|
||||||
|
@Override
|
||||||
|
protected String usageDetail() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.Command#usagePattern() */
|
||||||
|
@Override
|
||||||
|
protected String usagePattern() {
|
||||||
|
return super.usagePattern() + " [(-pid) <id>] ([-delai <delai>])";
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
* Copyright (C) 2014-2017 E. Bigeon
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
* mailto:emmanuel@bigeon.fr
|
* mailto:emmanuel@bigeon.fr
|
||||||
*
|
*
|
||||||
* This software is governed by the CeCILL license under French law and
|
* This software is governed by the CeCILL license under French law and
|
||||||
@ -35,17 +35,12 @@
|
|||||||
*/
|
*/
|
||||||
package fr.bigeon.gclc.process;
|
package fr.bigeon.gclc.process;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import fr.bigeon.gclc.command.CommandParameters;
|
import fr.bigeon.gclc.command.Command;
|
||||||
import fr.bigeon.gclc.command.ICommand;
|
import fr.bigeon.gclc.command.ICommand;
|
||||||
import fr.bigeon.gclc.command.ICommandProvider;
|
import fr.bigeon.gclc.command.ICommandProvider;
|
||||||
import fr.bigeon.gclc.command.ParametrizedCommand;
|
|
||||||
import fr.bigeon.gclc.exception.CommandRunException;
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
import fr.bigeon.gclc.exception.CommandRunExceptionType;
|
|
||||||
import fr.bigeon.gclc.exception.InvalidParameterException;
|
|
||||||
import fr.bigeon.gclc.manager.ConsoleInput;
|
import fr.bigeon.gclc.manager.ConsoleInput;
|
||||||
import fr.bigeon.gclc.manager.ConsoleOutput;
|
import fr.bigeon.gclc.manager.ConsoleOutput;
|
||||||
|
|
||||||
@ -56,72 +51,46 @@ import fr.bigeon.gclc.manager.ConsoleOutput;
|
|||||||
* <ul>
|
* <ul>
|
||||||
* <li>The commands will be able to run in parallel.
|
* <li>The commands will be able to run in parallel.
|
||||||
* <li>The managing of the commands will be handled through piped systems and
|
* <li>The managing of the commands will be handled through piped systems and
|
||||||
* buffered in so switching to a forled command will actually print again all
|
* buffered in so switching to a forked command will actually print again all
|
||||||
* the command history to the output console.
|
* the command history to the output console.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author Emmanuel Bigeon */
|
* @author Emmanuel Bigeon */
|
||||||
public class CommandFork extends ParametrizedCommand {
|
public class CommandFork extends Command {
|
||||||
|
|
||||||
private final TaskPool pool = new TaskPool();
|
private final TaskPool pool;
|
||||||
private ICommandProvider provider;
|
private final ICommandProvider provider;
|
||||||
|
private final int lines;
|
||||||
|
|
||||||
/** Add the fork command.
|
/** Add the fork command.
|
||||||
*
|
*
|
||||||
* @param name the command name */
|
* @param name the command name
|
||||||
public CommandFork(final String name) {
|
* @param provider the allowed command collection */
|
||||||
super(name);
|
public CommandFork(final String name, ICommandProvider provider, TaskPool pool) {
|
||||||
addParameters();
|
this(name, provider, pool, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Add the fork command.
|
||||||
*
|
*
|
||||||
*/
|
* @param name the command name
|
||||||
private void addParameters() {
|
* @param provider the allowed command collection */
|
||||||
try {
|
public CommandFork(final String name, ICommandProvider provider, TaskPool pool,
|
||||||
addStringParameter("join", false);
|
int lines) {
|
||||||
addBooleanParameter("list");
|
super(name);
|
||||||
} catch (final InvalidParameterException e) {
|
this.provider = provider;
|
||||||
// TODO Auto-generated catch block
|
this.pool = pool;
|
||||||
e.printStackTrace();
|
this.lines = lines;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see fr.bigeon.gclc.command.ParametrizedCommand#doExecute(fr.bigeon.gclc.
|
|
||||||
* manager.ConsoleOutput, fr.bigeon.gclc.manager.ConsoleInput,
|
|
||||||
* fr.bigeon.gclc.command.CommandParameters) */
|
|
||||||
@Override
|
@Override
|
||||||
protected void doExecute(final ConsoleOutput out, final ConsoleInput in,
|
public void execute(final ConsoleOutput out, final ConsoleInput in, String... args)
|
||||||
final CommandParameters parameters) throws CommandRunException {
|
throws CommandRunException {
|
||||||
if (parameters.getBool("list")) {
|
if (args.length < 1) {
|
||||||
for (final String id : pool.getPIDs()) {
|
throw new CommandRunException("No command to fork", this);
|
||||||
try {
|
|
||||||
out.println(id + "\t" + pool.get(id).getName());
|
|
||||||
} catch (final IOException e) {
|
|
||||||
throw new CommandRunException(
|
|
||||||
CommandRunExceptionType.INTERACTION,
|
|
||||||
"Failed to write to console", e, this);
|
|
||||||
}
|
}
|
||||||
}
|
final ICommand cmd = provider.get(args[0]);
|
||||||
}
|
final String[] inner = Arrays.copyOfRange(args, 1, args.length);
|
||||||
|
final ForkTask task = new ForkCommandTask(cmd, inner, lines);
|
||||||
final String string = parameters.get("join");
|
|
||||||
if (string != null) {
|
|
||||||
// Join the command.
|
|
||||||
final ForkTask cmd = (ForkTask) pool.get(string);
|
|
||||||
if (cmd == null) {
|
|
||||||
throw new CommandRunException("No such fork process", this);
|
|
||||||
}
|
|
||||||
cmd.join(out, in);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<String> strings = parameters.getAdditionals();
|
|
||||||
final ICommand cmd = provider.get(strings.get(0));
|
|
||||||
final String[] args = Arrays.copyOfRange(strings.toArray(new String[0]),
|
|
||||||
1, strings.size());
|
|
||||||
final ForkTask task = new ForkTask(cmd, args);
|
|
||||||
final Thread th = new Thread(task);
|
final Thread th = new Thread(task);
|
||||||
pool.add(task);
|
pool.add(task);
|
||||||
th.start();
|
th.start();
|
||||||
@ -131,18 +100,20 @@ public class CommandFork extends ParametrizedCommand {
|
|||||||
* @see fr.bigeon.gclc.command.ICommand#tip() */
|
* @see fr.bigeon.gclc.command.ICommand#tip() */
|
||||||
@Override
|
@Override
|
||||||
public String tip() {
|
public String tip() {
|
||||||
// TODO Auto-generated method stub
|
return "Command background launch";
|
||||||
// return null;
|
|
||||||
throw new RuntimeException("Not implemented yet");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see fr.bigeon.gclc.command.Command#usageDetail() */
|
* @see fr.bigeon.gclc.command.Command#usageDetail() */
|
||||||
@Override
|
@Override
|
||||||
protected String usageDetail() {
|
protected String usageDetail() {
|
||||||
// TODO Auto-generated method stub
|
return "";
|
||||||
// return null;
|
|
||||||
throw new RuntimeException("Not implemented yet");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.Command#usagePattern() */
|
||||||
|
@Override
|
||||||
|
protected String usagePattern() {
|
||||||
|
return super.usagePattern() + " <command>";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
|
* mailto:emmanuel@bigeon.fr
|
||||||
|
*
|
||||||
|
* 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.process;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.command.ICommand;
|
||||||
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bigeon
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ForkCommandTask extends ForkTask {
|
||||||
|
private final ICommand command;
|
||||||
|
private final String[] args;
|
||||||
|
|
||||||
|
/** @param cmd the command
|
||||||
|
* @param args the arguements
|
||||||
|
* @param lines the number of print to store in the output */
|
||||||
|
public ForkCommandTask(final ICommand cmd, final String[] args, int lines) {
|
||||||
|
super(lines);
|
||||||
|
command = cmd;
|
||||||
|
this.args = Arrays.copyOf(args, args.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.process.Task#getName() */
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return command.getCommandName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.process.ForkTask#doRun() */
|
||||||
|
@Override
|
||||||
|
protected void doRun() throws CommandRunException {
|
||||||
|
command.execute(out, in, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
* Copyright (C) 2014-2017 E. Bigeon
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
* mailto:emmanuel@bigeon.fr
|
* mailto:emmanuel@bigeon.fr
|
||||||
*
|
*
|
||||||
* This software is governed by the CeCILL license under French law and
|
* This software is governed by the CeCILL license under French law and
|
||||||
@ -35,63 +35,70 @@
|
|||||||
*/
|
*/
|
||||||
package fr.bigeon.gclc.process;
|
package fr.bigeon.gclc.process;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import fr.bigeon.gclc.command.ICommand;
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
import fr.bigeon.gclc.manager.ConsoleInput;
|
import fr.bigeon.gclc.manager.ConsoleInput;
|
||||||
import fr.bigeon.gclc.manager.ConsoleOutput;
|
import fr.bigeon.gclc.manager.ConsoleOutput;
|
||||||
|
import fr.bigeon.gclc.process.io.ConnectingConsoleInput;
|
||||||
|
import fr.bigeon.gclc.process.io.ConnectingConsoleOutput;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* TODO
|
* TODO
|
||||||
*
|
*
|
||||||
* @author Emmanuel Bigeon
|
* @author Emmanuel Bigeon */
|
||||||
*
|
public abstract class ForkTask implements Task {
|
||||||
*/
|
|
||||||
public class ForkTask implements Task {
|
|
||||||
|
|
||||||
private final ICommand command;
|
|
||||||
private final String[] args;
|
|
||||||
private final Set<InterruptionListener> listeners = new HashSet<>();
|
private final Set<InterruptionListener> listeners = new HashSet<>();
|
||||||
private boolean running = false;
|
private boolean running = false;
|
||||||
|
|
||||||
/** @param cmd the command
|
protected final ConnectingConsoleInput in = new ConnectingConsoleInput();
|
||||||
* @param args the arguements */
|
protected final ConnectingConsoleOutput out;
|
||||||
public ForkTask(final ICommand cmd, final String[] args) {
|
private CommandRunException exception;
|
||||||
command = cmd;
|
private final Object runLock = new Object();
|
||||||
this.args = Arrays.copyOf(args, args.length);
|
|
||||||
|
/** @param lines the number of print to store in the output */
|
||||||
|
public ForkTask(int lines) {
|
||||||
|
out = new ConnectingConsoleOutput(ConnectingConsoleOutput.PERSIST, lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see fr.bigeon.gclc.process.Task#addInterruptionListener(fr.bigeon.gclc.
|
* @see fr.bigeon.gclc.process.Task#addInterruptionListener(fr.bigeon.gclc.
|
||||||
* process.InterruptionListener) */
|
* process.InterruptionListener) */
|
||||||
@Override
|
@Override
|
||||||
public void addInterruptionListener(final InterruptionListener listener) {
|
public final void addInterruptionListener(final InterruptionListener listener) {
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see fr.bigeon.gclc.process.Task#getName() */
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return command.getCommandName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see fr.bigeon.gclc.process.Task#isRunning() */
|
* @see fr.bigeon.gclc.process.Task#isRunning() */
|
||||||
@Override
|
@Override
|
||||||
public boolean isRunning() {
|
public final boolean isRunning() {
|
||||||
|
synchronized (runLock) {
|
||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @param out the console output
|
/** @param out the console output
|
||||||
* @param in the console input */
|
* @param in the console input
|
||||||
public void join(final ConsoleOutput out, final ConsoleInput in) {
|
* @param timeout the maximal wait (0 for ever) */
|
||||||
// TODO Auto-generated method stub
|
public final void join(final ConsoleOutput out, final ConsoleInput in, long timeout) {
|
||||||
//
|
synchronized (runLock) {
|
||||||
throw new RuntimeException("Not implemented yet");
|
this.out.connect(out);
|
||||||
|
this.in.connect(in);
|
||||||
|
try {
|
||||||
|
if (running) {
|
||||||
|
runLock.wait(timeout);
|
||||||
|
}
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
// TODO log.
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
this.out.disconnect();
|
||||||
|
this.in.disconnect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
@ -99,29 +106,50 @@ public class ForkTask implements Task {
|
|||||||
* fr.bigeon.gclc.process.Task#rmInterruptionListener(fr.bigeon.gclc.process
|
* fr.bigeon.gclc.process.Task#rmInterruptionListener(fr.bigeon.gclc.process
|
||||||
* .InterruptionListener) */
|
* .InterruptionListener) */
|
||||||
@Override
|
@Override
|
||||||
public void rmInterruptionListener(final InterruptionListener listener) {
|
public final void rmInterruptionListener(final InterruptionListener listener) {
|
||||||
listeners.remove(listener);
|
listeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see java.lang.Runnable#run() */
|
* @see java.lang.Runnable#run() */
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public final void run() {
|
||||||
|
synchronized (runLock) {
|
||||||
running = true;
|
running = true;
|
||||||
try {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
//
|
|
||||||
throw new RuntimeException("Not implemented yet");
|
|
||||||
} finally {
|
|
||||||
running = false;
|
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
doRun();
|
||||||
|
} catch (final CommandRunException e) {
|
||||||
|
exception = e;
|
||||||
|
} finally {
|
||||||
|
setRunning(false);
|
||||||
|
}
|
||||||
|
for (final InterruptionListener interruptionListener : listeners) {
|
||||||
|
interruptionListener.interrupted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actually run the fork. */
|
||||||
|
protected abstract void doRun() throws CommandRunException;
|
||||||
|
|
||||||
|
/** Get the excepion that caused a failure.
|
||||||
|
*
|
||||||
|
* @return the exception */
|
||||||
|
public final CommandRunException getException() {
|
||||||
|
return exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see fr.bigeon.gclc.process.Task#setRunning(boolean) */
|
* @see fr.bigeon.gclc.process.Task#setRunning(boolean) */
|
||||||
@Override
|
@Override
|
||||||
public void setRunning(final boolean running) {
|
public final void setRunning(final boolean running) {
|
||||||
|
synchronized (runLock) {
|
||||||
this.running = running;
|
this.running = running;
|
||||||
|
runLock.notifyAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected final Object getRunningLock() {
|
||||||
|
return runLock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
* Copyright (C) 2014-2017 E. Bigeon
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
* mailto:emmanuel@bigeon.fr
|
* mailto:emmanuel@bigeon.fr
|
||||||
*
|
*
|
||||||
* This software is governed by the CeCILL license under French law and
|
* This software is governed by the CeCILL license under French law and
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
|
* mailto:emmanuel@bigeon.fr
|
||||||
|
*
|
||||||
|
* 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.process;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.ApplicationAttachement;
|
||||||
|
import fr.bigeon.gclc.command.ICommandProvider;
|
||||||
|
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bigeon
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ProcessAttachement implements ApplicationAttachement {
|
||||||
|
|
||||||
|
private final TaskPool pool;
|
||||||
|
|
||||||
|
/** @param pool the task pool to manage */
|
||||||
|
public ProcessAttachement(TaskPool pool) {
|
||||||
|
super();
|
||||||
|
this.pool = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.ApplicationAttachement#attach(fr.bigeon.gclc.ConsoleApplication)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void attach(ICommandProvider application) throws InvalidCommandName {
|
||||||
|
application.add(new ProcessKill("kill", pool));
|
||||||
|
application.add(new ProcessList("list", pool));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
|
* mailto:emmanuel@bigeon.fr
|
||||||
|
*
|
||||||
|
* 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.proc.ProcessList.java
|
||||||
|
* Created on: May 10, 2017
|
||||||
|
*/
|
||||||
|
package fr.bigeon.gclc.process;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.command.Command;
|
||||||
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
|
import fr.bigeon.gclc.manager.ConsoleInput;
|
||||||
|
import fr.bigeon.gclc.manager.ConsoleOutput;
|
||||||
|
|
||||||
|
/** A command that will flag a task to stop
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon */
|
||||||
|
public final class ProcessClear extends Command {
|
||||||
|
/** The taskpool */
|
||||||
|
private final TaskPool pool;
|
||||||
|
|
||||||
|
/** @param name the command name
|
||||||
|
* @param pool the pool */
|
||||||
|
public ProcessClear(final String name, final TaskPool pool) {
|
||||||
|
super(name);
|
||||||
|
this.pool = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.ICommand#execute(fr.bigeon.gclc.manager.
|
||||||
|
* ConsoleOutput, fr.bigeon.gclc.manager.ConsoleInput,
|
||||||
|
* java.lang.String[]) */
|
||||||
|
@Override
|
||||||
|
public void execute(final ConsoleOutput out, final ConsoleInput in,
|
||||||
|
final String... args) throws CommandRunException {
|
||||||
|
for (final String id : pool.getPIDs()) {
|
||||||
|
if (!pool.get(id).isRunning()) {
|
||||||
|
pool.remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.ICommand#tip() */
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
@Override
|
||||||
|
public String tip() {
|
||||||
|
return "Request a process to stop (softly)";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.Command#usageDetail() */
|
||||||
|
@Override
|
||||||
|
protected String usageDetail() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
* Copyright (C) 2014-2017 E. Bigeon
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
* mailto:emmanuel@bigeon.fr
|
* mailto:emmanuel@bigeon.fr
|
||||||
*
|
*
|
||||||
* This software is governed by the CeCILL license under French law and
|
* This software is governed by the CeCILL license under French law and
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
* Copyright (C) 2014-2017 E. Bigeon
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
* mailto:emmanuel@bigeon.fr
|
* mailto:emmanuel@bigeon.fr
|
||||||
*
|
*
|
||||||
* This software is governed by the CeCILL license under French law and
|
* This software is governed by the CeCILL license under French law and
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
|
* mailto:emmanuel@bigeon.fr
|
||||||
|
*
|
||||||
|
* 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.process;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.ApplicationAttachement;
|
||||||
|
import fr.bigeon.gclc.command.ICommandProvider;
|
||||||
|
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||||
|
|
||||||
|
/** @author Emmanuel Bigeon */
|
||||||
|
public class ScreenAttachement implements ApplicationAttachement {
|
||||||
|
|
||||||
|
private final TaskPool pool;
|
||||||
|
private final int lines;
|
||||||
|
|
||||||
|
/** @param pool the task pool to manage */
|
||||||
|
public ScreenAttachement(TaskPool pool, int lines) {
|
||||||
|
super();
|
||||||
|
this.pool = pool;
|
||||||
|
this.lines = lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.ApplicationAttachement#attach(fr.bigeon.gclc.
|
||||||
|
* ConsoleApplication) */
|
||||||
|
@Override
|
||||||
|
public void attach(ICommandProvider application) throws InvalidCommandName {
|
||||||
|
application.add(new ProcessKill("terminate", pool));
|
||||||
|
application.add(new ProcessList("list", pool));
|
||||||
|
application.add(new ProcessClear("clear", pool));
|
||||||
|
application.add(new CommandForeground("fg", pool));
|
||||||
|
application.add(new CommandFork("fork", application, pool, lines));
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
* Copyright (C) 2014-2017 E. Bigeon
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
* mailto:emmanuel@bigeon.fr
|
* mailto:emmanuel@bigeon.fr
|
||||||
*
|
*
|
||||||
* This software is governed by the CeCILL license under French law and
|
* This software is governed by the CeCILL license under French law and
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
* Copyright (C) 2014-2017 E. Bigeon
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
* mailto:emmanuel@bigeon.fr
|
* mailto:emmanuel@bigeon.fr
|
||||||
*
|
*
|
||||||
* This software is governed by the CeCILL license under French law and
|
* This software is governed by the CeCILL license under French law and
|
||||||
@ -50,10 +50,26 @@ public final class TaskPool {
|
|||||||
private int count = 0;
|
private int count = 0;
|
||||||
/** The lock for pid attribution synchronization. */
|
/** The lock for pid attribution synchronization. */
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
|
private final boolean autoClear;
|
||||||
|
|
||||||
/** Default constructor. */
|
/** Default constructor. */
|
||||||
public TaskPool() {
|
public TaskPool() {
|
||||||
//
|
this(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Default constructor. */
|
||||||
|
public TaskPool(boolean autoClear) {
|
||||||
|
this.autoClear = autoClear;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove a task from the pool
|
||||||
|
*
|
||||||
|
* @param pid the task id */
|
||||||
|
public void remove(String pid) {
|
||||||
|
synchronized (lock) {
|
||||||
|
running.remove(pid);
|
||||||
|
count = Math.min(count, Integer.parseInt(pid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Add a process in the pool.
|
/** Add a process in the pool.
|
||||||
@ -64,22 +80,23 @@ public final class TaskPool {
|
|||||||
if (cmd == null) {
|
if (cmd == null) {
|
||||||
throw new IllegalArgumentException("Task cannot be null"); //$NON-NLS-1$
|
throw new IllegalArgumentException("Task cannot be null"); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
final String pid = getPID();
|
final String pid;
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
|
pid = getPID();
|
||||||
running.put(pid, cmd);
|
running.put(pid, cmd);
|
||||||
}
|
}
|
||||||
|
if (autoClear) {
|
||||||
cmd.addInterruptionListener(new InterruptionListener() {
|
cmd.addInterruptionListener(new InterruptionListener() {
|
||||||
|
|
||||||
@SuppressWarnings("synthetic-access")
|
@SuppressWarnings("synthetic-access")
|
||||||
@Override
|
@Override
|
||||||
public void interrupted() {
|
public void interrupted() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
running.remove(pid);
|
remove(pid);
|
||||||
count = Math.min(count, Integer.parseInt(pid));
|
|
||||||
}
|
}
|
||||||
cmd.rmInterruptionListener(this);
|
cmd.rmInterruptionListener(this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,4 +129,21 @@ public final class TaskPool {
|
|||||||
public Collection<String> getPIDs() {
|
public Collection<String> getPIDs() {
|
||||||
return new HashSet<>(running.keySet());
|
return new HashSet<>(running.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return if the clearing of ended task is automatic */
|
||||||
|
public boolean isAutoClearing() {
|
||||||
|
return autoClear;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Request all task to stop running.
|
||||||
|
* <p>
|
||||||
|
* This call does not guaranty end of execution, it is up to the task
|
||||||
|
* implementation to actually take into account the termination request. */
|
||||||
|
public void shutdown() {
|
||||||
|
synchronized (lock) {
|
||||||
|
for (final Task task : running.values()) {
|
||||||
|
task.setRunning(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
* Copyright (C) 2014-2017 E. Bigeon
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
* mailto:emmanuel@bigeon.fr
|
* mailto:emmanuel@bigeon.fr
|
||||||
*
|
*
|
||||||
* This software is governed by the CeCILL license under French law and
|
* This software is governed by the CeCILL license under French law and
|
||||||
@ -35,6 +35,8 @@
|
|||||||
*/
|
*/
|
||||||
package fr.bigeon.gclc.process;
|
package fr.bigeon.gclc.process;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
import fr.bigeon.gclc.command.Command;
|
import fr.bigeon.gclc.command.Command;
|
||||||
import fr.bigeon.gclc.exception.CommandRunException;
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
import fr.bigeon.gclc.manager.ConsoleInput;
|
import fr.bigeon.gclc.manager.ConsoleInput;
|
||||||
@ -46,31 +48,35 @@ import fr.bigeon.gclc.manager.ConsoleOutput;
|
|||||||
public abstract class TaskSpawner extends Command {
|
public abstract class TaskSpawner extends Command {
|
||||||
/** The process pool */
|
/** The process pool */
|
||||||
private final TaskPool pool;
|
private final TaskPool pool;
|
||||||
|
private final ExecutorService threadPool;
|
||||||
|
|
||||||
/** @param name the command name
|
/** @param name the command name
|
||||||
* @param pool the pool */
|
* @param pool the pool */
|
||||||
public TaskSpawner(final String name, final TaskPool pool) {
|
public TaskSpawner(final String name, final TaskPool pool,
|
||||||
|
ExecutorService threadPool) {
|
||||||
super(name);
|
super(name);
|
||||||
this.pool = pool;
|
this.pool = pool;
|
||||||
|
this.threadPool = threadPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param in the input
|
/** @param in the input
|
||||||
* @param out the output
|
* @param out the output
|
||||||
* @param args the arguments
|
* @param args the arguments
|
||||||
* @return the process to start and add to the pool */
|
* @return the process to start and add to the pool
|
||||||
|
* @throws CommandRunException if the task creation failed */
|
||||||
protected abstract Task createTask(ConsoleOutput out, ConsoleInput in,
|
protected abstract Task createTask(ConsoleOutput out, ConsoleInput in,
|
||||||
String... args);
|
String... args) throws CommandRunException;
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see fr.bigeon.gclc.command.ICommand#execute(fr.bigeon.gclc.manager.
|
* @see fr.bigeon.gclc.command.ICommand#execute(fr.bigeon.gclc.manager.
|
||||||
* ConsoleOutput, fr.bigeon.gclc.manager.ConsoleInput,
|
* ConsoleOutput, fr.bigeon.gclc.manager.ConsoleInput,
|
||||||
* java.lang.String[]) */
|
* java.lang.String[]) */
|
||||||
@Override
|
@Override
|
||||||
public void execute(final ConsoleOutput out, final ConsoleInput in,
|
public final void execute(final ConsoleOutput out, final ConsoleInput in,
|
||||||
final String... args) throws CommandRunException {
|
final String... args) throws CommandRunException {
|
||||||
final Task task = createTask(out, in, args);
|
final Task task = createTask(out, in, args);
|
||||||
final Thread th = new Thread(task);
|
final Thread th = new Thread(task);
|
||||||
pool.add(task);
|
pool.add(task);
|
||||||
th.start();
|
threadPool.execute(th);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
|
* mailto:emmanuel@bigeon.fr
|
||||||
|
*
|
||||||
|
* 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.process.io;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.manager.ConsoleInput;
|
||||||
|
import fr.bigeon.gclc.tools.StringProvider;
|
||||||
|
|
||||||
|
/** @author Emmanuel Bigeon */
|
||||||
|
public final class ConnectingConsoleInput implements ConsoleInput {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger
|
||||||
|
.getLogger(ConnectingConsoleInput.class.getName());
|
||||||
|
private boolean close = false;
|
||||||
|
private StringProvider prompt;
|
||||||
|
private boolean prompting;
|
||||||
|
private final Object promptLock = new Object();
|
||||||
|
private final Object connectionLock = new Object();
|
||||||
|
private ConsoleInput connected;
|
||||||
|
private boolean disconnection;
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleInput#close() */
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
close = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleInput#getPrompt() */
|
||||||
|
@Override
|
||||||
|
public StringProvider getPrompt() {
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleInput#interruptPrompt() */
|
||||||
|
@Override
|
||||||
|
public void interruptPrompt() {
|
||||||
|
synchronized (promptLock) {
|
||||||
|
prompting = false;
|
||||||
|
if (connected != null) {
|
||||||
|
connected.interruptPrompt();
|
||||||
|
}
|
||||||
|
promptLock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleInput#isClosed() */
|
||||||
|
@Override
|
||||||
|
public boolean isClosed() {
|
||||||
|
return close;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleInput#prompt() */
|
||||||
|
@Override
|
||||||
|
public String prompt() throws IOException {
|
||||||
|
return prompt(prompt.apply());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleInput#setPrompt(fr.bigeon.gclc.tools.
|
||||||
|
* StringProvider) */
|
||||||
|
@Override
|
||||||
|
public void setPrompt(StringProvider string) {
|
||||||
|
prompt = string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleInput#prompt(long) */
|
||||||
|
@Override
|
||||||
|
public String prompt(long timeout) throws IOException {
|
||||||
|
return prompt(prompt.apply(), timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleInput#prompt(java.lang.String) */
|
||||||
|
@Override
|
||||||
|
public String prompt(String message) throws IOException {
|
||||||
|
synchronized (promptLock) {
|
||||||
|
prompting = true;
|
||||||
|
}
|
||||||
|
while (prompting) {
|
||||||
|
synchronized (promptLock) {
|
||||||
|
if (connected == null) {
|
||||||
|
try {
|
||||||
|
promptLock.wait();
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
LOGGER.log(Level.WARNING, "Inerruption of console thread", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final String res = connected.prompt(message);
|
||||||
|
synchronized (connectionLock) {
|
||||||
|
if (disconnection) {
|
||||||
|
disconnection = false;
|
||||||
|
} else if (prompting) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleInput#prompt(java.lang.String, long) */
|
||||||
|
@Override
|
||||||
|
public String prompt(String message, long timeout) throws IOException {
|
||||||
|
if (timeout <= 0) {
|
||||||
|
return prompt(message);
|
||||||
|
}
|
||||||
|
final long end = System.currentTimeMillis() + timeout;
|
||||||
|
synchronized (promptLock) {
|
||||||
|
prompting = true;
|
||||||
|
}
|
||||||
|
while (prompting) {
|
||||||
|
synchronized (promptLock) {
|
||||||
|
if (connected == null) {
|
||||||
|
try {
|
||||||
|
promptLock.wait();
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
LOGGER.log(Level.WARNING, "Inerruption of console thread", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final String res = connected.prompt(message,
|
||||||
|
end - System.currentTimeMillis());
|
||||||
|
synchronized (connectionLock) {
|
||||||
|
if (disconnection) {
|
||||||
|
disconnection = false;
|
||||||
|
} else if (prompting) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleInput#setPrompt(java.lang.String) */
|
||||||
|
@Override
|
||||||
|
public void setPrompt(final String prompt) {
|
||||||
|
this.prompt = new StringProvider() {
|
||||||
|
@Override
|
||||||
|
public String apply() {
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect(ConsoleInput input) {
|
||||||
|
disconnect();
|
||||||
|
synchronized (promptLock) {
|
||||||
|
connected = input;
|
||||||
|
promptLock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect() {
|
||||||
|
synchronized (connectionLock) {
|
||||||
|
if (connected != null) {
|
||||||
|
disconnection = true;
|
||||||
|
synchronized (promptLock) {
|
||||||
|
connected.interruptPrompt();
|
||||||
|
}
|
||||||
|
connected = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* process, Distribution repositories and basic setup for Emmanuel Bigeon projects
|
||||||
|
* Copyright (C) 2014-2018 E. Bigeon
|
||||||
|
* mailto:emmanuel@bigeon.fr
|
||||||
|
*
|
||||||
|
* 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.process.io;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.manager.ConsoleOutput;
|
||||||
|
|
||||||
|
/** @author Emmanuel Bigeon */
|
||||||
|
public class ConnectingConsoleOutput implements ConsoleOutput {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger
|
||||||
|
.getLogger(ConnectingConsoleOutput.class.getName());
|
||||||
|
/** If the undelivered message should be stored. */
|
||||||
|
public static final int QUEUE = 1;
|
||||||
|
/** If the messages should be stored in all cases. */
|
||||||
|
public static final int PERSIST = 1 << 1;
|
||||||
|
private ConsoleOutput output;
|
||||||
|
private boolean close = false;
|
||||||
|
|
||||||
|
private final boolean persistent;
|
||||||
|
private final boolean queued;
|
||||||
|
private final Deque<String> messages;
|
||||||
|
private final int lines;
|
||||||
|
|
||||||
|
/** @param style the type of redirected output
|
||||||
|
* @param lines the number of lines to store */
|
||||||
|
public ConnectingConsoleOutput(int style, int lines) {
|
||||||
|
super();
|
||||||
|
this.lines = lines;
|
||||||
|
queued = (style & QUEUE) != 0;
|
||||||
|
persistent = (style & PERSIST) != 0;
|
||||||
|
if (lines > 0) {
|
||||||
|
messages = new ArrayDeque<>(lines);
|
||||||
|
} else {
|
||||||
|
messages = new ArrayDeque<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void addMessage(String text) {
|
||||||
|
if (persistent || queued && output == null) {
|
||||||
|
if (messages.size() == lines) {
|
||||||
|
messages.poll();
|
||||||
|
}
|
||||||
|
messages.offer(text);
|
||||||
|
}
|
||||||
|
if (output != null) {
|
||||||
|
try {
|
||||||
|
output.print(text);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
LOGGER.severe("nable to print to connecting console");
|
||||||
|
LOGGER.log(Level.FINE, "Console error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.AutoCloseable#close() */
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
close = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleOutput#isClosed() */
|
||||||
|
@Override
|
||||||
|
public boolean isClosed() {
|
||||||
|
return close;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleOutput#print(java.lang.String) */
|
||||||
|
@Override
|
||||||
|
public void print(String text) {
|
||||||
|
addMessage(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleOutput#println() */
|
||||||
|
@Override
|
||||||
|
public void println() {
|
||||||
|
addMessage(System.lineSeparator());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleOutput#println(java.lang.String) */
|
||||||
|
@Override
|
||||||
|
public void println(String message) {
|
||||||
|
addMessage(message + System.lineSeparator());
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void connect(ConsoleOutput output) {
|
||||||
|
this.output = output;
|
||||||
|
for (final String string : messages) {
|
||||||
|
try {
|
||||||
|
output.print(string);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
LOGGER.severe("nable to print to connecting console");
|
||||||
|
LOGGER.log(Level.FINE, "Console error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!persistent) {
|
||||||
|
messages.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void disconnect() {
|
||||||
|
output = null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user