Move ClientHello command into its own class
authorDavid ‘Bombe’ Roden <bombe@freenetproject.org>
Fri, 10 Jul 2015 11:59:20 +0000 (13:59 +0200)
committerDavid ‘Bombe’ Roden <bombe@freenetproject.org>
Fri, 10 Jul 2015 11:59:46 +0000 (13:59 +0200)
src/main/java/net/pterodactylus/fcp/quelaton/ClientHelloImpl.java [new file with mode: 0644]
src/main/java/net/pterodactylus/fcp/quelaton/DefaultFcpClient.java
src/main/java/net/pterodactylus/fcp/quelaton/Executable.java [new file with mode: 0644]

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 (file)
index 0000000..a87cd30
--- /dev/null
@@ -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 <code>ClientHello</code> implementation based on {@link FcpReplySequence}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ClientHelloImpl {
+
+       private final ListeningExecutorService threadPool;
+       private final String hostname;
+       private final int port;
+       private final AtomicReference<String> clientName = new AtomicReference<>();
+
+       public ClientHelloImpl(ExecutorService threadPool, String hostname, int port) {
+               this.threadPool = MoreExecutors.listeningDecorator(threadPool);
+               this.hostname = hostname;
+               this.port = port;
+       }
+
+       public Executable<FcpConnection> withName(String name) {
+               clientName.set(name);
+               return this::execute;
+       }
+
+       private ListenableFuture<FcpConnection> 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<Void> {
+
+               private final AtomicReference<NodeHello> 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);
+               }
+
+       }
+
+}
index 1d7c02c..0693e1c 100644 (file)
@@ -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<Void> {
-
-               private final AtomicReference<NodeHello> 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 (file)
index 0000000..e410515
--- /dev/null
@@ -0,0 +1,15 @@
+package net.pterodactylus.fcp.quelaton;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Terminal operation for all FCP commands.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+@FunctionalInterface
+public interface Executable<R> {
+
+       ListenableFuture<R> execute();
+
+}