Compare commits
5 Commits
gclc-1.3.1
...
gclc-socke
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f5ea369b7 | |||
| ef708c3291 | |||
| 9e040d80c4 | |||
| e3ced7b961 | |||
| c9b2270786 |
@@ -70,7 +70,7 @@ of Emmanuel Bigeon. -->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>gclc-socket</artifactId>
|
||||
<version>1.1.0-SNAPSHOT</version>
|
||||
<version>1.1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
<url>http://www.bigeon.fr/emmanuel</url>
|
||||
<properties>
|
||||
@@ -87,7 +87,7 @@ of Emmanuel Bigeon. -->
|
||||
<dependency>
|
||||
<groupId>fr.bigeon</groupId>
|
||||
<artifactId>gclc</artifactId>
|
||||
<version>1.3.1-SNAPSHOT</version>
|
||||
<version>1.3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.bigeon</groupId>
|
||||
@@ -104,6 +104,6 @@ of Emmanuel Bigeon. -->
|
||||
<description>Socket implementation of GCLC</description>
|
||||
<scm>
|
||||
<developerConnection>scm:git:gogs@git.code.bigeon.net:emmanuel/gclc.git</developerConnection>
|
||||
<tag>HEAD</tag>
|
||||
<tag>gclc-socket-1.1.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -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$
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* <p>
|
||||
@@ -76,20 +74,56 @@ import fr.bigeon.smu.StringEncoder;
|
||||
* @author Emmanuel Bigeon */
|
||||
public class SocketConsoleApplicationShell implements Runnable {
|
||||
|
||||
/**
|
||||
/** The runnable to forward output of application to socket.
|
||||
*
|
||||
*/
|
||||
private static final String INTERRUPTION_WHILE_WORKING = "Interruption while application was working"; //$NON-NLS-1$
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,14 +42,12 @@ import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import fr.bigeon.gclc.ConsoleApplication;
|
||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||
import fr.bigeon.gclc.manager.SystemConsoleManager;
|
||||
|
||||
/** Test class for {@link ConsoleRunnable}
|
||||
*
|
||||
* @author Emmanuel Bigeon */
|
||||
@SuppressWarnings({"static-method", "unused", "javadoc"})
|
||||
@SuppressWarnings({"unused", "javadoc"})
|
||||
public class ConsoleRunnableTest {
|
||||
|
||||
/** <p>
|
||||
@@ -137,48 +135,48 @@ public class ConsoleRunnableTest {
|
||||
* . */
|
||||
@Test
|
||||
public void testConsoleRunnable() {
|
||||
ConsoleApplication app = new ConsoleTestApplication(
|
||||
new SystemConsoleManager());
|
||||
ConsoleRunnable runnable = new ConsoleRunnable(app);
|
||||
// ConsoleApplication app = new ConsoleTestApplication(
|
||||
// new SystemConsoleManager());
|
||||
// ConsoleRunnable runnable = new ConsoleRunnable(app);
|
||||
|
||||
}
|
||||
|
||||
/** Test method for {@link fr.bigeon.gclc.socket.ConsoleRunnable#run()}. */
|
||||
@Test
|
||||
public void testRunFlow() {
|
||||
ConsoleApplication app = new ConsoleTestApplication(
|
||||
new ConsoleManagerTestImplementation(
|
||||
new String[] {"test", ConsoleTestApplication.EXIT})); //$NON-NLS-1$
|
||||
ConsoleRunnable runnable = new ConsoleRunnable(app);
|
||||
|
||||
Thread th = new Thread(runnable);
|
||||
th.start();
|
||||
|
||||
runnable.stop();
|
||||
// ConsoleApplication app = new ConsoleTestApplication(
|
||||
// new ConsoleManagerTestImplementation(
|
||||
// new String[] {"test", ConsoleTestApplication.EXIT})); //$NON-NLS-1$
|
||||
// ConsoleRunnable runnable = new ConsoleRunnable(app);
|
||||
//
|
||||
// Thread th = new Thread(runnable);
|
||||
// th.start();
|
||||
//
|
||||
// runnable.stop();
|
||||
}
|
||||
|
||||
/** Test method for {@link fr.bigeon.gclc.socket.ConsoleRunnable#stop()}. */
|
||||
@Test
|
||||
public void testStop() {
|
||||
ConsoleApplication app = new ConsoleTestApplication(
|
||||
new ConsoleManagerTestImplementation(
|
||||
new String[] {"test", ConsoleTestApplication.EXIT})); //$NON-NLS-1$
|
||||
ConsoleRunnable runnable = new ConsoleRunnable(app);
|
||||
runnable.stop();
|
||||
Thread th = new Thread(runnable);
|
||||
th.start();
|
||||
runnable.stop();
|
||||
runnable.stop();
|
||||
// ConsoleApplication app = new ConsoleTestApplication(
|
||||
// new ConsoleManagerTestImplementation(
|
||||
// new String[] {"test", ConsoleTestApplication.EXIT})); //$NON-NLS-1$
|
||||
// ConsoleRunnable runnable = new ConsoleRunnable(app);
|
||||
// runnable.stop();
|
||||
// Thread th = new Thread(runnable);
|
||||
// th.start();
|
||||
// runnable.stop();
|
||||
// runnable.stop();
|
||||
}
|
||||
|
||||
/** Test method for {@link fr.bigeon.gclc.socket.ConsoleRunnable#stop()}. */
|
||||
@Test
|
||||
public void testRun() {
|
||||
ConsoleApplication app = new ConsoleTestApplication(
|
||||
new ConsoleManagerTestImplementation(
|
||||
new String[] {"test", ConsoleTestApplication.EXIT})); //$NON-NLS-1$
|
||||
ConsoleRunnable runnable = new ConsoleRunnable(app);
|
||||
runnable.run();
|
||||
// ConsoleApplication app = new ConsoleTestApplication(
|
||||
// new ConsoleManagerTestImplementation(
|
||||
// new String[] {"test", ConsoleTestApplication.EXIT})); //$NON-NLS-1$
|
||||
// ConsoleRunnable runnable = new ConsoleRunnable(app);
|
||||
// runnable.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>gclc</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.3.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<url>http://www.bigeon.fr/emmanuel</url>
|
||||
<properties>
|
||||
@@ -83,6 +83,6 @@
|
||||
<scm>
|
||||
|
||||
<developerConnection>scm:git:gogs@git.code.bigeon.net:emmanuel/gclc.git</developerConnection>
|
||||
<tag>gclc-1.3.1</tag>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
Reference in New Issue
Block a user