Compare commits
36 Commits
gclc-1.3.3
...
gclc-1.4.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 629d07bc32 | |||
| e32e2428e5 | |||
| db9f81c6a8 | |||
| 0a995394f9 | |||
| 0ca055db8e | |||
| b93c2b5220 | |||
| 8322454f72 | |||
| ab47d6573b | |||
| 6d496d701d | |||
| b4df39491e | |||
| 775a71b2ec | |||
| c9eb221d31 | |||
| 340a0317af | |||
| 35959a8d8a | |||
| 07645d7c0c | |||
| 99c0c9008b | |||
| 26265ad7e6 | |||
| 092883f4c3 | |||
| 25904c907d | |||
| ae55ebea29 | |||
| e989aff2f4 | |||
| 2f0c03a73b | |||
| ff9ace1033 | |||
| ffa54af3be | |||
| 269704f5a2 | |||
| aecc18cc83 | |||
| 063cad61cd | |||
| 201b6ad366 | |||
| bf8d76750f | |||
| 17ac47f15e | |||
| 7de2dadbe0 | |||
| 50395ba852 | |||
| 248c82cf50 | |||
| 6289ca1db9 | |||
| 5b6634eaf0 | |||
| 4737a16874 |
@@ -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">
|
<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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>gclc-socket</artifactId>
|
<artifactId>gclc-socket</artifactId>
|
||||||
<version>1.1.5-SNAPSHOT</version>
|
<version>1.1.8-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<url>http://www.bigeon.fr/emmanuel</url>
|
<url>http://www.bigeon.fr/emmanuel</url>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -78,16 +78,10 @@ of Emmanuel Bigeon. -->
|
|||||||
<project.scm.id>git.bigeon.net</project.scm.id>
|
<project.scm.id>git.bigeon.net</project.scm.id>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>4.11</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>fr.bigeon</groupId>
|
<groupId>fr.bigeon</groupId>
|
||||||
<artifactId>gclc</artifactId>
|
<artifactId>gclc</artifactId>
|
||||||
<version>1.3.3-SNAPSHOT</version>
|
<version>1.3.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>fr.bigeon</groupId>
|
<groupId>fr.bigeon</groupId>
|
||||||
|
|||||||
@@ -95,12 +95,11 @@ public class SocketConsoleApplicationShell implements Runnable, AutoCloseable {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
while (!socket.isOutputShutdown()) {
|
while (!socket.isClosed()) {
|
||||||
while (!socket.isOutputShutdown() &&
|
while (!socket.isClosed() && !consoleManager.available()) {
|
||||||
!consoleManager.available()) {
|
|
||||||
waitASec();
|
waitASec();
|
||||||
}
|
}
|
||||||
if (socket.isOutputShutdown()) {
|
if (socket.isClosed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String m = consoleManager.readNextLine();
|
String m = consoleManager.readNextLine();
|
||||||
@@ -192,7 +191,8 @@ public class SocketConsoleApplicationShell implements Runnable, AutoCloseable {
|
|||||||
// Create the streams
|
// Create the streams
|
||||||
runSokectServer();
|
runSokectServer();
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
LOGGER.log(Level.SEVERE,
|
LOGGER.severe("Communication error between client and server"); //$NON-NLS-1$
|
||||||
|
LOGGER.log(Level.FINE,
|
||||||
"Communication error between client and server", e); //$NON-NLS-1$
|
"Communication error between client and server", e); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,12 +229,28 @@ public class SocketConsoleApplicationShell implements Runnable, AutoCloseable {
|
|||||||
LOGGER.log(Level.FINE,
|
LOGGER.log(Level.FINE,
|
||||||
"Socket closed with exception (probably due to server interruption)", //$NON-NLS-1$
|
"Socket closed with exception (probably due to server interruption)", //$NON-NLS-1$
|
||||||
e);
|
e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
LOGGER.info("Closing client"); //$NON-NLS-1$
|
LOGGER.info("Closing client"); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
runnable.setRunning(false);
|
runnable.setRunning(false);
|
||||||
|
try {
|
||||||
consoleManager.type(applicationShutdown);
|
consoleManager.type(applicationShutdown);
|
||||||
|
try {
|
||||||
|
appThNext.join(ONE_TENTH_OF_SECOND);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.warning("Application thread was interrupted!"); //$NON-NLS-1$
|
||||||
|
LOGGER.log(Level.FINE,
|
||||||
|
"Application thread was interrupted while closing", //$NON-NLS-1$
|
||||||
|
e);
|
||||||
|
}
|
||||||
consoleManager.close();
|
consoleManager.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.warning("Unable to close application correctly"); //$NON-NLS-1$
|
||||||
|
LOGGER.log(Level.FINE, "Application closing caused an exception", //$NON-NLS-1$
|
||||||
|
e);
|
||||||
|
}
|
||||||
LOGGER.info("Closing Server"); //$NON-NLS-1$
|
LOGGER.info("Closing Server"); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,43 +279,46 @@ public class SocketConsoleApplicationShell implements Runnable, AutoCloseable {
|
|||||||
Thread th = new Thread(cc, "ClientComm"); //$NON-NLS-1$
|
Thread th = new Thread(cc, "ClientComm"); //$NON-NLS-1$
|
||||||
th.start();
|
th.start();
|
||||||
if (autoClose) {
|
if (autoClose) {
|
||||||
communicateOnce(socket, in);
|
communicateOnce(in);
|
||||||
} else {
|
} else {
|
||||||
communicateLoop(socket, in);
|
communicateLoop(in);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param socket the socket
|
/** @param in the input from the client
|
||||||
* @param in the input from the client
|
|
||||||
* @throws IOException if the communication failed */
|
* @throws IOException if the communication failed */
|
||||||
private void communicateOnce(Socket socket,
|
private void communicateOnce(BufferedReader in) throws IOException {
|
||||||
BufferedReader in) throws IOException {
|
|
||||||
ReadingRunnable reading = new ReadingRunnable(in);
|
ReadingRunnable reading = new ReadingRunnable(in);
|
||||||
Thread th = new Thread(reading, "gclcToApp"); //$NON-NLS-1$
|
Thread th = new Thread(reading, "gclcToApp"); //$NON-NLS-1$
|
||||||
th.start();
|
th.start();
|
||||||
communicationContent(reading);
|
communicationContent(reading);
|
||||||
reading.setRunning(false);
|
doEndCommunication(reading);
|
||||||
socket.shutdownOutput();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param socket the socket
|
/** @param reading the reading runnable
|
||||||
* @param in the input from the client
|
* @throws IOException if the end of communication failed */
|
||||||
|
private void doEndCommunication(ReadingRunnable reading) throws IOException {
|
||||||
|
reading.setRunning(false);
|
||||||
|
Thread wait = consoleManager.getWaitForDelivery("Bye."); //$NON-NLS-1$
|
||||||
|
consoleManager.println("Bye."); //$NON-NLS-1$
|
||||||
|
try {
|
||||||
|
wait.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.warning("The Bye wait was interrupted."); //$NON-NLS-1$
|
||||||
|
LOGGER.log(Level.FINE, "An interruption occured", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param in the input from the client
|
||||||
* @throws IOException if the communication failed */
|
* @throws IOException if the communication failed */
|
||||||
private void communicateLoop(Socket socket,
|
private void communicateLoop(BufferedReader in) throws IOException {
|
||||||
BufferedReader in) throws IOException {
|
|
||||||
ReadingRunnable reading = new ReadingRunnable(in);
|
ReadingRunnable reading = new ReadingRunnable(in);
|
||||||
Thread th = new Thread(reading, "gclcToApp"); //$NON-NLS-1$
|
Thread th = new Thread(reading, "gclcToApp"); //$NON-NLS-1$
|
||||||
th.start();
|
th.start();
|
||||||
while (app.isRunning() && communicationContent(reading)) {
|
while (app.isRunning() && communicationContent(reading)) {
|
||||||
// keep on going
|
// keep on going
|
||||||
}
|
}
|
||||||
reading.setRunning(false);
|
doEndCommunication(reading);
|
||||||
while (consoleManager.available()) {
|
|
||||||
waitASec();
|
|
||||||
}
|
|
||||||
socket.shutdownOutput();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param reading the reading
|
/** @param reading the reading
|
||||||
@@ -322,14 +341,6 @@ public class SocketConsoleApplicationShell implements Runnable, AutoCloseable {
|
|||||||
}
|
}
|
||||||
String ln = reading.getMessage();
|
String ln = reading.getMessage();
|
||||||
if (ln.equals(close)) {
|
if (ln.equals(close)) {
|
||||||
Thread wait = consoleManager.getWaitForDelivery("Bye."); //$NON-NLS-1$
|
|
||||||
consoleManager.println("Bye."); //$NON-NLS-1$
|
|
||||||
try {
|
|
||||||
wait.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LOGGER.warning("The Bye wait was interrupted."); //$NON-NLS-1$
|
|
||||||
LOGGER.log(Level.FINE, "An interruption occured", e); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Pass command to application
|
// Pass command to application
|
||||||
|
|||||||
@@ -89,17 +89,10 @@ public class SocketConsoleApplicationTest {
|
|||||||
String[] cmds = {"help", "toto", "test", "bye"};
|
String[] cmds = {"help", "toto", "test", "bye"};
|
||||||
while ((fromServer = in.readLine()) != null) {
|
while ((fromServer = in.readLine()) != null) {
|
||||||
i++;
|
i++;
|
||||||
LOGGER.fine("Server: \n" + fromServer);
|
fromServer = consumeToPrompt(fromServer, in);
|
||||||
if (fromServer.equals("Bye.")) {
|
if (fromServer == null || fromServer.equals("Bye.")) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while (fromServer != null && !fromServer.equals("> ")) {
|
|
||||||
fromServer = in.readLine();
|
|
||||||
LOGGER.fine("Server: \n" + fromServer);
|
|
||||||
}
|
|
||||||
if (fromServer == null) {
|
|
||||||
fail("Null pointer");
|
|
||||||
}
|
|
||||||
|
|
||||||
final String fromUser = cmds[i];
|
final String fromUser = cmds[i];
|
||||||
if (fromUser != null) {
|
if (fromUser != null) {
|
||||||
@@ -123,19 +116,15 @@ public class SocketConsoleApplicationTest {
|
|||||||
String[] cmds = {"help", "toto", "test",
|
String[] cmds = {"help", "toto", "test",
|
||||||
ConsoleTestApplication.EXIT};
|
ConsoleTestApplication.EXIT};
|
||||||
while ((fromServer = in.readLine()) != null) {
|
while ((fromServer = in.readLine()) != null) {
|
||||||
LOGGER.fine("Server: \n" + fromServer);
|
fromServer = consumeToPrompt(fromServer, in);
|
||||||
while (fromServer != null && !fromServer.equals("> ")) {
|
if (fromServer == null || fromServer.equals("Bye.")) {
|
||||||
LOGGER.fine("Server: \n" + fromServer);
|
|
||||||
fromServer = in.readLine();
|
|
||||||
}
|
|
||||||
if (fromServer == null) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
LOGGER.fine("Server: \n" + fromServer);
|
LOGGER.info("Server: \n" + fromServer);
|
||||||
|
|
||||||
final String fromUser = cmds[i];
|
final String fromUser = cmds[i];
|
||||||
if (fromUser != null) {
|
if (fromUser != null) {
|
||||||
LOGGER.fine("Client: " + fromUser);
|
LOGGER.info("Client: " + fromUser);
|
||||||
out.println(fromUser);
|
out.println(fromUser);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
@@ -161,11 +150,8 @@ public class SocketConsoleApplicationTest {
|
|||||||
String[] cmds = {"help", "toto", "test",
|
String[] cmds = {"help", "toto", "test",
|
||||||
ConsoleTestApplication.EXIT};
|
ConsoleTestApplication.EXIT};
|
||||||
while ((fromServer = in.readLine()) != null) {
|
while ((fromServer = in.readLine()) != null) {
|
||||||
while (fromServer != null && !fromServer.equals("> ")) {
|
fromServer = consumeToPrompt(fromServer, in);
|
||||||
fromServer = in.readLine();
|
if (fromServer == null || fromServer.equals("Bye.")) {
|
||||||
LOGGER.fine("Server: \n" + fromServer);
|
|
||||||
}
|
|
||||||
if (fromServer == null) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,17 +193,11 @@ public class SocketConsoleApplicationTest {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
String[] cmds = {"help", "test", "close"};
|
String[] cmds = {"help", "test", "close"};
|
||||||
while ((fromServer = in.readLine()) != null) {
|
while ((fromServer = in.readLine()) != null) {
|
||||||
assertTrue(i < 1);
|
fromServer = consumeToPrompt(fromServer, in);
|
||||||
while (fromServer != null && !fromServer.equals("> ") &&
|
if (fromServer == null || fromServer.equals("Bye.")) {
|
||||||
!fromServer.equals("See you")) {
|
|
||||||
fromServer = in.readLine();
|
|
||||||
LOGGER.fine("Server: \n" + fromServer);
|
|
||||||
}
|
|
||||||
if (fromServer == null || fromServer.equals("Bye.") ||
|
|
||||||
fromServer.equals("See you")) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
assertTrue(i < 1);
|
||||||
final String fromUser = cmds[i];
|
final String fromUser = cmds[i];
|
||||||
if (fromUser != null) {
|
if (fromUser != null) {
|
||||||
LOGGER.fine("Client: " + fromUser);
|
LOGGER.fine("Client: " + fromUser);
|
||||||
@@ -243,4 +223,19 @@ public class SocketConsoleApplicationTest {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param in the input
|
||||||
|
* @return the string
|
||||||
|
* @throws IOException if the input reading failed */
|
||||||
|
private String consumeToPrompt(String server,
|
||||||
|
BufferedReader in) throws IOException {
|
||||||
|
String fromServer = server;
|
||||||
|
LOGGER.fine("Server: \n" + fromServer);
|
||||||
|
while (fromServer != null && !fromServer.equals("Bye.") &&
|
||||||
|
!fromServer.equals("> ")) {
|
||||||
|
fromServer = in.readLine();
|
||||||
|
LOGGER.fine("Server: \n" + fromServer);
|
||||||
|
}
|
||||||
|
return fromServer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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">
|
<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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>gclc-swt</artifactId>
|
<artifactId>gclc-swt</artifactId>
|
||||||
<version>1.1.3-SNAPSHOT</version>
|
<version>1.1.4-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<url>http://www.bigeon.fr/emmanuel</url>
|
<url>http://www.bigeon.fr/emmanuel</url>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>fr.bigeon</groupId>
|
<groupId>fr.bigeon</groupId>
|
||||||
<artifactId>gclc</artifactId>
|
<artifactId>gclc</artifactId>
|
||||||
<version>1.3.2</version>
|
<version>1.3.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>fr.bigeon</groupId>
|
<groupId>fr.bigeon</groupId>
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.events.FocusAdapter;
|
|
||||||
import org.eclipse.swt.events.FocusEvent;
|
|
||||||
import org.eclipse.swt.layout.GridData;
|
import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.layout.GridLayout;
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
@@ -101,13 +99,6 @@ public class SWTConsole extends Composite
|
|||||||
consoleOutput.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true,
|
consoleOutput.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true,
|
||||||
LAYOUT_NB_COLUMNS, 1));
|
LAYOUT_NB_COLUMNS, 1));
|
||||||
consoleOutput.setRedraw(true);
|
consoleOutput.setRedraw(true);
|
||||||
consoleOutput.addFocusListener(new FocusAdapter() {
|
|
||||||
@SuppressWarnings("synthetic-access")
|
|
||||||
@Override
|
|
||||||
public void focusGained(FocusEvent e) {
|
|
||||||
consoleInput.setFocus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
lblPromptlabel = new Label(this, SWT.NONE);
|
lblPromptlabel = new Label(this, SWT.NONE);
|
||||||
lblPromptlabel.setText(prompt);
|
lblPromptlabel.setText(prompt);
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.events.FocusAdapter;
|
|
||||||
import org.eclipse.swt.events.FocusEvent;
|
|
||||||
import org.eclipse.swt.layout.GridData;
|
import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.layout.GridLayout;
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
@@ -115,13 +113,6 @@ public class SWTConsoleView extends Composite implements ConsoleDelayIO {
|
|||||||
consoleOutput.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true,
|
consoleOutput.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true,
|
||||||
1, 1));
|
1, 1));
|
||||||
consoleOutput.setRedraw(true);
|
consoleOutput.setRedraw(true);
|
||||||
consoleOutput.addFocusListener(new FocusAdapter() {
|
|
||||||
@SuppressWarnings("synthetic-access")
|
|
||||||
@Override
|
|
||||||
public void focusGained(FocusEvent e) {
|
|
||||||
consoleInput.setFocus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
consoleInput = new Text(this, SWT.BORDER);
|
consoleInput = new Text(this, SWT.BORDER);
|
||||||
consoleInput.setLayoutData(
|
consoleInput.setLayoutData(
|
||||||
|
|||||||
@@ -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">
|
<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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>gclc</artifactId>
|
<artifactId>gclc</artifactId>
|
||||||
<version>1.3.3</version>
|
<version>1.4.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<url>http://www.bigeon.fr/emmanuel</url>
|
<url>http://www.bigeon.fr/emmanuel</url>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>fr.bigeon</groupId>
|
<groupId>fr.bigeon</groupId>
|
||||||
<artifactId>ebigeon-config</artifactId>
|
<artifactId>ebigeon-config</artifactId>
|
||||||
<version>1.7.0</version>
|
<version>1.7.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
@@ -83,6 +83,6 @@
|
|||||||
<scm>
|
<scm>
|
||||||
|
|
||||||
<developerConnection>scm:git:gogs@git.code.bigeon.net:emmanuel/gclc.git</developerConnection>
|
<developerConnection>scm:git:gogs@git.code.bigeon.net:emmanuel/gclc.git</developerConnection>
|
||||||
<tag>gclc-1.3.3</tag>
|
<tag>gclc-1.4.0</tag>
|
||||||
</scm>
|
</scm>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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.ApplicationAttachement.java
|
||||||
|
* Created on: Apr 19, 2017
|
||||||
|
*/
|
||||||
|
package fr.bigeon.gclc;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface ApplicationAttachement {
|
||||||
|
/** Attach this object to a console application.
|
||||||
|
* <p>
|
||||||
|
* The attaching usually consist in the addition of commands in the console
|
||||||
|
* application. The attached command should be specific to the attachement
|
||||||
|
* (typically, the generic help command or the script command should not be
|
||||||
|
* added through this mechanism).
|
||||||
|
*
|
||||||
|
* @param application the application
|
||||||
|
* @throws InvalidCommandName if a command name is invalid for the
|
||||||
|
* application. */
|
||||||
|
void attach(ConsoleApplication application) throws InvalidCommandName;
|
||||||
|
}
|
||||||
@@ -73,19 +73,19 @@ import fr.bigeon.gclc.manager.ConsoleManager;
|
|||||||
* start method.
|
* start method.
|
||||||
*
|
*
|
||||||
* @author Emmanuel BIGEON */
|
* @author Emmanuel BIGEON */
|
||||||
public class ConsoleApplication implements ICommandProvider {
|
public final class ConsoleApplication implements ICommandProvider {
|
||||||
|
|
||||||
/** The class logger */
|
/** The class logger */
|
||||||
private static final Logger LOGGER = Logger
|
private static final Logger LOGGER = Logger
|
||||||
.getLogger(ConsoleApplication.class.getName());
|
.getLogger(ConsoleApplication.class.getName());
|
||||||
/** The welcome message */
|
/** The welcome message */
|
||||||
private final String header;
|
public final String header;
|
||||||
/** The good bye message */
|
/** The good bye message */
|
||||||
private final String footer;
|
public final String footer;
|
||||||
/** The console manager */
|
/** The console manager */
|
||||||
protected final ConsoleManager manager;
|
public final ConsoleManager manager;
|
||||||
/** The container of commands */
|
/** The container of commands */
|
||||||
private final SubedCommand root;
|
public final SubedCommand root;
|
||||||
/** The state of this application */
|
/** The state of this application */
|
||||||
private boolean running;
|
private boolean running;
|
||||||
/** The listeners */
|
/** The listeners */
|
||||||
@@ -135,11 +135,6 @@ public class ConsoleApplication implements ICommandProvider {
|
|||||||
return root.get(command);
|
return root.get(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return the manager */
|
|
||||||
public final ConsoleManager getManager() {
|
|
||||||
return manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param cmd the command
|
/** @param cmd the command
|
||||||
* @throws IOException if the command could not be parsed */
|
* @throws IOException if the command could not be parsed */
|
||||||
public final void interpretCommand(String cmd) throws IOException {
|
public final void interpretCommand(String cmd) throws IOException {
|
||||||
@@ -161,7 +156,7 @@ public class ConsoleApplication implements ICommandProvider {
|
|||||||
.getString("ConsoleApplication.cmd.failed", cmd)); //$NON-NLS-1$
|
.getString("ConsoleApplication.cmd.failed", cmd)); //$NON-NLS-1$
|
||||||
manager.println(e.getLocalizedMessage());
|
manager.println(e.getLocalizedMessage());
|
||||||
if (e.getType() == CommandRunExceptionType.USAGE) {
|
if (e.getType() == CommandRunExceptionType.USAGE) {
|
||||||
e.getSource().help(getManager());
|
e.getSource().help(manager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,19 +242,4 @@ public class ConsoleApplication implements ICommandProvider {
|
|||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return the root */
|
|
||||||
public SubedCommand getRoot() {
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return the header */
|
|
||||||
public String getHeader() {
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return the footer */
|
|
||||||
public String getFooter() {
|
|
||||||
return footer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,4 +184,11 @@ public class CommandParameters {
|
|||||||
public Set<String> getStringArgumentKeys() {
|
public Set<String> getStringArgumentKeys() {
|
||||||
return stringArguments.keySet();
|
return stringArguments.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param key the key
|
||||||
|
* @return if the key is present in string arguments or boolean ones. */
|
||||||
|
public boolean hasArgument(String key) {
|
||||||
|
return stringArguments.containsKey(key) ||
|
||||||
|
booleanArguments.containsKey(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,7 +167,8 @@ public abstract class ParametrizedCommand extends Command {
|
|||||||
/** @param param the parameter
|
/** @param param the parameter
|
||||||
* @param stringParameter the string parameter type
|
* @param stringParameter the string parameter type
|
||||||
* @param needed if the parameter is needed
|
* @param needed if the parameter is needed
|
||||||
* @throws InvalidParameterException if the new definition is invalid */
|
* @throws InvalidParameterException if the new definition is invalid
|
||||||
|
* @deprecated since 1.3.3 */
|
||||||
@Deprecated
|
@Deprecated
|
||||||
private void checkParam(String param, boolean stringParameter,
|
private void checkParam(String param, boolean stringParameter,
|
||||||
boolean needed) throws InvalidParameterException {
|
boolean needed) throws InvalidParameterException {
|
||||||
@@ -246,9 +247,10 @@ public abstract class ParametrizedCommand extends Command {
|
|||||||
for (final String string : toProvide) {
|
for (final String string : toProvide) {
|
||||||
String value;
|
String value;
|
||||||
try {
|
try {
|
||||||
value = manager.prompt(string);
|
value = manager.prompt("value of " + string + "? ");
|
||||||
while (value.isEmpty()) {
|
while (value.isEmpty()) {
|
||||||
value = manager.prompt(string);
|
value = manager.prompt(
|
||||||
|
"value of " + string + "? (cannot be empty) ");
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CommandRunException(
|
throw new CommandRunException(
|
||||||
|
|||||||
@@ -107,8 +107,8 @@ public class ScriptExecution extends Command {
|
|||||||
application.executeSub(command, ps.toArray(new String[0]));
|
application.executeSub(command, ps.toArray(new String[0]));
|
||||||
}
|
}
|
||||||
} catch (CommandParsingException e) {
|
} catch (CommandParsingException e) {
|
||||||
throw new CommandRunException("Invalid command in script (" + //$NON-NLS-1$
|
throw new CommandRunException(MessageFormat.format(
|
||||||
e.getLocalizedMessage() + ")", //$NON-NLS-1$
|
"Invalid command in script ({0})", e.getLocalizedMessage()), //$NON-NLS-1$
|
||||||
e, this);
|
e, this);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CommandRunException("Unable to read script", //$NON-NLS-1$
|
throw new CommandRunException("Unable to read script", //$NON-NLS-1$
|
||||||
@@ -166,31 +166,41 @@ public class ScriptExecution extends Command {
|
|||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see fr.bigeon.gclc.command.Command#usageDetail() */
|
* @see fr.bigeon.gclc.command.Command#usageDetail() */
|
||||||
|
@SuppressWarnings("nls")
|
||||||
@Override
|
@Override
|
||||||
protected String usageDetail() {
|
protected String usageDetail() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append(
|
builder.append(
|
||||||
" scriptfile: path to the file containing the script to execute."); //$NON-NLS-1$
|
" scriptfile: path to the file containing the script to execute.");
|
||||||
builder.append(System.lineSeparator());
|
builder.append(System.lineSeparator());
|
||||||
builder.append(System.lineSeparator());
|
builder.append(System.lineSeparator());
|
||||||
builder.append(
|
builder.append(
|
||||||
" The script file must contain one line commands. The lines must never"); //$NON-NLS-1$
|
" The script file must contain one line commands. The lines must never");
|
||||||
builder.append(System.lineSeparator());
|
builder.append(System.lineSeparator());
|
||||||
builder.append(
|
builder.append(
|
||||||
"start with whitespace characters. The lines starting with"); //$NON-NLS-1$
|
"start with whitespace characters. The lines starting with");
|
||||||
builder.append(System.lineSeparator());
|
builder.append(System.lineSeparator());
|
||||||
builder.append("\"" + commentPrefix + //$NON-NLS-1$
|
builder.append("\"" + commentPrefix +
|
||||||
"\" will be ignored as well as empty lines."); //$NON-NLS-1$
|
"\" will be ignored as well as empty lines.");
|
||||||
builder.append(System.lineSeparator());
|
builder.append(System.lineSeparator());
|
||||||
|
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.Command#usagePattern() */
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
@Override
|
||||||
|
protected String usagePattern() {
|
||||||
|
return super.usagePattern() + " <scriptfile>";
|
||||||
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see fr.bigeon.gclc.command.ICommand#tip() */
|
* @see fr.bigeon.gclc.command.ICommand#tip() */
|
||||||
|
@SuppressWarnings("nls")
|
||||||
@Override
|
@Override
|
||||||
public String tip() {
|
public String tip() {
|
||||||
return "Execute a script"; //$NON-NLS-1$
|
return "Execute a script";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,12 +74,25 @@ public interface ConsoleManager extends AutoCloseable {
|
|||||||
* @throws InterruptedIOException if the prompt was interrupted */
|
* @throws InterruptedIOException if the prompt was interrupted */
|
||||||
String prompt() throws IOException;
|
String prompt() throws IOException;
|
||||||
|
|
||||||
|
/** @param timeout the time to wait in milliseconds
|
||||||
|
* @return the user inputed string, null if the timeout was reached
|
||||||
|
* @throws IOException if the manager is closed or could not read the prompt
|
||||||
|
* @throws InterruptedIOException if the prompt was interrupted */
|
||||||
|
String prompt(long timeout) throws IOException;
|
||||||
|
|
||||||
/** @param message the message to prompt the user
|
/** @param message the message to prompt the user
|
||||||
* @return the user inputed string
|
* @return the user inputed string
|
||||||
* @throws IOException if the manager is closed or could not read the prompt
|
* @throws IOException if the manager is closed or could not read the prompt
|
||||||
* @throws InterruptedIOException if the prompt was interrupted */
|
* @throws InterruptedIOException if the prompt was interrupted */
|
||||||
String prompt(String message) throws IOException;
|
String prompt(String message) throws IOException;
|
||||||
|
|
||||||
|
/** @param timeout the time to wait in milliseconds
|
||||||
|
* @param message the message to prompt the user
|
||||||
|
* @return the user inputed string, null if the timeout was reached
|
||||||
|
* @throws IOException if the manager is closed or could not read the prompt
|
||||||
|
* @throws InterruptedIOException if the prompt was interrupted */
|
||||||
|
String prompt(String message, long timeout) throws IOException;
|
||||||
|
|
||||||
/** <p>
|
/** <p>
|
||||||
* Set a prompting prefix.
|
* Set a prompting prefix.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -121,11 +121,23 @@ public final class PipedConsoleManager
|
|||||||
.prompt(innerManager.getPrompt() + System.lineSeparator());
|
.prompt(innerManager.getPrompt() + System.lineSeparator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleManager#prompt(long) */
|
||||||
|
@Override
|
||||||
|
public String prompt(long timeout) throws IOException {
|
||||||
|
return innerManager.prompt(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String prompt(String message) throws IOException {
|
public String prompt(String message) throws IOException {
|
||||||
return innerManager.prompt(message + System.lineSeparator());
|
return innerManager.prompt(message + System.lineSeparator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String prompt(String message, long timeout) throws IOException {
|
||||||
|
return innerManager.prompt(message + System.lineSeparator(), timeout);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPrompt(String prompt) {
|
public void setPrompt(String prompt) {
|
||||||
innerManager.setPrompt(prompt);
|
innerManager.setPrompt(prompt);
|
||||||
|
|||||||
@@ -53,6 +53,60 @@ import java.util.logging.Logger;
|
|||||||
* @author Emmanuel Bigeon */
|
* @author Emmanuel Bigeon */
|
||||||
public class ReadingRunnable implements Runnable {
|
public class ReadingRunnable implements Runnable {
|
||||||
|
|
||||||
|
/** The runnable to wait for notification on an object
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon */
|
||||||
|
private final class ToWaitRunnable implements Runnable {
|
||||||
|
/** The Object */
|
||||||
|
private final Object obj;
|
||||||
|
/** The locking object */
|
||||||
|
private final Object start;
|
||||||
|
/** The message */
|
||||||
|
private final String message;
|
||||||
|
/** The started status */
|
||||||
|
private boolean started = false;
|
||||||
|
|
||||||
|
/** @param obj the object to lock on
|
||||||
|
* @param start the object to notify when ready to wait
|
||||||
|
* @param message the message to wait for */
|
||||||
|
public ToWaitRunnable(Object obj, Object start, String message) {
|
||||||
|
this.obj = obj;
|
||||||
|
this.start = start;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("synthetic-access")
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
synchronized (obj) {
|
||||||
|
synchronized (start) {
|
||||||
|
started = true;
|
||||||
|
start.notify();
|
||||||
|
}
|
||||||
|
while (isRunning()) {
|
||||||
|
try {
|
||||||
|
obj.wait();
|
||||||
|
if (delivering.equals(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, THREAD_INTERRUPTION_EXCEPTION,
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the started */
|
||||||
|
public boolean isStarted() {
|
||||||
|
synchronized (start) {
|
||||||
|
return started;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The thread intteruption logging message */
|
||||||
|
private static final String THREAD_INTERRUPTION_EXCEPTION = "Thread interruption exception."; //$NON-NLS-1$
|
||||||
/** The closed pipe message */
|
/** The closed pipe message */
|
||||||
private static final String CLOSED_PIPE = "Closed pipe"; //$NON-NLS-1$
|
private static final String CLOSED_PIPE = "Closed pipe"; //$NON-NLS-1$
|
||||||
/** Wait timeout */
|
/** Wait timeout */
|
||||||
@@ -71,14 +125,11 @@ public class ReadingRunnable implements Runnable {
|
|||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
/** The waiting status for a message */
|
/** The waiting status for a message */
|
||||||
private boolean waiting;
|
private boolean waiting;
|
||||||
/**
|
/** The blocker for a given message */
|
||||||
* The blocker for a given message
|
|
||||||
*/
|
|
||||||
private final Map<String, Object> messageBlocker = new HashMap<>();
|
private final Map<String, Object> messageBlocker = new HashMap<>();
|
||||||
/**
|
/** The lock */
|
||||||
* The lock
|
|
||||||
*/
|
|
||||||
private final Object messageBlockerLock = new Object();
|
private final Object messageBlockerLock = new Object();
|
||||||
|
/** The message being delivered */
|
||||||
private String delivering;
|
private String delivering;
|
||||||
|
|
||||||
/** @param reader the input to read from */
|
/** @param reader the input to read from */
|
||||||
@@ -146,8 +197,7 @@ public class ReadingRunnable implements Runnable {
|
|||||||
try {
|
try {
|
||||||
lock.wait(TIMEOUT);
|
lock.wait(TIMEOUT);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.log(Level.SEVERE, "Thread interruption exception.", //$NON-NLS-1$
|
LOGGER.log(Level.SEVERE, THREAD_INTERRUPTION_EXCEPTION, e);
|
||||||
e);
|
|
||||||
}
|
}
|
||||||
if (messages.isEmpty() && !running) {
|
if (messages.isEmpty() && !running) {
|
||||||
throw new IOException(CLOSED_PIPE);
|
throw new IOException(CLOSED_PIPE);
|
||||||
@@ -160,6 +210,28 @@ public class ReadingRunnable implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getNextMessage(long timeout) throws IOException {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (!running) {
|
||||||
|
throw new IOException(CLOSED_PIPE);
|
||||||
|
}
|
||||||
|
waiting = true;
|
||||||
|
try {
|
||||||
|
lock.wait(timeout);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, THREAD_INTERRUPTION_EXCEPTION, e);
|
||||||
|
}
|
||||||
|
if (messages.isEmpty() && !running) {
|
||||||
|
throw new IOException(CLOSED_PIPE);
|
||||||
|
}
|
||||||
|
waiting = false;
|
||||||
|
if (messages.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return messages.poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @param running the running to set */
|
/** @param running the running to set */
|
||||||
public void setRunning(boolean running) {
|
public void setRunning(boolean running) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
@@ -218,38 +290,20 @@ public class ReadingRunnable implements Runnable {
|
|||||||
}
|
}
|
||||||
final Object obj = messageBlocker.get(message);
|
final Object obj = messageBlocker.get(message);
|
||||||
final Object start = new Object();
|
final Object start = new Object();
|
||||||
Thread th = new Thread(new Runnable() {
|
ToWaitRunnable waitRunn = new ToWaitRunnable(obj, start, message);
|
||||||
|
Thread th = new Thread(waitRunn);
|
||||||
|
|
||||||
@SuppressWarnings("synthetic-access")
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
synchronized (obj) {
|
|
||||||
synchronized (start) {
|
|
||||||
start.notify();
|
|
||||||
}
|
|
||||||
while (isRunning()) {
|
|
||||||
try {
|
|
||||||
obj.wait();
|
|
||||||
if (delivering.equals(message)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LOGGER.log(Level.SEVERE,
|
|
||||||
"Thread interruption exception.", e); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
synchronized (start) {
|
synchronized (start) {
|
||||||
th.start();
|
th.start();
|
||||||
|
while (!waitRunn.isStarted()) {
|
||||||
try {
|
try {
|
||||||
start.wait();
|
start.wait(TIMEOUT);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.log(Level.SEVERE, "Thread interruption exception.", //$NON-NLS-1$
|
LOGGER.log(Level.SEVERE, THREAD_INTERRUPTION_EXCEPTION,
|
||||||
e);
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return th;
|
return th;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,6 +136,13 @@ public final class SystemConsoleManager implements ConsoleManager { // NOSONAR
|
|||||||
return prompt(prompt);
|
return prompt(prompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.manager.ConsoleManager#prompt(long) */
|
||||||
|
@Override
|
||||||
|
public String prompt(long timeout) throws IOException {
|
||||||
|
return prompt(prompt, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see fr.bigeon.gclc.ConsoleManager#prompt(java.lang.String) */
|
* @see fr.bigeon.gclc.ConsoleManager#prompt(java.lang.String) */
|
||||||
@Override
|
@Override
|
||||||
@@ -145,6 +152,15 @@ public final class SystemConsoleManager implements ConsoleManager { // NOSONAR
|
|||||||
return reading.getMessage();
|
return reading.getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.ConsoleManager#prompt(java.lang.String) */
|
||||||
|
@Override
|
||||||
|
public String prompt(String message, long timeout) throws IOException {
|
||||||
|
checkOpen();
|
||||||
|
out.print(message);
|
||||||
|
return reading.getNextMessage(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
/** @param prompt the prompt to set */
|
/** @param prompt the prompt to set */
|
||||||
@Override
|
@Override
|
||||||
public void setPrompt(String prompt) {
|
public void setPrompt(String prompt) {
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.proc.InterruptionListener.java
|
||||||
|
* Created on: May 10, 2017
|
||||||
|
*/
|
||||||
|
package fr.bigeon.gclc.proc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface InterruptionListener {
|
||||||
|
void interrupted();
|
||||||
|
}
|
||||||
77
gclc/src/main/java/fr/bigeon/gclc/proc/ProcessKill.java
Normal file
77
gclc/src/main/java/fr/bigeon/gclc/proc/ProcessKill.java
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* 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.proc.ProcessList.java
|
||||||
|
* Created on: May 10, 2017
|
||||||
|
*/
|
||||||
|
package fr.bigeon.gclc.proc;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.command.Command;
|
||||||
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ProcessKill extends Command {
|
||||||
|
private final TaskPool pool;
|
||||||
|
|
||||||
|
/** @param name the command name
|
||||||
|
* @param pool the pool */
|
||||||
|
public ProcessKill(String name, TaskPool pool) {
|
||||||
|
super(name);
|
||||||
|
this.pool = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.ICommand#execute(java.lang.String[])
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void execute(String... args) throws CommandRunException {
|
||||||
|
pool.get(args[0]).setRunning(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.ICommand#tip()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String tip() {
|
||||||
|
return "List all processes";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
101
gclc/src/main/java/fr/bigeon/gclc/proc/ProcessList.java
Normal file
101
gclc/src/main/java/fr/bigeon/gclc/proc/ProcessList.java
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* 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.proc.ProcessList.java
|
||||||
|
* Created on: May 10, 2017
|
||||||
|
*/
|
||||||
|
package fr.bigeon.gclc.proc;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.command.Command;
|
||||||
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
|
import fr.bigeon.gclc.exception.CommandRunExceptionType;
|
||||||
|
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ProcessList extends Command {
|
||||||
|
private final TaskPool pool;
|
||||||
|
|
||||||
|
private final ConsoleManager manager;
|
||||||
|
|
||||||
|
/** @param name the command name
|
||||||
|
* @param pool the pool
|
||||||
|
* @param manager the console manager */
|
||||||
|
public ProcessList(String name, TaskPool pool,
|
||||||
|
ConsoleManager manager) {
|
||||||
|
super(name);
|
||||||
|
this.pool = pool;
|
||||||
|
this.manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.ICommand#execute(java.lang.String[])
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void execute(String... args) throws CommandRunException {
|
||||||
|
ArrayList<String> pids = new ArrayList<>(pool.getPIDs());
|
||||||
|
Collections.sort(pids);
|
||||||
|
for (String string : pids) {
|
||||||
|
try {
|
||||||
|
// XXX Format?
|
||||||
|
manager.println(
|
||||||
|
string + "\t" + pool.get(string).getName());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CommandRunException(
|
||||||
|
CommandRunExceptionType.INTERACTION,
|
||||||
|
"Unable to communicate with user", e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.ICommand#tip()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String tip() {
|
||||||
|
return "List all processes";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
77
gclc/src/main/java/fr/bigeon/gclc/proc/Task.java
Normal file
77
gclc/src/main/java/fr/bigeon/gclc/proc/Task.java
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* 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.proc.ThreadCommand.java
|
||||||
|
* Created on: May 10, 2017
|
||||||
|
*/
|
||||||
|
package fr.bigeon.gclc.proc;
|
||||||
|
|
||||||
|
/** Tasks are named runnable that can be interrupted.
|
||||||
|
* <p>
|
||||||
|
* Good practice for those objects include an absence of interaction with the
|
||||||
|
* user (otherwise the user may not know from which running command comes
|
||||||
|
* information and requests) and unicity of the object to have a coherent
|
||||||
|
* control through the {@link #setRunning(boolean)} method.
|
||||||
|
* <p>
|
||||||
|
* Typical cases where such command can be useful is for an application that
|
||||||
|
* does long computations.
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon */
|
||||||
|
public interface Task extends Runnable {
|
||||||
|
/** @return the task name */
|
||||||
|
public String getName();
|
||||||
|
|
||||||
|
/** @return if the command is supposed to be running */
|
||||||
|
boolean isRunning();
|
||||||
|
|
||||||
|
/** Set the running state.
|
||||||
|
* <p>
|
||||||
|
* This method should be only called by external objects with the false
|
||||||
|
* argument. Calling this method with true has unspecified behavior and
|
||||||
|
* could do nothing as well as restart the command for example.
|
||||||
|
*
|
||||||
|
* @param running the running state */
|
||||||
|
void setRunning(boolean running);
|
||||||
|
|
||||||
|
/** Add a listener for this command end of execution
|
||||||
|
*
|
||||||
|
* @param listener the listener */
|
||||||
|
void addInterruptionListener(InterruptionListener listener);
|
||||||
|
|
||||||
|
/** Remove a listener of this command end of execution
|
||||||
|
*
|
||||||
|
* @param listener the listener */
|
||||||
|
void rmInterruptionListener(InterruptionListener listener);
|
||||||
|
}
|
||||||
94
gclc/src/main/java/fr/bigeon/gclc/proc/TaskPool.java
Normal file
94
gclc/src/main/java/fr/bigeon/gclc/proc/TaskPool.java
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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.proc.TaskPool.java
|
||||||
|
* Created on: May 10, 2017
|
||||||
|
*/
|
||||||
|
package fr.bigeon.gclc.proc;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/** <p>
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon */
|
||||||
|
public class TaskPool {
|
||||||
|
private final Map<String, Task> running = new HashMap<>();
|
||||||
|
private int count = 0;
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
|
public void add(final Task cmd) {
|
||||||
|
final String pid = getPID();
|
||||||
|
synchronized (lock) {
|
||||||
|
running.put(pid, cmd);
|
||||||
|
}
|
||||||
|
cmd.addInterruptionListener(new InterruptionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void interrupted() {
|
||||||
|
synchronized (lock) {
|
||||||
|
running.remove(pid);
|
||||||
|
count = Math.min(count, Integer.parseInt(pid));
|
||||||
|
}
|
||||||
|
cmd.rmInterruptionListener(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the process id */
|
||||||
|
private String getPID() {
|
||||||
|
synchronized (lock) {
|
||||||
|
String pid;
|
||||||
|
do {
|
||||||
|
pid = Integer.toString(count++);
|
||||||
|
} while (running.containsKey(pid));
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task get(String pid) {
|
||||||
|
synchronized (lock) {
|
||||||
|
return running.get(pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the pids */
|
||||||
|
public Collection<String> getPIDs() {
|
||||||
|
return new HashSet<>(running.keySet());
|
||||||
|
}
|
||||||
|
}
|
||||||
74
gclc/src/main/java/fr/bigeon/gclc/proc/TaskSpawner.java
Normal file
74
gclc/src/main/java/fr/bigeon/gclc/proc/TaskSpawner.java
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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.proc.ProcessList.java
|
||||||
|
* Created on: May 10, 2017
|
||||||
|
*/
|
||||||
|
package fr.bigeon.gclc.proc;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.command.Command;
|
||||||
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class TaskSpawner extends Command {
|
||||||
|
private final TaskPool pool;
|
||||||
|
|
||||||
|
/** @param name the command name
|
||||||
|
* @param pool the pool */
|
||||||
|
public TaskSpawner(String name, TaskPool pool) {
|
||||||
|
super(name);
|
||||||
|
this.pool = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see fr.bigeon.gclc.command.ICommand#execute(java.lang.String[])
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final void execute(String... args) throws CommandRunException {
|
||||||
|
Task task = createTask(args);
|
||||||
|
Thread th = new Thread(task);
|
||||||
|
th.start();
|
||||||
|
pool.add(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param args the arguments */
|
||||||
|
protected abstract Task createTask(String... args);
|
||||||
|
}
|
||||||
@@ -54,14 +54,15 @@ import fr.bigeon.gclc.manager.PipedConsoleManager;
|
|||||||
@SuppressWarnings("javadoc")
|
@SuppressWarnings("javadoc")
|
||||||
public class CommandTestingApplication implements AutoCloseable {
|
public class CommandTestingApplication implements AutoCloseable {
|
||||||
|
|
||||||
private final ConsoleTestApplication application;
|
private final ConsoleApplication application;
|
||||||
private final Thread th;
|
private final Thread th;
|
||||||
private final PipedConsoleManager manager;
|
private final PipedConsoleManager manager;
|
||||||
|
|
||||||
/** @throws IOException if the streams cannot be build */
|
/** @throws IOException if the streams cannot be build */
|
||||||
public CommandTestingApplication() throws IOException {
|
public CommandTestingApplication() throws IOException {
|
||||||
manager = new PipedConsoleManager();
|
manager = new PipedConsoleManager();
|
||||||
application = new ConsoleTestApplication(manager);
|
application = new ConsoleApplication(manager, "", "");
|
||||||
|
new ConsoleTestApplication().attach(application);
|
||||||
th = new Thread(new Runnable() {
|
th = new Thread(new Runnable() {
|
||||||
|
|
||||||
@SuppressWarnings("synthetic-access")
|
@SuppressWarnings("synthetic-access")
|
||||||
@@ -93,7 +94,7 @@ public class CommandTestingApplication implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return the application */
|
/** @return the application */
|
||||||
public ConsoleTestApplication getApplication() {
|
public ConsoleApplication getApplication() {
|
||||||
return application;
|
return application;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import static org.junit.Assert.assertFalse;
|
|||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -55,7 +56,6 @@ import fr.bigeon.gclc.exception.CommandRunExceptionType;
|
|||||||
import fr.bigeon.gclc.exception.InvalidCommandName;
|
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||||
import fr.bigeon.gclc.i18n.Messages;
|
import fr.bigeon.gclc.i18n.Messages;
|
||||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
import fr.bigeon.gclc.manager.ConsoleManager;
|
||||||
import fr.bigeon.gclc.manager.SystemConsoleManager;
|
|
||||||
import fr.bigeon.gclc.manager.PipedConsoleManager;
|
import fr.bigeon.gclc.manager.PipedConsoleManager;
|
||||||
|
|
||||||
/** Test class for ConsoleApplication
|
/** Test class for ConsoleApplication
|
||||||
@@ -70,9 +70,14 @@ public class ConsoleApplicationTest {
|
|||||||
/** Test the base of a console application */
|
/** Test the base of a console application */
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
ConsoleTestApplication app = new ConsoleTestApplication(
|
|
||||||
new SystemConsoleManager());
|
try (PipedConsoleManager manager = new PipedConsoleManager()) {
|
||||||
|
ConsoleApplication app = new ConsoleApplication(manager, "", "");
|
||||||
app.exit();
|
app.exit();
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("System Console Manager failed");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -80,7 +85,7 @@ public class ConsoleApplicationTest {
|
|||||||
try (CommandTestingApplication application = new CommandTestingApplication()) {
|
try (CommandTestingApplication application = new CommandTestingApplication()) {
|
||||||
|
|
||||||
// remove welcome
|
// remove welcome
|
||||||
assertEquals(application.getApplication().getHeader(),
|
assertEquals(application.getApplication().header,
|
||||||
application.readNextLine());
|
application.readNextLine());
|
||||||
// Remove first prompt
|
// Remove first prompt
|
||||||
assertNull(application.readNextLine());
|
assertNull(application.readNextLine());
|
||||||
@@ -128,7 +133,7 @@ public class ConsoleApplicationTest {
|
|||||||
|
|
||||||
assertNull(application.readNextLine());
|
assertNull(application.readNextLine());
|
||||||
application.sendCommand("exit");
|
application.sendCommand("exit");
|
||||||
assertEquals(application.getApplication().getFooter(),
|
assertEquals(application.getApplication().footer,
|
||||||
application.readNextLine());
|
application.readNextLine());
|
||||||
assertFalse(application.getApplication().isRunning());
|
assertFalse(application.getApplication().isRunning());
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
@@ -156,7 +161,10 @@ public class ConsoleApplicationTest {
|
|||||||
manager.type("exit");
|
manager.type("exit");
|
||||||
th.join();
|
th.join();
|
||||||
|
|
||||||
} catch (IOException | InvalidCommandName | InterruptedException e) {
|
} catch (IOException | InvalidCommandName |
|
||||||
|
|
||||||
|
InterruptedException e) {
|
||||||
|
|
||||||
assertNull(e);
|
assertNull(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,12 +41,11 @@ import fr.bigeon.gclc.command.ExitCommand;
|
|||||||
import fr.bigeon.gclc.command.HelpExecutor;
|
import fr.bigeon.gclc.command.HelpExecutor;
|
||||||
import fr.bigeon.gclc.exception.CommandRunException;
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
import fr.bigeon.gclc.exception.InvalidCommandName;
|
import fr.bigeon.gclc.exception.InvalidCommandName;
|
||||||
import fr.bigeon.gclc.manager.ConsoleManager;
|
|
||||||
|
|
||||||
/** A test-purpose application
|
/** A test-purpose application
|
||||||
*
|
*
|
||||||
* @author Emmanuel Bigeon */
|
* @author Emmanuel Bigeon */
|
||||||
public class ConsoleTestApplication extends ConsoleApplication {
|
public class ConsoleTestApplication implements ApplicationAttachement {
|
||||||
|
|
||||||
/** Exit command */
|
/** Exit command */
|
||||||
public static final String EXIT = "exit"; //$NON-NLS-1$
|
public static final String EXIT = "exit"; //$NON-NLS-1$
|
||||||
@@ -54,14 +53,14 @@ public class ConsoleTestApplication extends ConsoleApplication {
|
|||||||
protected static final long TWO_SECONDS = 2000;
|
protected static final long TWO_SECONDS = 2000;
|
||||||
|
|
||||||
/** @param manager the manager */
|
/** @param manager the manager */
|
||||||
|
@Override
|
||||||
@SuppressWarnings("nls")
|
@SuppressWarnings("nls")
|
||||||
public ConsoleTestApplication(final ConsoleManager manager) {
|
public void attach(final ConsoleApplication application) {
|
||||||
super(manager, "Welcome to the test application. Type help or test.",
|
|
||||||
"See you");
|
|
||||||
try {
|
try {
|
||||||
add(new ExitCommand(EXIT, this));
|
application.add(new ExitCommand(EXIT, application));
|
||||||
add(new HelpExecutor("help", manager, this.getRoot()));
|
application.add(new HelpExecutor("help", application.manager,
|
||||||
add(new Command("test") {
|
application.root));
|
||||||
|
application.add(new Command("test") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String tip() {
|
public String tip() {
|
||||||
@@ -71,14 +70,14 @@ public class ConsoleTestApplication extends ConsoleApplication {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(String... args) throws CommandRunException {
|
public void execute(String... args) throws CommandRunException {
|
||||||
try {
|
try {
|
||||||
manager.println("Test command ran fine");
|
application.manager.println("Test command ran fine");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CommandRunException("manager closed", e,
|
throw new CommandRunException("manager closed", e,
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
add(new Command("long") {
|
application.add(new Command("long") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String tip() {
|
public String tip() {
|
||||||
@@ -88,9 +87,9 @@ public class ConsoleTestApplication extends ConsoleApplication {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(String... args) throws CommandRunException {
|
public void execute(String... args) throws CommandRunException {
|
||||||
try {
|
try {
|
||||||
manager.println("Waita minute");
|
application.manager.println("Waita minute");
|
||||||
Thread.sleep(TWO_SECONDS);
|
Thread.sleep(TWO_SECONDS);
|
||||||
manager.println("done!");
|
application.manager.println("done!");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CommandRunException("manager closed", e,
|
throw new CommandRunException("manager closed", e,
|
||||||
this);
|
this);
|
||||||
@@ -100,7 +99,7 @@ public class ConsoleTestApplication extends ConsoleApplication {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
add(new Command("failingCmd") {
|
application.add(new Command("failingCmd") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String tip() {
|
public String tip() {
|
||||||
|
|||||||
@@ -578,9 +578,16 @@ public class ParametrizedCommandTest {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
assertEquals(str1, test.readNextLine());
|
assertEquals("value of " + str1 + "? ",
|
||||||
|
test.readNextLine());
|
||||||
test.type("");
|
test.type("");
|
||||||
assertEquals(str1, test.readNextLine());
|
assertEquals(
|
||||||
|
"value of " + str1 + "? (cannot be empty) ",
|
||||||
|
test.readNextLine());
|
||||||
|
test.type("");
|
||||||
|
assertEquals(
|
||||||
|
"value of " + str1 + "? (cannot be empty) ",
|
||||||
|
test.readNextLine());
|
||||||
test.type(str2);
|
test.type(str2);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
assertNull(e);
|
assertNull(e);
|
||||||
@@ -598,7 +605,8 @@ public class ParametrizedCommandTest {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
assertEquals(str1, test.readNextLine());
|
assertEquals("value of " + str1 + "? ",
|
||||||
|
test.readNextLine());
|
||||||
test.type(str2);
|
test.type(str2);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
assertNull(e);
|
assertNull(e);
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import java.nio.charset.Charset;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import fr.bigeon.gclc.ConsoleApplication;
|
||||||
import fr.bigeon.gclc.ConsoleTestApplication;
|
import fr.bigeon.gclc.ConsoleTestApplication;
|
||||||
import fr.bigeon.gclc.exception.CommandRunException;
|
import fr.bigeon.gclc.exception.CommandRunException;
|
||||||
import fr.bigeon.gclc.exception.CommandRunExceptionType;
|
import fr.bigeon.gclc.exception.CommandRunExceptionType;
|
||||||
@@ -75,8 +76,9 @@ public class ScriptExecutionTest {
|
|||||||
assertNotNull(e2);
|
assertNotNull(e2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ConsoleTestApplication app = new ConsoleTestApplication(
|
ConsoleApplication app = new ConsoleApplication(
|
||||||
test);
|
test, "", "");
|
||||||
|
new ConsoleTestApplication().attach(app);
|
||||||
ScriptExecution exec = new ScriptExecution("script", app, "#", //$NON-NLS-1$ //$NON-NLS-2$
|
ScriptExecution exec = new ScriptExecution("script", app, "#", //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
Charset.forName("UTF-8"));
|
Charset.forName("UTF-8"));
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* 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.manager.ReadingRunnableTest.java
|
||||||
|
* Created on: Dec 6, 2016
|
||||||
|
*/
|
||||||
|
package fr.bigeon.gclc.manager;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.PipedInputStream;
|
||||||
|
import java.io.PipedOutputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/** <p>
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author Emmanuel Bigeon */
|
||||||
|
public class ReadingRunnableTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp() {}
|
||||||
|
|
||||||
|
/** Test method for
|
||||||
|
* {@link fr.bigeon.gclc.manager.ReadingRunnable#getMessage()}. */
|
||||||
|
@Test
|
||||||
|
public final void testGetMessage() {
|
||||||
|
BufferedReader reader = null;
|
||||||
|
ReadingRunnable runnable = new ReadingRunnable(reader);
|
||||||
|
runnable.setRunning(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
runnable.getMessage();
|
||||||
|
fail("reading from closed runnable");
|
||||||
|
} catch (IOException e) {
|
||||||
|
assertNotNull(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Test method for
|
||||||
|
* {@link fr.bigeon.gclc.manager.ReadingRunnable#hasMessage()}. */
|
||||||
|
@Test
|
||||||
|
public final void testHasMessage() {
|
||||||
|
|
||||||
|
BufferedReader reader = null;
|
||||||
|
ReadingRunnable runnable = new ReadingRunnable(reader);
|
||||||
|
runnable.setRunning(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
runnable.getMessage();
|
||||||
|
fail("reading from closed runnable");
|
||||||
|
} catch (IOException e) {
|
||||||
|
assertNotNull(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Test method for
|
||||||
|
* {@link fr.bigeon.gclc.manager.ReadingRunnable#getWaitForDelivery(java.lang.String)}.
|
||||||
|
*
|
||||||
|
* @throws InterruptedException */
|
||||||
|
@Test
|
||||||
|
public final void testGetWaitForDelivery() throws InterruptedException {
|
||||||
|
try (PipedOutputStream out = new PipedOutputStream();
|
||||||
|
InputStream piped = new PipedInputStream(out);
|
||||||
|
BufferedReader reader = new BufferedReader(
|
||||||
|
new InputStreamReader(piped, "UTF-8"))) {
|
||||||
|
final ReadingRunnable runnable = new ReadingRunnable(reader);
|
||||||
|
Thread th0 = new Thread(runnable, "read");
|
||||||
|
th0.start();
|
||||||
|
Thread th = runnable.getWaitForDelivery("msg");
|
||||||
|
|
||||||
|
out.write(Charset.forName("UTF-8")
|
||||||
|
.encode("msg" + System.lineSeparator()).array());
|
||||||
|
|
||||||
|
Thread th2 = new Thread(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
runnable.getMessage();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "get");
|
||||||
|
th2.start();
|
||||||
|
try {
|
||||||
|
th.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
assertNull(e);
|
||||||
|
}
|
||||||
|
runnable.setRunning(false);
|
||||||
|
out.close();
|
||||||
|
} catch (IOException e1) {
|
||||||
|
assertNull(e1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -65,13 +65,12 @@ public class SystemConsoleManagerTest {
|
|||||||
@Test
|
@Test
|
||||||
public final void testPrompt() {
|
public final void testPrompt() {
|
||||||
|
|
||||||
try {
|
final String test = "test";
|
||||||
PipedOutputStream outStream = new PipedOutputStream();
|
try (PipedOutputStream outStream = new PipedOutputStream();
|
||||||
InputStream in = new PipedInputStream(outStream);
|
InputStream in = new PipedInputStream(outStream);
|
||||||
final PrintStream out = new PrintStream(outStream);
|
final PrintStream out = new PrintStream(outStream);
|
||||||
final String test = "test";
|
|
||||||
SystemConsoleManager manager = new SystemConsoleManager(System.out,
|
SystemConsoleManager manager = new SystemConsoleManager(System.out,
|
||||||
in, Charset.forName("UTF-8"));
|
in, Charset.forName("UTF-8"))) {
|
||||||
|
|
||||||
Thread th = new Thread(new Runnable() {
|
Thread th = new Thread(new Runnable() {
|
||||||
|
|
||||||
@@ -95,10 +94,18 @@ public class SystemConsoleManagerTest {
|
|||||||
* {@link fr.bigeon.gclc.manager.SystemConsoleManager#setPrompt(java.lang.String)}. */
|
* {@link fr.bigeon.gclc.manager.SystemConsoleManager#setPrompt(java.lang.String)}. */
|
||||||
@Test
|
@Test
|
||||||
public final void testSetPrompt() {
|
public final void testSetPrompt() {
|
||||||
SystemConsoleManager manager = new SystemConsoleManager();
|
try (PipedOutputStream outStream = new PipedOutputStream();
|
||||||
|
InputStream in = new PipedInputStream(outStream);
|
||||||
|
final PrintStream out = new PrintStream(outStream);
|
||||||
|
SystemConsoleManager manager = new SystemConsoleManager(System.out,
|
||||||
|
in, Charset.forName("UTF-8"))) {
|
||||||
|
|
||||||
String prt = "++";
|
String prt = "++";
|
||||||
manager.setPrompt(prt);
|
manager.setPrompt(prt);
|
||||||
assertEquals(prt, manager.getPrompt());
|
assertEquals(prt, manager.getPrompt());
|
||||||
|
} catch (IOException e) {
|
||||||
|
assertNull(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Test method for
|
/** Test method for
|
||||||
|
|||||||
Reference in New Issue
Block a user