diff --git a/gclc-socket/src/main/java/fr/bigeon/gclc/socket/SocketConsoleApplicationShell.java b/gclc-socket/src/main/java/fr/bigeon/gclc/socket/SocketConsoleApplicationShell.java index c2ee33e..f5d29e4 100644 --- a/gclc-socket/src/main/java/fr/bigeon/gclc/socket/SocketConsoleApplicationShell.java +++ b/gclc-socket/src/main/java/fr/bigeon/gclc/socket/SocketConsoleApplicationShell.java @@ -35,12 +35,9 @@ package fr.bigeon.gclc.socket; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; @@ -72,7 +69,7 @@ import fr.bigeon.gclc.manager.ReadingRunnable; * end of the execution. * * @author Emmanuel Bigeon */ -public class SocketConsoleApplicationShell implements Runnable { +public class SocketConsoleApplicationShell implements Runnable, AutoCloseable { /** The runnable to forward output of application to socket. * @@ -126,8 +123,6 @@ public class SocketConsoleApplicationShell implements Runnable { protected static final long ONE_TENTH_OF_SECOND = 100; /** The listening port */ private final int port; - /** The input */ - private final PipedInputStream consoleInput = new PipedInputStream(); /** The application */ private ConsoleApplication app; /** The session closing command */ @@ -195,18 +190,8 @@ public class SocketConsoleApplicationShell implements Runnable { this.serverSocket = actualServerSocket; running = true; // Create the streams - try (PipedOutputStream outStream = new PipedOutputStream(); - BufferedWriter writer = new BufferedWriter( - new OutputStreamWriter(outStream, charset)); - InputStreamReader isr = new InputStreamReader(consoleInput, - charset); - BufferedReader inBuf = new BufferedReader(isr)) { - consoleInput.connect(outStream); - runSokectServer(); - } - } catch ( - - final IOException e) { + runSokectServer(); + } catch (final IOException e) { LOGGER.log(Level.SEVERE, "Communication error between client and server", e); //$NON-NLS-1$ } @@ -218,7 +203,7 @@ public class SocketConsoleApplicationShell implements Runnable { Thread appThNext = new Thread(runnable, "gclc-ctrl"); //$NON-NLS-1$ appThNext.start(); while (running) { - LOGGER.info("Opening client"); //$NON-NLS-1$ + LOGGER.info("Waiting client"); //$NON-NLS-1$ try (Socket clientSocket = serverSocket.accept(); PrintWriter out = new PrintWriter(new OutputStreamWriter( clientSocket.getOutputStream(), charset), true); @@ -227,6 +212,7 @@ public class SocketConsoleApplicationShell implements Runnable { BufferedReader in = new BufferedReader(isr);) { // this is not threaded to avoid several clients at the same // time + LOGGER.info("Opening client"); //$NON-NLS-1$ // Initiate application if (!runnable.isApplicationRunning()) { @@ -248,7 +234,8 @@ public class SocketConsoleApplicationShell implements Runnable { } runnable.setRunning(false); consoleManager.type(applicationShutdown); - LOGGER.info("Out client"); //$NON-NLS-1$ + consoleManager.close(); + LOGGER.info("Closing Server"); //$NON-NLS-1$ } /** @param runnable the runnable */ @@ -279,6 +266,7 @@ public class SocketConsoleApplicationShell implements Runnable { communicateOnce(socket, in); } else { communicateLoop(socket, in); + } } @@ -315,16 +303,23 @@ public class SocketConsoleApplicationShell implements Runnable { * @return if the communication should be stopped. * @throws IOException if the reading failed */ private boolean communicationContent(ReadingRunnable reading) throws IOException { - while (app.isRunning() && !reading.hasMessage()) { - synchronized (this) { - waitASec(); + try { + while (app.isRunning() && !reading.hasMessage()) { + synchronized (this) { + waitASec(); + } } + } catch (IOException e) { + LOGGER.warning("Client seems dead. Closing communication"); //$NON-NLS-1$ + LOGGER.log(Level.FINE, "Wait on message from client failed", e); //$NON-NLS-1$ + return false; } if (!app.isRunning()) { return false; } String ln = reading.getMessage(); if (ln.equals(close)) { + consoleManager.println("Bye."); return false; } // Pass command to application @@ -368,4 +363,11 @@ public class SocketConsoleApplicationShell implements Runnable { return; } } + + /* (non-Javadoc) + * @see java.lang.AutoCloseable#close() */ + @Override + public void close() throws Exception { + consoleManager.close(); + } } diff --git a/gclc-socket/src/test/java/fr/bigeon/gclc/socket/SocketConsoleApplicationTest.java b/gclc-socket/src/test/java/fr/bigeon/gclc/socket/SocketConsoleApplicationTest.java index 4f13d1e..f2c8899 100644 --- a/gclc-socket/src/test/java/fr/bigeon/gclc/socket/SocketConsoleApplicationTest.java +++ b/gclc-socket/src/test/java/fr/bigeon/gclc/socket/SocketConsoleApplicationTest.java @@ -94,8 +94,7 @@ public class SocketConsoleApplicationTest { } while (fromServer != null && !fromServer.equals("> ")) { fromServer = in.readLine(); - System.out - .println("Server: \n" + fromServer); + LOGGER.fine("Server: \n" + fromServer); } if (fromServer == null) { fail("Null pointer"); @@ -126,8 +125,7 @@ public class SocketConsoleApplicationTest { while ((fromServer = in.readLine()) != null) { LOGGER.fine("Server: \n" + fromServer); while (fromServer != null && !fromServer.equals("> ")) { - System.out - .println("Server: \n" + fromServer); + LOGGER.fine("Server: \n" + fromServer); fromServer = in.readLine(); } if (fromServer == null) { @@ -165,8 +163,7 @@ public class SocketConsoleApplicationTest { while ((fromServer = in.readLine()) != null) { while (fromServer != null && !fromServer.equals("> ")) { fromServer = in.readLine(); - System.out - .println("Server: \n" + fromServer); + LOGGER.fine("Server: \n" + fromServer); } if (fromServer == null) { break; @@ -214,8 +211,7 @@ public class SocketConsoleApplicationTest { while (fromServer != null && !fromServer.equals("> ") && !fromServer.equals("See you")) { fromServer = in.readLine(); - System.out - .println("Server: \n" + fromServer); + LOGGER.fine("Server: \n" + fromServer); } if (fromServer == null || fromServer.equals("Bye.") || fromServer.equals("See you")) { diff --git a/gclc/src/main/java/fr/bigeon/gclc/tools/AOutputForwardRunnable.java b/gclc/src/main/java/fr/bigeon/gclc/tools/AOutputForwardRunnable.java index 6bbde38..2864664 100644 --- a/gclc/src/main/java/fr/bigeon/gclc/tools/AOutputForwardRunnable.java +++ b/gclc/src/main/java/fr/bigeon/gclc/tools/AOutputForwardRunnable.java @@ -1,3 +1,37 @@ +/* + * 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.tools.AOutputForwardRunnable.java * Created on: Dec 1, 2016 diff --git a/gclc/src/test/java/fr/bigeon/gclc/tools/AOutputForwardRunnableTest.java b/gclc/src/test/java/fr/bigeon/gclc/tools/AOutputForwardRunnableTest.java new file mode 100644 index 0000000..35d7ba6 --- /dev/null +++ b/gclc/src/test/java/fr/bigeon/gclc/tools/AOutputForwardRunnableTest.java @@ -0,0 +1,132 @@ +/* + * 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.tools.AOutputForwardRunnableTest.java + * Created on: Dec 3, 2016 + */ +package fr.bigeon.gclc.tools; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.junit.Test; + +import fr.bigeon.gclc.manager.PipedConsoleManager; + +/**
+ * TODO + * + * @author Emmanuel Bigeon */ +public class AOutputForwardRunnableTest { + + /**
+ * TODO + * + * @author Emmanuel Bigeon */ + private final class AOutputForwardTestRunnable + extends AOutputForwardRunnable { + private int count = 1; + private String message; + + /** @param manager */ + private AOutputForwardTestRunnable(PipedConsoleManager manager) { + super(manager); + } + + @Override + protected boolean isRunning() { + return count != 0; + } + + @Override + protected void forwardLine(String m) { + // Do nothing + message = m; + synchronized (this) { + notify(); + try { + wait(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + /** @return the message */ + public String getMessage() { + if (message == null) { + synchronized (this) { + try { + wait(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + String m = message; + count--; + message = null; + synchronized (this) { + notify(); + } + return m; + } + } + + /** Test method for + * {@link fr.bigeon.gclc.tools.AOutputForwardRunnable#run()}. */ + @Test + public final void testRun() { + try (PipedConsoleManager manager = new PipedConsoleManager()) { + AOutputForwardTestRunnable runnable = new AOutputForwardTestRunnable( + manager); + + Thread th = new Thread(runnable, "forward"); + th.start(); + manager.println("before"); + + assertEquals("before", runnable.getMessage()); + + th.join(); + + } catch (IOException | InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +}