d0bf14a37b965571a8c487dba084a209e34e042b
[jFCPlib.git] / src / main / java / net / pterodactylus / fcp / quelaton / DefaultFcpClient.java
1 package net.pterodactylus.fcp.quelaton;
2
3 import java.io.IOException;
4 import java.util.concurrent.ExecutionException;
5 import java.util.concurrent.ExecutorService;
6 import java.util.concurrent.atomic.AtomicReference;
7 import java.util.function.Supplier;
8
9 import net.pterodactylus.fcp.FcpConnection;
10
11 import com.google.common.util.concurrent.ListeningExecutorService;
12 import com.google.common.util.concurrent.MoreExecutors;
13
14 /**
15  * Default {@link FcpClient} implementation.
16  *
17  * @author <a href="bombe@freenetproject.org">David ‘Bombe’ Roden</a>
18  */
19 public class DefaultFcpClient implements FcpClient {
20
21         private final ListeningExecutorService threadPool;
22         private final String hostname;
23         private final int port;
24         private final AtomicReference<FcpConnection> fcpConnection = new AtomicReference<>();
25         private final Supplier<String> clientName;
26         private final ActiveSubscriptions activeSubscriptions = new ActiveSubscriptions(this::unsubscribeUsk);
27
28         public DefaultFcpClient(ExecutorService threadPool, String hostname, int port, Supplier<String> clientName) {
29                 this.threadPool = MoreExecutors.listeningDecorator(threadPool);
30                 this.hostname = hostname;
31                 this.port = port;
32                 this.clientName = clientName;
33         }
34
35         private FcpConnection connect() throws IOException {
36                 FcpConnection fcpConnection = this.fcpConnection.get();
37                 if ((fcpConnection != null) && !fcpConnection.isClosed()) {
38                         return fcpConnection;
39                 }
40                 fcpConnection = createConnection();
41                 this.fcpConnection.set(fcpConnection);
42                 try {
43                         activeSubscriptions.renew(fcpConnection::addFcpListener, this::subscribeUsk);
44                 } catch (InterruptedException | ExecutionException e) {
45                         throw new IOException(e);
46                 }
47                 return fcpConnection;
48         }
49
50         private FcpConnection createConnection() throws IOException {
51                 try {
52                         return new ClientHelloImpl(threadPool, hostname, port).withName(clientName.get()).execute().get();
53                 } catch (InterruptedException | ExecutionException e) {
54                         throw new IOException(e);
55                 }
56         }
57
58         @Override
59         public GetNodeCommand getNode() {
60                 return new GetNodeCommandImpl(threadPool, this::connect);
61         }
62
63         @Override
64         public GetConfigCommand getConfig() {
65                 return new GetConfigCommandImpl(threadPool, this::connect);
66         }
67
68         @Override
69         public ModifyConfigCommand modifyConfig() {
70                 return new ModifyConfigCommandImpl(threadPool, this::connect);
71         }
72
73         @Override
74         public GenerateKeypairCommand generateKeypair() {
75                 return new GenerateKeypairCommandImpl(threadPool, this::connect);
76         }
77
78         @Override
79         public ClientGetCommand clientGet() {
80                 return new ClientGetCommandImpl(threadPool, this::connect);
81         }
82
83         @Override
84         public ClientPutCommand clientPut() {
85                 return new ClientPutCommandImpl(threadPool, this::connect);
86         }
87
88         @Override
89         public ListPeerCommand listPeer() {
90                 return new ListPeerCommandImpl(threadPool, this::connect);
91         }
92
93         @Override
94         public ListPeersCommand listPeers() {
95                 return new ListPeersCommandImpl(threadPool, this::connect);
96         }
97
98         @Override
99         public AddPeerCommand addPeer() {
100                 return new AddPeerCommandImpl(threadPool, this::connect);
101         }
102
103         @Override
104         public ModifyPeerCommand modifyPeer() {
105                 return new ModifyPeerCommandImpl(threadPool, this::connect);
106         }
107
108         @Override
109         public RemovePeerCommand removePeer() {
110                 return new RemovePeerCommandImpl(threadPool, this::connect);
111         }
112
113         @Override
114         public ListPeerNotesCommand listPeerNotes() {
115                 return new ListPeerNotesCommandImpl(threadPool, this::connect);
116         }
117
118         @Override
119         public ModifyPeerNoteCommand modifyPeerNote() {
120                 return new ModifyPeerNoteCommandImpl(threadPool, this::connect);
121         }
122
123         @Override
124         public LoadPluginCommand loadPlugin() {
125                 return new LoadPluginCommandImpl(threadPool, this::connect);
126         }
127
128         @Override
129         public ReloadPluginCommand reloadPlugin() {
130                 return new ReloadPluginCommandImpl(threadPool, this::connect);
131         }
132
133         @Override
134         public RemovePluginCommand removePlugin() {
135                 return new RemovePluginCommandImpl(threadPool, this::connect);
136         }
137
138         @Override
139         public GetPluginInfoCommand getPluginInfo() {
140                 return new GetPluginInfoCommandImpl(threadPool, this::connect);
141         }
142
143         @Override
144         public SubscribeUskCommand subscribeUsk() {
145                 return new SubscribeUskCommandImpl(threadPool, this::connect, activeSubscriptions);
146         }
147
148         private UnsubscribeUskCommand unsubscribeUsk() {
149                 return new UnsubscribeUskCommandImpl(threadPool, this::connect);
150         }
151
152 }
153