diff --git a/gclc.system/src/main/java/net/bigeon/gclc/system/ExecSystemCommand.java b/gclc.system/src/main/java/net/bigeon/gclc/system/ExecSystemCommand.java index d4a1b03..6415bb1 100644 --- a/gclc.system/src/main/java/net/bigeon/gclc/system/ExecSystemCommand.java +++ b/gclc.system/src/main/java/net/bigeon/gclc/system/ExecSystemCommand.java @@ -42,8 +42,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.util.logging.Level; -import java.util.logging.Logger; import net.bigeon.gclc.command.Command; import net.bigeon.gclc.exception.CommandRunException; @@ -66,9 +64,6 @@ public class ExecSystemCommand extends Command { private static final String COMMAND_DEFAULT_NAME = "exec"; //$NON-NLS-1$ /** The end of line separator */ private static final String EOL = System.lineSeparator(); - /** The class logger */ - private static final Logger LOGGER = Logger - .getLogger(ExecSystemCommand.class.getName()); /** Create the command with the name 'exec'. */ public ExecSystemCommand() { @@ -96,25 +91,12 @@ public class ExecSystemCommand extends Command { throw new CommandRunException("Unable to run process", e2); } // Stream forwarding to the application's console + // This is started in a parallel thread. final InputStream is = proc.getInputStream(); - final Thread th = new Thread(new Runnable() { - /* (non-Javadoc) - * @see java.lang.Runnable#run() */ - @Override - public void run() { - try { - readToEnd(out, is); - is.close(); - } catch (final CommandRunException e) { - LOGGER.log(Level.WARNING, "Manager was closed in the meantime...", e); //$NON-NLS-1$ - } catch (final IOException e) { - LOGGER.log(Level.WARNING, "Input stream was closed...", e); //$NON-NLS-1$ - } - } - }); + final Thread th = new Thread(new ForwardingRunnable(out, is)); th.start(); in.setPrompt(""); //$NON-NLS-1$ - // Forwar console input to the process. + // Forward console input to the process. final OutputStream os = proc.getOutputStream(); try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os))) { while (th.isAlive()) { @@ -129,38 +111,6 @@ public class ExecSystemCommand extends Command { } } - /** 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()) >= 0) { - printCharacter(out, (char) c); - } - } catch (final IOException e) { - LOGGER.log(Level.INFO, "input stream reading failed", e); //$NON-NLS-1$ - } - } - - /** Print a character on the console. - * - * @param out the console - * @param c the character - * @throws CommandRunException if the console failed to print the character. */ - private static void printCharacter(final ConsoleOutput out, final char c) - throws CommandRunException { - try { - out.print(Character.toString(c)); - } catch (final IOException e) { - throw new CommandRunException(CommandRunExceptionType.INTERACTION, - MANAGER_WAS_CLOSED, e); // $NON-NLS-1$ - } - } - /* (non-Javadoc) * @see fr.bigeon.gclc.command.ICommand#tip() */ @Override diff --git a/gclc.system/src/main/java/net/bigeon/gclc/system/ForwardingRunnable.java b/gclc.system/src/main/java/net/bigeon/gclc/system/ForwardingRunnable.java new file mode 100644 index 0000000..5be3a4f --- /dev/null +++ b/gclc.system/src/main/java/net/bigeon/gclc/system/ForwardingRunnable.java @@ -0,0 +1,117 @@ +package net.bigeon.gclc.system; + +/*- + * #%L + * GCLC system command + * %% + * Copyright (C) 2016 - 2018 Bigeon + * %% + * 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. + * #L% + */ + +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +import net.bigeon.gclc.exception.CommandRunException; +import net.bigeon.gclc.exception.CommandRunExceptionType; +import net.bigeon.gclc.manager.ConsoleOutput; + +/** A class forwarding the content of a stream into a console output. + * + * @author Emmanuel Bigeon */ +public final class ForwardingRunnable implements Runnable { + /** Error message for the manager closed. */ + private static final String MANAGER_WAS_CLOSED = "manager was closed"; + /** The class logger */ + private static final Logger LOGGER = Logger + .getLogger(ForwardingRunnable.class.getName()); + + /** The console output. */ + private final ConsoleOutput out; + /** The input stream. */ + private final InputStream is; + + /** Create the runnable. + * + * @param out the output console + * @param is the input stream */ + public ForwardingRunnable(final ConsoleOutput out, final InputStream is) { + this.out = out; + this.is = is; + } + + /* (non-Javadoc) + * @see java.lang.Runnable#run() */ + @Override + public void run() { + try { + readToEnd(out, is); + is.close(); + } catch (final CommandRunException e) { + LOGGER.log(Level.WARNING, + "Manager was closed in the meantime...", e); //$NON-NLS-1$ + } catch (final IOException e) { + LOGGER.log(Level.WARNING, "Input stream was closed...", e); //$NON-NLS-1$ + } + } + + /** Read the input until its end. + * + * @param is the input stream + * @throws CommandRunException if the manager was closed while writing the + * stream */ + private void readToEnd(final ConsoleOutput out, final InputStream is) + throws CommandRunException { + int c; + try { + while ((c = is.read()) >= 0) { + // Print the chaeacter in the output + printCharacter(out, (char) c); + } + } catch (final IOException e) { + LOGGER.log(Level.INFO, "input stream reading failed", e); //$NON-NLS-1$ + } + } + + /** Print a character on the console. + * + * @param out the console + * @param c the character + * @throws CommandRunException if the console failed to print the character. */ + private static void printCharacter(final ConsoleOutput out, final char c) + throws CommandRunException { + try { + out.print(Character.toString(c)); + } catch (final IOException e) { + throw new CommandRunException(CommandRunExceptionType.INTERACTION, + MANAGER_WAS_CLOSED, e); // $NON-NLS-1$ + } + } +} diff --git a/gclc.system/src/test/java/net/bigeon/gclc/system/ExecSystemCommandTest.java b/gclc.system/src/test/java/net/bigeon/gclc/system/ExecSystemCommandTest.java index 4789afb..7277d4b 100644 --- a/gclc.system/src/test/java/net/bigeon/gclc/system/ExecSystemCommandTest.java +++ b/gclc.system/src/test/java/net/bigeon/gclc/system/ExecSystemCommandTest.java @@ -1,5 +1,39 @@ package net.bigeon.gclc.system; +/*- + * #%L + * GCLC system command + * %% + * Copyright (C) 2016 - 2018 Bigeon + * %% + * 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. + * #L% + */ + import static org.junit.Assert.*; import org.junit.Test;