diff --git a/gclc-socket/src/main/java/net/bigeon/gclc/socket/DisconnexionListener.java b/gclc-socket/src/main/java/net/bigeon/gclc/socket/DisconnexionListener.java new file mode 100644 index 0000000..227ee64 --- /dev/null +++ b/gclc-socket/src/main/java/net/bigeon/gclc/socket/DisconnexionListener.java @@ -0,0 +1,14 @@ +/** + * + */ +package net.bigeon.gclc.socket; + +/** Interface for listener of brutal disconnection from a pluggable + * input/output. + * + * @author Emmanuel Bigeon */ +@FunctionalInterface +public interface DisconnexionListener { + /** Indicate a brutal disconnection */ + void disconnected(); +} diff --git a/gclc-socket/src/main/java/net/bigeon/gclc/socket/PluggableConsoleInput.java b/gclc-socket/src/main/java/net/bigeon/gclc/socket/PluggableConsoleInput.java index f857405..212d103 100644 --- a/gclc-socket/src/main/java/net/bigeon/gclc/socket/PluggableConsoleInput.java +++ b/gclc-socket/src/main/java/net/bigeon/gclc/socket/PluggableConsoleInput.java @@ -44,6 +44,8 @@ import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.io.PrintStream; import java.nio.charset.StandardCharsets; +import java.util.HashSet; +import java.util.Set; import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; @@ -88,6 +90,8 @@ public final class PluggableConsoleInput implements ConsoleInput { /** The output for hints. */ private PrintStream output; + private final Set listeners = new HashSet<>(); + // Locks /** The lock for connexion and disconnexion of actual streams. */ private final Object connexionLock = new Object(); @@ -287,11 +291,23 @@ public final class PluggableConsoleInput implements ConsoleInput { throw e; } catch (final IOException e) { LOGGER.log(Level.INFO, "Communication was abrubptly interrupted", e); - disconnect(); + brutalDisconnection(); } } connexionLock.wait(connexionTimeout); } return null; } + + /** + * + */ + private void brutalDisconnection() { + // clean up the disconnection + disconnect(); + // notify listeners + for (final DisconnexionListener listener : listeners) { + listener.disconnected(); + } + } } diff --git a/gclc-socket/src/main/java/net/bigeon/gclc/socket/RemoteDisconnectCommand.java b/gclc-socket/src/main/java/net/bigeon/gclc/socket/RemoteDisconnectCommand.java index a7acfdd..501030d 100644 --- a/gclc-socket/src/main/java/net/bigeon/gclc/socket/RemoteDisconnectCommand.java +++ b/gclc-socket/src/main/java/net/bigeon/gclc/socket/RemoteDisconnectCommand.java @@ -50,7 +50,10 @@ import net.bigeon.gclc.manager.ConsoleOutput; /** A {@link Command} to disconnect elements from a {@link ConnexionManager}. * * @author Emmanuel Bigeon - * @param the type of connected object */ + * @param the type of connected object + * @deprecated since 1.1.17, this has been moved to + * {@link RemoteDisconnectCommand}. */ +@Deprecated public final class RemoteDisconnectCommand extends Command { /** The connexion manager. */ diff --git a/gclc-socket/src/main/java/net/bigeon/gclc/socket/cmd/ConnexionListCommand.java b/gclc-socket/src/main/java/net/bigeon/gclc/socket/cmd/ConnexionListCommand.java new file mode 100644 index 0000000..eb342f9 --- /dev/null +++ b/gclc-socket/src/main/java/net/bigeon/gclc/socket/cmd/ConnexionListCommand.java @@ -0,0 +1,98 @@ +/** + * gclc-socket:net.bigeon.gclc.socket.RemoteDisconnectCommand.java + * Created on: Nov 18, 2017 + */ +package net.bigeon.gclc.socket.cmd; + +/*- + * #%L + * GCLC Socket + * %% + * Copyright (C) 2016 - 2018 Bigeon + * %% + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + * #L% + */ +import java.io.IOException; +import java.util.Collection; + +import net.bigeon.gclc.command.Command; +import net.bigeon.gclc.exception.CommandRunException; +import net.bigeon.gclc.exception.CommandRunExceptionType; +import net.bigeon.gclc.manager.ConsoleInput; +import net.bigeon.gclc.manager.ConsoleOutput; +import net.bigeon.gclc.socket.ConnexionManager; + +/** A {@link Command} to disconnect elements from a {@link ConnexionManager}. + * + * @author Emmanuel Bigeon + * @param the type of connected object */ +public final class ConnexionListCommand extends Command { + + /** The connexion manager. */ + private final ConnexionManager manager; + + /** Create the connexion listing command. + * + * @param name the command name + * @param manager the manager */ + public ConnexionListCommand(final String name, final ConnexionManager manager) { + super(name); + this.manager = manager; + } + + /* (non-Javadoc) + * @see fr.bigeon.gclc.command.ICommand#execute(fr.bigeon.gclc.manager. + * ConsoleOutput, fr.bigeon.gclc.manager.ConsoleInput, java.lang.String[]) */ + @Override + public void execute(final ConsoleOutput out, final ConsoleInput in, + final String... args) throws CommandRunException { + final Collection coll = manager.getConnected(); + try { + for (final String string : coll) { + out.println(string); + } + } catch (final IOException e) { + throw new CommandRunException(CommandRunExceptionType.INTERACTION, + "User cannot be notified", e); + } + } + + /* (non-Javadoc) + * @see fr.bigeon.gclc.command.ICommand#tip() */ + @Override + public String tip() { + return "List current connexions."; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see fr.bigeon.gclc.command.Command#usageDetail() */ + @Override + protected String usageDetail() { + return ""; + } +} diff --git a/gclc-socket/src/main/java/net/bigeon/gclc/socket/cmd/RemoteDisconnectCommand.java b/gclc-socket/src/main/java/net/bigeon/gclc/socket/cmd/RemoteDisconnectCommand.java new file mode 100644 index 0000000..c6f7ece --- /dev/null +++ b/gclc-socket/src/main/java/net/bigeon/gclc/socket/cmd/RemoteDisconnectCommand.java @@ -0,0 +1,130 @@ +/** + * gclc-socket:net.bigeon.gclc.socket.RemoteDisconnectCommand.java + * Created on: Nov 18, 2017 + */ +package net.bigeon.gclc.socket.cmd; + +/*- + * #%L + * GCLC Socket + * %% + * Copyright (C) 2016 - 2018 Bigeon + * %% + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + * #L% + */ +import java.io.IOException; +import java.text.MessageFormat; +import java.util.Collection; + +import net.bigeon.gclc.command.Command; +import net.bigeon.gclc.exception.CommandRunException; +import net.bigeon.gclc.exception.CommandRunExceptionType; +import net.bigeon.gclc.manager.ConsoleInput; +import net.bigeon.gclc.manager.ConsoleOutput; +import net.bigeon.gclc.socket.ConnexionManager; + +/** A {@link Command} to disconnect elements from a {@link ConnexionManager}. + * + * @author Emmanuel Bigeon + * @param the type of connected object */ +public final class RemoteDisconnectCommand extends Command { + + /** The connexion manager. */ + private final ConnexionManager manager; + /** If all connexion should be disconnected when no argument have been + * specified. */ + private final boolean all; + + /** Create the disconnection command. + * + * @param name the command name + * @param manager the manager + * @param all if all elements should be disconnected when no argument is + * provided */ + public RemoteDisconnectCommand(final String name, final ConnexionManager manager, + final boolean all) { + super(name); + this.manager = manager; + this.all = all; + } + + /* (non-Javadoc) + * @see fr.bigeon.gclc.command.ICommand#execute(fr.bigeon.gclc.manager. + * ConsoleOutput, fr.bigeon.gclc.manager.ConsoleInput, java.lang.String[]) */ + @Override + public void execute(final ConsoleOutput out, final ConsoleInput in, + final String... args) throws CommandRunException { + if (args.length == 0 && all) { + final Collection coll = manager.getConnected(); + for (final String string : coll) { + manager.disconnect(string); + } + } + for (final String string : args) { + if (manager.isConnected(string)) { + manager.disconnect(string); + } else { + print(out, + MessageFormat.format("[WARNING] {0} is not connected", string)); //$NON-NLS-1$ + } + } + } + + /** Print a message if the output is defined. + * + * @param out the output + * @param string the message + * @throws CommandRunException if the output exists but cannot be printed to */ + private static void print(final ConsoleOutput out, final String string) + throws CommandRunException { + if (out != null) { + try { + out.println(string); + } catch (final IOException e) { + throw new CommandRunException(CommandRunExceptionType.INTERACTION, + "Unable to print to existing output", e); //$NON-NLS-1$ + } + } + } + + /* (non-Javadoc) + * @see fr.bigeon.gclc.command.ICommand#tip() */ + @Override + public String tip() { + return "Close a connexion."; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see fr.bigeon.gclc.command.Command#usageDetail() */ + @Override + protected String usageDetail() { + return MessageFormat.format( + " If arguments are provided the corresponding connexions are closed, otherwise\n{0} are.", + all ? "all connexions" : "none"); + } +} diff --git a/gclc-socket/src/main/java/net/bigeon/gclc/socket/cmd/package-info.java b/gclc-socket/src/main/java/net/bigeon/gclc/socket/cmd/package-info.java new file mode 100644 index 0000000..137740e --- /dev/null +++ b/gclc-socket/src/main/java/net/bigeon/gclc/socket/cmd/package-info.java @@ -0,0 +1,8 @@ +/** + * + */ +/** + * @author Emmanuel Bigeon + * + */ +package net.bigeon.gclc.socket.cmd;