From bcbda1a1adef0a7848e87601a5dbf1741a63d1cb Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Fri, 10 Jul 2015 13:59:20 +0200 Subject: [PATCH] Move ClientHello command into its own class --- .../fcp/quelaton/ClientHelloImpl.java | 88 ++++++++++++++++++++++ .../fcp/quelaton/DefaultFcpClient.java | 43 +---------- .../net/pterodactylus/fcp/quelaton/Executable.java | 15 ++++ 3 files changed, 105 insertions(+), 41 deletions(-) create mode 100644 src/main/java/net/pterodactylus/fcp/quelaton/ClientHelloImpl.java create mode 100644 src/main/java/net/pterodactylus/fcp/quelaton/Executable.java diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/ClientHelloImpl.java b/src/main/java/net/pterodactylus/fcp/quelaton/ClientHelloImpl.java new file mode 100644 index 0000000..a87cd30 --- /dev/null +++ b/src/main/java/net/pterodactylus/fcp/quelaton/ClientHelloImpl.java @@ -0,0 +1,88 @@ +package net.pterodactylus.fcp.quelaton; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import net.pterodactylus.fcp.ClientHello; +import net.pterodactylus.fcp.CloseConnectionDuplicateClientName; +import net.pterodactylus.fcp.FcpConnection; +import net.pterodactylus.fcp.NodeHello; + +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; + +/** + * Internal ClientHello implementation based on {@link FcpReplySequence}. + * + * @author David ‘Bombe’ Roden + */ +public class ClientHelloImpl { + + private final ListeningExecutorService threadPool; + private final String hostname; + private final int port; + private final AtomicReference clientName = new AtomicReference<>(); + + public ClientHelloImpl(ExecutorService threadPool, String hostname, int port) { + this.threadPool = MoreExecutors.listeningDecorator(threadPool); + this.hostname = hostname; + this.port = port; + } + + public Executable withName(String name) { + clientName.set(name); + return this::execute; + } + + private ListenableFuture execute() { + return threadPool.submit(() -> establishConnection()); + } + + private FcpConnection establishConnection() throws IOException { + FcpConnection connection = new FcpConnection(hostname, port); + connection.connect(); + FcpReplySequence nodeHelloSequence = new ClientHelloReplySequence(connection); + ClientHello clientHello = new ClientHello(clientName.get(), "2.0"); + try { + nodeHelloSequence.send(clientHello).get(); + } catch (InterruptedException | ExecutionException e) { + connection.close(); + throw new IOException(String.format("Could not connect to %s:%d.", hostname, port), e); + } + return connection; + } + + private class ClientHelloReplySequence extends FcpReplySequence { + + private final AtomicReference receivedNodeHello; + private final AtomicBoolean receivedClosed; + + public ClientHelloReplySequence(FcpConnection connection) { + super(ClientHelloImpl.this.threadPool, connection); + receivedNodeHello = new AtomicReference<>(); + receivedClosed = new AtomicBoolean(); + } + + @Override + protected boolean isFinished() { + return receivedNodeHello.get() != null || receivedClosed.get(); + } + + @Override + protected void consumeNodeHello(NodeHello nodeHello) { + receivedNodeHello.set(nodeHello); + } + + @Override + protected void consumeCloseConnectionDuplicateClientName( + CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) { + receivedClosed.set(true); + } + + } + +} diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/DefaultFcpClient.java b/src/main/java/net/pterodactylus/fcp/quelaton/DefaultFcpClient.java index 1d7c02c..0693e1c 100644 --- a/src/main/java/net/pterodactylus/fcp/quelaton/DefaultFcpClient.java +++ b/src/main/java/net/pterodactylus/fcp/quelaton/DefaultFcpClient.java @@ -3,14 +3,10 @@ package net.pterodactylus.fcp.quelaton; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; -import net.pterodactylus.fcp.ClientHello; -import net.pterodactylus.fcp.CloseConnectionDuplicateClientName; import net.pterodactylus.fcp.FcpConnection; -import net.pterodactylus.fcp.NodeHello; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; @@ -46,17 +42,11 @@ public class DefaultFcpClient implements FcpClient { } private FcpConnection createConnection() throws IOException { - FcpConnection connection = new FcpConnection(hostname, port); - connection.connect(); - FcpReplySequence nodeHelloSequence = new ClientHelloReplySequence(connection); - ClientHello clientHello = new ClientHello(clientName.get(), "2.0"); try { - nodeHelloSequence.send(clientHello).get(); + return new ClientHelloImpl(threadPool, hostname, port).withName(clientName.get()).execute().get(); } catch (InterruptedException | ExecutionException e) { - connection.close(); - throw new IOException(String.format("Could not connect to %s:%d.", hostname, port), e); + throw new IOException(e); } - return connection; } @Override @@ -79,34 +69,5 @@ public class DefaultFcpClient implements FcpClient { return new ListPeersCommandImpl(threadPool, this::connect); } - private class ClientHelloReplySequence extends FcpReplySequence { - - private final AtomicReference receivedNodeHello; - private final AtomicBoolean receivedClosed; - - public ClientHelloReplySequence(FcpConnection connection) { - super(DefaultFcpClient.this.threadPool, connection); - receivedNodeHello = new AtomicReference<>(); - receivedClosed = new AtomicBoolean(); - } - - @Override - protected boolean isFinished() { - return receivedNodeHello.get() != null || receivedClosed.get(); - } - - @Override - protected void consumeNodeHello(NodeHello nodeHello) { - receivedNodeHello.set(nodeHello); - } - - @Override - protected void consumeCloseConnectionDuplicateClientName( - CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) { - receivedClosed.set(true); - } - - } - } diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/Executable.java b/src/main/java/net/pterodactylus/fcp/quelaton/Executable.java new file mode 100644 index 0000000..e410515 --- /dev/null +++ b/src/main/java/net/pterodactylus/fcp/quelaton/Executable.java @@ -0,0 +1,15 @@ +package net.pterodactylus.fcp.quelaton; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Terminal operation for all FCP commands. + * + * @author David ‘Bombe’ Roden + */ +@FunctionalInterface +public interface Executable { + + ListenableFuture execute(); + +} -- 2.7.4