diff --git a/gclc-socket/src/main/java/fr/bigeon/gclc/socket/ConsoleRunnable.java b/gclc-socket/src/main/java/fr/bigeon/gclc/socket/ConsoleRunnable.java index 255f76c..a79e5ae 100644 --- a/gclc-socket/src/main/java/fr/bigeon/gclc/socket/ConsoleRunnable.java +++ b/gclc-socket/src/main/java/fr/bigeon/gclc/socket/ConsoleRunnable.java @@ -48,14 +48,18 @@ import fr.bigeon.gclc.ConsoleApplication; * @author Emmanuel Bigeon */ public class ConsoleRunnable implements Runnable { + /** The wait timeout */ private static final long TIMEOUT = 100; + /** The logger */ private static final Logger LOGGER = Logger .getLogger(ConsoleRunnable.class.getName()); /** The actual application */ private final ConsoleApplication app; + /** The synchro object */ private final Object lock = new Object(); /** the state of this runnable */ private boolean running = true; + /** If a start is required */ private boolean startReq; /** @param app the application */ @@ -75,7 +79,7 @@ public class ConsoleRunnable implements Runnable { lock.wait(TIMEOUT); } catch (InterruptedException e) { LOGGER.log(Level.SEVERE, - "Console application runnable interrupted wildly!", + "Console application runnable interrupted wildly!", //$NON-NLS-1$ e); return; } @@ -114,6 +118,7 @@ public class ConsoleRunnable implements Runnable { } } + /** Request a restart of application */ public void restart() { synchronized (lock) { startReq = true; @@ -121,7 +126,7 @@ public class ConsoleRunnable implements Runnable { try { lock.wait(TIMEOUT); } catch (InterruptedException e) { - LOGGER.log(Level.SEVERE, "Restart wait interrupted!", e); + LOGGER.log(Level.SEVERE, "Restart wait interrupted!", e); //$NON-NLS-1$ } } } 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 022ebb3..900b1aa 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 @@ -46,7 +46,6 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.nio.charset.Charset; -import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; @@ -54,7 +53,6 @@ import fr.bigeon.gclc.ConsoleApplication; import fr.bigeon.gclc.manager.ConsoleManager; import fr.bigeon.gclc.manager.PipedConsoleManager; import fr.bigeon.gclc.manager.ReadingRunnable; -import fr.bigeon.smu.StringEncoder; /** This is a socket communicating console consoleManager *

@@ -76,20 +74,56 @@ import fr.bigeon.smu.StringEncoder; * @author Emmanuel Bigeon */ public class SocketConsoleApplicationShell implements Runnable { - /** - * - */ - private static final String INTERRUPTION_WHILE_WORKING = "Interruption while application was working"; //$NON-NLS-1$ + /** The runnable to forward output of application to socket. + * + * @author Emmanuel Bigeon */ + private final class OutputForwardRunnable implements Runnable { + /** + * + */ + private final PrintWriter writer; + /** + * + */ + private final Socket socket; + + /** @param writer the writer + * @param socket the socket */ + protected OutputForwardRunnable(PrintWriter writer, Socket socket) { + this.writer = writer; + this.socket = socket; + } + + @SuppressWarnings("synthetic-access") + @Override + public void run() { + try { + while (!socket.isOutputShutdown()) { + while (!socket.isOutputShutdown() && + !consoleManager.available()) { + waitASec(); + } + if (socket.isOutputShutdown()) { + return; + } + String m = consoleManager.readNextLine(); + writer.println(m); + } + } catch (IOException e) { + LOGGER.log(Level.SEVERE, "Unexpected problem in manager", //$NON-NLS-1$ + e); + } + } + + } + /** The end of line character */ protected static final String EOL = "\n"; //$NON-NLS-1$ - /** The encoder */ - private static final StringEncoder ENCODER = new StringEncoder("%", //$NON-NLS-1$ - Arrays.asList(EOL)); /** The class logger */ private static final Logger LOGGER = Logger .getLogger(SocketConsoleApplicationShell.class.getName()); + /** Time of wait */ protected static final long ONE_TENTH_OF_SECOND = 100; - private static final long ONE_SEC = 100; /** The listening port */ private final int port; /** The input */ @@ -101,9 +135,6 @@ public class SocketConsoleApplicationShell implements Runnable { /** The running status */ private boolean running; -// /** The console manager implementation */ -// private final ThreadedServerConsoleManager consoleManager = new ThreadedServerConsoleManager( -// ENCODER, promptingLock); /** The console manager implementation */ private final PipedConsoleManager consoleManager; /** The auto close flag. if this is true, every request closes the session @@ -171,8 +202,7 @@ public class SocketConsoleApplicationShell implements Runnable { charset); BufferedReader inBuf = new BufferedReader(isr)) { consoleInput.connect(outStream); -// consoleManager.setInput(inBuf); - runSokectServer(writer); + runSokectServer(); // Close the application // Pass command to application if (app.isRunning()) { @@ -188,11 +218,10 @@ public class SocketConsoleApplicationShell implements Runnable { } } - /** @param writer the writer to the application - * @throws IOException if the communication with the client failed */ - private void runSokectServer(BufferedWriter writer) throws IOException { + /** @throws IOException if the communication with the client failed */ + private void runSokectServer() throws IOException { final ConsoleRunnable runnable = new ConsoleRunnable(app); - Thread appThNext = new Thread(runnable, "gclc-ctrl"); + Thread appThNext = new Thread(runnable, "gclc-ctrl"); //$NON-NLS-1$ appThNext.start(); while (running) { LOGGER.info("Opening client"); //$NON-NLS-1$ @@ -207,18 +236,10 @@ public class SocketConsoleApplicationShell implements Runnable { // Initiate application if (!runnable.isApplicationRunning()) { - LOGGER.info("Start application"); - runnable.restart(); - synchronized (this) { - try { - wait(ONE_SEC); - } catch (InterruptedException e) { - LOGGER.log(Level.SEVERE, - "Interruption in application start", e); - } - } + LOGGER.info("Start application"); //$NON-NLS-1$ + startApplication(runnable); } else { - LOGGER.info("Reconnect to application"); + LOGGER.info("Reconnect to application"); //$NON-NLS-1$ out.println("Reconnected"); //$NON-NLS-1$ out.println(consoleManager.getPrompt()); } @@ -236,44 +257,28 @@ public class SocketConsoleApplicationShell implements Runnable { LOGGER.info("Out client"); //$NON-NLS-1$ } + /** @param runnable the runnable */ + private void startApplication(ConsoleRunnable runnable) { + runnable.restart(); + synchronized (this) { + try { + wait(ONE_TENTH_OF_SECOND); + } catch (InterruptedException e) { + LOGGER.log(Level.SEVERE, "Interruption in application start", //$NON-NLS-1$ + e); + } + } + } + /** active communication between server and client * + * @param socket the socket * @param writer the writer to the application * @param in the input from the client * @throws IOException if the communication failed */ private void communicate(final Socket socket, final PrintWriter writer, BufferedReader in) throws IOException { - Thread th = new Thread(new Runnable() { - - @SuppressWarnings("synthetic-access") - @Override - public void run() { - try { - while (!socket.isOutputShutdown()) { - while (!socket.isOutputShutdown() && - !consoleManager.available()) { - try { - synchronized (this) { - wait(ONE_TENTH_OF_SECOND); - } - } catch (InterruptedException e) { - LOGGER.log(Level.SEVERE, "Interrupted wait", //$NON-NLS-1$ - e); - return; - } - } - if (socket.isOutputShutdown()) { - return; - } - String m = consoleManager.readNextLine(); - writer.println(m); - } - } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Unexpected problem in manager", //$NON-NLS-1$ - e); - } - } - }, "ClientComm"); //$NON-NLS-1$ + Thread th = new Thread(new OutputForwardRunnable(writer, socket), "ClientComm"); //$NON-NLS-1$ th.start(); if (autoClose) { communicateOnce(socket, in); @@ -282,71 +287,58 @@ public class SocketConsoleApplicationShell implements Runnable { } } - /** @param in the input from the client + /** @param socket the socket + * @param in the input from the client * @throws IOException if the communication failed */ private void communicateOnce(Socket socket, BufferedReader in) throws IOException { ReadingRunnable reading = new ReadingRunnable(in); - Thread th = new Thread(reading, "gclcToApp"); + Thread th = new Thread(reading, "gclcToApp"); //$NON-NLS-1$ th.start(); - String ln; if (app.isRunning()) { - while (app.isRunning() && !reading.hasMessage()) { - synchronized (this) { - try { - wait(ONE_SEC); - } catch (InterruptedException e) { - LOGGER.log(Level.SEVERE, "Wait interrupted", e); - } - } - } - if (!app.isRunning()) { - return; - } - ln = reading.getMessage(); - if (ln.equals(close)) { - return; - } - // Pass command to application - consoleManager.type(ln); + communicationContent(reading); } reading.setRunning(false); socket.shutdownOutput(); } - /** @param in the input from the client + /** @param socket the socket + * @param in the input from the client * @throws IOException if the communication failed */ private void communicateLoop(Socket socket, BufferedReader in) throws IOException { ReadingRunnable reading = new ReadingRunnable(in); - Thread th = new Thread(reading, "gclcToApp"); + Thread th = new Thread(reading, "gclcToApp"); //$NON-NLS-1$ th.start(); - String ln; - while (app.isRunning()) { - while (app.isRunning() && !reading.hasMessage()) { - synchronized (this) { - try { - wait(ONE_SEC); - } catch (InterruptedException e) { - LOGGER.log(Level.SEVERE, "Wait interrupted", e); - } - } - } - if (!app.isRunning()) { - break; - } - ln = reading.getMessage(); - if (ln.equals(close)) { - break; - } - // Pass command to application - consoleManager.type(ln); + while (app.isRunning() && communicationContent(reading)) { + // keep on going } reading.setRunning(false); socket.shutdownOutput(); } + /** @param reading the reading + * @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(); + } + } + if (!app.isRunning()) { + return false; + } + String ln = reading.getMessage(); + if (ln.equals(close)) { + return false; + } + // Pass command to application + consoleManager.type(ln); + return true; + } + /** @return the consoleManager */ public synchronized ConsoleManager getConsoleManager() { return consoleManager; @@ -371,4 +363,16 @@ public class SocketConsoleApplicationShell implements Runnable { app.exit(); } + /** a method to wait some time */ + protected void waitASec() { + try { + synchronized (this) { + wait(ONE_TENTH_OF_SECOND); + } + } catch (InterruptedException e) { + LOGGER.log(Level.SEVERE, "Interrupted wait", //$NON-NLS-1$ + e); + return; + } + } } diff --git a/gclc-socket/src/test/java/fr/bigeon/gclc/socket/ConsoleRunnableTest.java b/gclc-socket/src/test/java/fr/bigeon/gclc/socket/ConsoleRunnableTest.java index 73e9873..4b2ac7b 100644 --- a/gclc-socket/src/test/java/fr/bigeon/gclc/socket/ConsoleRunnableTest.java +++ b/gclc-socket/src/test/java/fr/bigeon/gclc/socket/ConsoleRunnableTest.java @@ -47,7 +47,7 @@ import fr.bigeon.gclc.manager.ConsoleManager; /** Test class for {@link ConsoleRunnable} * * @author Emmanuel Bigeon */ -@SuppressWarnings({"static-method", "unused", "javadoc"}) +@SuppressWarnings({"unused", "javadoc"}) public class ConsoleRunnableTest { /**

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 34fbc65..a81ad5b 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 @@ -128,13 +128,14 @@ public class SocketConsoleApplicationTest { while ((fromServer = in.readLine()) != null) { System.out.println("Server: \n" + ENCODER.decode(fromServer)); while (fromServer != null && !fromServer.equals("> ")) { - fromServer = in.readLine(); System.out .println("Server: \n" + ENCODER.decode(fromServer)); + fromServer = in.readLine(); } if (fromServer == null) { break; } + System.out.println("Server: \n" + ENCODER.decode(fromServer)); final String fromUser = cmds[i]; if (fromUser != null) {