2 * fcplib - HighLevelClient.java -
3 * Copyright © 2008 David Roden
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 package net.pterodactylus.fcp.highlevel;
22 import java.io.BufferedReader;
24 import java.io.FileReader;
25 import java.io.FileWriter;
26 import java.io.IOException;
27 import java.net.InetAddress;
29 import java.net.UnknownHostException;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
35 import java.util.Map.Entry;
36 import java.util.logging.Level;
37 import java.util.logging.Logger;
39 import net.pterodactylus.fcp.AddPeer;
40 import net.pterodactylus.fcp.AllData;
41 import net.pterodactylus.fcp.ClientGet;
42 import net.pterodactylus.fcp.ClientHello;
43 import net.pterodactylus.fcp.CloseConnectionDuplicateClientName;
44 import net.pterodactylus.fcp.ConfigData;
45 import net.pterodactylus.fcp.DataFound;
46 import net.pterodactylus.fcp.EndListPeerNotes;
47 import net.pterodactylus.fcp.EndListPeers;
48 import net.pterodactylus.fcp.EndListPersistentRequests;
49 import net.pterodactylus.fcp.FCPPluginReply;
50 import net.pterodactylus.fcp.FcpConnection;
51 import net.pterodactylus.fcp.FcpListener;
52 import net.pterodactylus.fcp.FcpMessage;
53 import net.pterodactylus.fcp.FcpUtils;
54 import net.pterodactylus.fcp.FinishedCompression;
55 import net.pterodactylus.fcp.GenerateSSK;
56 import net.pterodactylus.fcp.GetFailed;
57 import net.pterodactylus.fcp.IdentifierCollision;
58 import net.pterodactylus.fcp.ListPeers;
59 import net.pterodactylus.fcp.ListPersistentRequests;
60 import net.pterodactylus.fcp.NodeData;
61 import net.pterodactylus.fcp.NodeHello;
62 import net.pterodactylus.fcp.NodeRef;
63 import net.pterodactylus.fcp.Peer;
64 import net.pterodactylus.fcp.PeerNote;
65 import net.pterodactylus.fcp.PeerRemoved;
66 import net.pterodactylus.fcp.PersistentGet;
67 import net.pterodactylus.fcp.PersistentPut;
68 import net.pterodactylus.fcp.PersistentPutDir;
69 import net.pterodactylus.fcp.PersistentRequestModified;
70 import net.pterodactylus.fcp.PersistentRequestRemoved;
71 import net.pterodactylus.fcp.PluginInfo;
72 import net.pterodactylus.fcp.ProtocolError;
73 import net.pterodactylus.fcp.PutFailed;
74 import net.pterodactylus.fcp.PutFetchable;
75 import net.pterodactylus.fcp.PutSuccessful;
76 import net.pterodactylus.fcp.ReturnType;
77 import net.pterodactylus.fcp.SSKKeypair;
78 import net.pterodactylus.fcp.SimpleProgress;
79 import net.pterodactylus.fcp.StartedCompression;
80 import net.pterodactylus.fcp.SubscribedUSKUpdate;
81 import net.pterodactylus.fcp.TestDDAComplete;
82 import net.pterodactylus.fcp.TestDDAReply;
83 import net.pterodactylus.fcp.TestDDARequest;
84 import net.pterodactylus.fcp.TestDDAResponse;
85 import net.pterodactylus.fcp.URIGenerated;
86 import net.pterodactylus.fcp.UnknownNodeIdentifier;
87 import net.pterodactylus.fcp.UnknownPeerNoteType;
88 import net.pterodactylus.fcp.WatchGlobal;
91 * A high-level client that allows simple yet full-featured access to a Freenet
94 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
97 public class HighLevelClient {
100 private static final Logger logger = Logger.getLogger(HighLevelClient.class.getName());
102 /** Object for internal synchronization. */
103 private final Object syncObject = new Object();
105 /** The name of the client. */
106 private final String clientName;
108 /** The address of the node. */
109 private InetAddress address;
111 /** The port number of the node. */
114 /** The FCP connection to the node. */
115 private FcpConnection fcpConnection;
117 /** Listeners for high-level client events. */
118 private List<HighLevelClientListener> highLevelClientListeners = Collections.synchronizedList(new ArrayList<HighLevelClientListener>());
120 /** The listener for the connection. */
121 private HighLevelClientFcpListener highLevelClientFcpListener = new HighLevelClientFcpListener();
123 /** The callback for {@link #connect()}. */
124 private HighLevelCallback<ConnectResult> connectCallback;
126 /** Mapping from request identifiers to callbacks. */
127 private Map<String, HighLevelCallback<KeyGenerationResult>> keyGenerationCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<KeyGenerationResult>>());
129 /** Mapping from request identifier to peer list callbacks. */
130 private Map<String, HighLevelCallback<PeerListResult>> peerListCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerListResult>>());
132 /** Mapping from request identifier to peer callbacks. */
133 private Map<String, HighLevelCallback<PeerResult>> peerCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerResult>>());
135 /** Mapping from directories to DDA callbacks. */
136 private Map<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<DirectDiskAccessResult>>());
138 /** Mapping from request identifiers to download callbacks. */
139 private Map<String, HighLevelProgressCallback<DownloadResult>> downloadCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelProgressCallback<DownloadResult>>());
141 /** The callback for {@link #getRequests()}. */
142 private HighLevelCallback<RequestListResult> requestListCallback;
145 * Creates a new high-level client that connects to a node on
146 * <code>localhost</code>.
149 * The name of the client
150 * @throws UnknownHostException
151 * if the hostname of the node can not be resolved.
153 public HighLevelClient(String clientName) throws UnknownHostException {
154 this(clientName, "localhost");
158 * Creates a new high-level client that connects to a node on the given
162 * The name of the client
164 * The hostname of the node
165 * @throws UnknownHostException
166 * if the hostname of the node can not be resolved.
168 public HighLevelClient(String clientName, String host) throws UnknownHostException {
169 this(clientName, host, FcpConnection.DEFAULT_PORT);
173 * Creates a new high-level client that connects to a node on the given
177 * The name of the client
179 * The hostname of the node
181 * The port number of the node
182 * @throws UnknownHostException
183 * if the hostname of the node can not be resolved.
185 public HighLevelClient(String clientName, String host, int port) throws UnknownHostException {
186 this(clientName, InetAddress.getByName(host), port);
190 * Creates a new high-level client that connects to a node at the given
194 * The name of the client
196 * The address of the node
198 * The port number of the node
200 public HighLevelClient(String clientName, InetAddress address, int port) {
201 this.clientName = clientName;
202 this.address = address;
211 * Adds the given high-level client listener to list of listeners.
213 * @param highLevelClientListener
214 * The listener to add
216 public void addHighLevelClientListener(HighLevelClientListener highLevelClientListener) {
217 highLevelClientListeners.add(highLevelClientListener);
221 * Removes the given high-level client listener from the list of listeners.
223 * @param highLevelClientListener
224 * The listener to remove
226 public void removeHighLevelClientListener(HighLevelClientListener highLevelClientListener) {
227 highLevelClientListeners.remove(highLevelClientListener);
231 * Notifies all listeners that a client has connected.
233 private void fireClientConnected() {
234 for (HighLevelClientListener highLevelClientListener: highLevelClientListeners) {
235 highLevelClientListener.clientConnected(this);
240 * Notifies all listeners that a client has disconnected.
243 * The exception that caused the disconnect, or <code>null</code>
244 * if there was no exception
246 private void fireClientDisconnected(Throwable throwable) {
247 for (HighLevelClientListener highLevelClientListener: highLevelClientListeners) {
248 highLevelClientListener.clientDisconnected(this, throwable);
257 * Returns the FCP connection that backs this high-level client. This method
258 * should be used with care as fiddling around with the FCP connection can
259 * easily break the high-level client if you don’t know what you’re doing!
261 * @return The FCP connection of this client
263 public FcpConnection getFcpConnection() {
264 return fcpConnection;
272 * Connects the client.
274 * @return A callback with a connection result
275 * @throws IOException
276 * if an I/O error occurs communicating with the node
278 public HighLevelCallback<ConnectResult> connect() throws IOException {
279 fcpConnection = new FcpConnection(address, port);
280 fcpConnection.addFcpListener(highLevelClientFcpListener);
281 fcpConnection.connect();
282 ClientHello clientHello = new ClientHello(clientName);
283 connectCallback = new HighLevelCallback<ConnectResult>(new ConnectResult());
284 fcpConnection.sendMessage(clientHello);
285 return connectCallback;
289 * Disconnects the client from the node.
291 public void disconnect() {
296 * Generates a new SSK keypair.
298 * @return A callback with the keypair
299 * @throws IOException
300 * if an I/O error occurs communicating with the node
302 public HighLevelCallback<KeyGenerationResult> generateKey() throws IOException {
303 String identifier = generateIdentifier("generateSSK");
304 GenerateSSK generateSSK = new GenerateSSK(identifier);
305 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = new HighLevelCallback<KeyGenerationResult>(new KeyGenerationResult(identifier));
306 keyGenerationCallbacks.put(identifier, keyGenerationCallback);
307 fcpConnection.sendMessage(generateSSK);
308 return keyGenerationCallback;
312 * Sets whether to watch the global queue.
315 * <code>true</code> to watch the global queue in addition to
316 * the client-local queue, <code>false</code> to only watch the
318 * @throws IOException
319 * if an I/O error occurs communicating with the node
321 public void setWatchGlobal(boolean enabled) throws IOException {
322 WatchGlobal watchGlobal = new WatchGlobal(enabled);
323 fcpConnection.sendMessage(watchGlobal);
327 * Gets a list of all peers from the node.
329 * @return A callback with the peer list
330 * @throws IOException
331 * if an I/O error occurs with the node
333 public HighLevelCallback<PeerListResult> getPeers() throws IOException {
334 String identifier = generateIdentifier("listPeers");
335 ListPeers listPeers = new ListPeers(identifier, true, true);
336 HighLevelCallback<PeerListResult> peerListCallback = new HighLevelCallback<PeerListResult>(new PeerListResult(identifier));
337 peerListCallbacks.put(identifier, peerListCallback);
338 fcpConnection.sendMessage(listPeers);
339 return peerListCallback;
343 * Adds the peer whose noderef is stored in the given file.
346 * The name of the file the peer’s noderef is stored in
347 * @return A peer callback
348 * @throws IOException
349 * if an I/O error occurs communicating with the node
351 public HighLevelCallback<PeerResult> addPeer(String nodeRefFile) throws IOException {
352 String identifier = generateIdentifier("addPeer");
353 AddPeer addPeer = new AddPeer(nodeRefFile);
354 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
355 peerCallbacks.put(identifier, peerCallback);
356 fcpConnection.sendMessage(addPeer);
361 * Adds the peer whose noderef is stored in the given file.
364 * The URL where the peer’s noderef is stored
365 * @return A peer callback
366 * @throws IOException
367 * if an I/O error occurs communicating with the node
369 public HighLevelCallback<PeerResult> addPeer(URL nodeRefURL) throws IOException {
370 String identifier = generateIdentifier("addPeer");
371 AddPeer addPeer = new AddPeer(nodeRefURL);
372 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
373 peerCallbacks.put(identifier, peerCallback);
374 fcpConnection.sendMessage(addPeer);
379 * Adds the peer whose noderef is stored in the given file.
383 * @return A peer callback
384 * @throws IOException
385 * if an I/O error occurs communicating with the node
387 public HighLevelCallback<PeerResult> addPeer(NodeRef nodeRef) throws IOException {
388 String identifier = generateIdentifier("addPeer");
389 AddPeer addPeer = new AddPeer(nodeRef);
390 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
391 peerCallbacks.put(identifier, peerCallback);
392 fcpConnection.sendMessage(addPeer);
397 * Checks whether direct disk access for the given directory is possible.
398 * You have to perform this check before you can upload or download anything
399 * from or the disk directly!
402 * The directory to check
404 * Whether you want to read the given directory
406 * Whether you want to write to the given directory
407 * @return A direct disk access callback
408 * @throws IOException
410 public HighLevelCallback<DirectDiskAccessResult> checkDirectDiskAccess(String directory, boolean wantRead, boolean wantWrite) throws IOException {
411 TestDDARequest testDDARequest = new TestDDARequest(directory, wantRead, wantWrite);
412 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = new HighLevelCallback<DirectDiskAccessResult>(new DirectDiskAccessResult(directory));
413 directDiskAccessCallbacks.put(directory, directDiskAccessCallback);
414 fcpConnection.sendMessage(testDDARequest);
415 return directDiskAccessCallback;
419 * Starts a download. Files can either be download to disk or streamed from
420 * the node. When downloading to disk you have to perform a direct disk
421 * access check for the directory you want to put the downloaded file in!
423 * @see #checkDirectDiskAccess(String, boolean, boolean)
427 * The filename to save the data to, or <code>null</code> to
428 * retrieve the data as InputStream from the
429 * {@link DownloadResult}
431 * Whether to put the download on the global queue
432 * @return A download result
433 * @throws IOException
434 * if an I/O error occurs communicating with the node
436 public HighLevelProgressCallback<DownloadResult> download(String uri, String filename, boolean global) throws IOException {
437 String identifier = generateIdentifier("download");
438 ClientGet clientGet = new ClientGet(uri, identifier, (filename == null) ? ReturnType.direct : ReturnType.disk);
439 clientGet.setGlobal(global);
440 HighLevelProgressCallback<DownloadResult> downloadCallback = new HighLevelProgressCallback<DownloadResult>(new DownloadResult(identifier));
441 downloadCallbacks.put(identifier, downloadCallback);
442 fcpConnection.sendMessage(clientGet);
443 return downloadCallback;
447 * Requests a list of all running requests from the node.
449 * @return The request list result
450 * @throws IOException
451 * if an I/O errors communicating with the node
453 public HighLevelCallback<RequestListResult> getRequests() throws IOException {
454 String identifier = generateIdentifier("list-persistent-requests");
455 ListPersistentRequests listPersistentRequests = new ListPersistentRequests();
456 synchronized (syncObject) {
457 if (requestListCallback != null) {
458 logger.log(Level.SEVERE, "getRequests() called with request still running!");
460 requestListCallback = new HighLevelCallback<RequestListResult>(new RequestListResult(identifier));
462 fcpConnection.sendMessage(listPersistentRequests);
463 return requestListCallback;
471 * Generates an identifier for the given function.
474 * The name of the function
475 * @return An identifier
477 private String generateIdentifier(String function) {
478 return "jFCPlib-" + function + "-" + System.currentTimeMillis();
482 * Disconnects the client from the node, handing the given Throwable to
483 * {@link #fireClientDisconnected(Throwable)}.
486 * The exception that caused the disconnect, or <code>null</code>
487 * if there was no exception
489 private void disconnect(Throwable throwable) {
490 fcpConnection.close();
491 fireClientDisconnected(throwable);
495 * FCP listener for {@link HighLevelClient}.
497 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
500 private class HighLevelClientFcpListener implements FcpListener {
502 /** Mapping from directory to written file (for cleanup). */
503 private final Map<DirectDiskAccessResult, String> writtenFiles = new HashMap<DirectDiskAccessResult, String>();
506 * Creates a new FCP listener for {@link HighLevelClient}.
508 HighLevelClientFcpListener() {
517 * Searches all callback collections for a callback with the given
518 * identifier and cancels it.
521 * The identifier to search for, or <code>null</code> to
522 * cancel all pending requests
524 @SuppressWarnings("synthetic-access")
525 private void cancelIdentifier(String identifier) {
526 synchronized (syncObject) {
527 if (connectCallback != null) {
528 connectCallback.getIntermediaryResult().setFailed(true);
529 connectCallback.setDone();
530 connectCallback = null;
532 if (requestListCallback != null) {
533 requestListCallback.getIntermediaryResult().setFailed(true);
534 requestListCallback.setDone();
535 requestListCallback = null;
538 if (identifier == null) {
539 /* key generation callbacks */
540 for (Entry<String, HighLevelCallback<KeyGenerationResult>> keyGenerationEntry: keyGenerationCallbacks.entrySet()) {
541 keyGenerationEntry.getValue().getIntermediaryResult().setFailed(true);
542 keyGenerationEntry.getValue().setDone();
544 keyGenerationCallbacks.clear();
545 /* peer list callbacks. */
546 for (Entry<String, HighLevelCallback<PeerListResult>> peerListEntry: peerListCallbacks.entrySet()) {
547 peerListEntry.getValue().getIntermediaryResult().setFailed(true);
548 peerListEntry.getValue().setDone();
550 peerListCallbacks.clear();
551 /* peer callbacks. */
552 for (Entry<String, HighLevelCallback<PeerResult>> peerEntry: peerCallbacks.entrySet()) {
553 peerEntry.getValue().getIntermediaryResult().setFailed(true);
554 peerEntry.getValue().setDone();
556 peerCallbacks.clear();
557 /* direct disk access callbacks. */
558 for (Entry<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessEntry: directDiskAccessCallbacks.entrySet()) {
559 directDiskAccessEntry.getValue().getIntermediaryResult().setFailed(true);
560 directDiskAccessEntry.getValue().setDone();
562 directDiskAccessCallbacks.clear();
563 /* download callbacks. */
564 for (Entry<String, HighLevelProgressCallback<DownloadResult>> downloadEntry: downloadCallbacks.entrySet()) {
565 downloadEntry.getValue().getIntermediaryResult().setFailed(true);
566 downloadEntry.getValue().setDone();
568 downloadCallbacks.clear();
570 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(identifier);
571 if (keyGenerationCallback != null) {
572 keyGenerationCallback.getIntermediaryResult().setFailed(true);
573 keyGenerationCallback.setDone();
576 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
577 if (peerListCallback != null) {
578 peerListCallback.getIntermediaryResult().setFailed(true);
579 peerListCallback.setDone();
582 HighLevelCallback<PeerResult> peerCallback = peerCallbacks.remove(identifier);
583 if (peerCallback != null) {
584 peerCallback.getIntermediaryResult().setFailed(true);
585 peerCallback.setDone();
588 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(identifier);
589 if (directDiskAccessCallback != null) {
590 directDiskAccessCallback.getIntermediaryResult().setFailed(true);
591 directDiskAccessCallback.setDone();
594 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
595 if (downloadCallback != null) {
596 downloadCallback.getIntermediaryResult().setFailed(true);
597 downloadCallback.setDone();
604 * Reads the given file and returns the first line of the file.
606 * @param readFilename
607 * The name of the file to read
608 * @return The content of the file
610 private String readContent(String readFilename) {
611 FileReader fileReader = null;
612 BufferedReader bufferedFileReader = null;
614 fileReader = new FileReader(readFilename);
615 bufferedFileReader = new BufferedReader(fileReader);
616 String content = bufferedFileReader.readLine();
618 } catch (IOException ioe1) {
621 FcpUtils.close(bufferedFileReader);
622 FcpUtils.close(fileReader);
628 * Writes the given content to the given file.
630 * @param directDiskAccessResult
632 * @param writeFilename
633 * The name of the file to write to
634 * @param writeContent
635 * The content to write to the file
637 private void writeContent(DirectDiskAccessResult directDiskAccessResult, String writeFilename, String writeContent) {
638 if ((writeFilename == null) || (writeContent == null)) {
641 writtenFiles.put(directDiskAccessResult, writeFilename);
642 FileWriter fileWriter = null;
644 fileWriter = new FileWriter(writeFilename);
645 fileWriter.write(writeContent);
646 } catch (IOException ioe1) {
649 FcpUtils.close(fileWriter);
654 * Cleans up any files that written for the given result.
656 * @param directDiskAccessResult
657 * The direct disk access result
659 @SuppressWarnings("synthetic-access")
660 private void cleanFiles(DirectDiskAccessResult directDiskAccessResult) {
661 String writeFilename = writtenFiles.remove(directDiskAccessResult);
662 if (writeFilename != null) {
663 if (!new File(writeFilename).delete()) {
664 logger.warning("could not delete " + writeFilename);
670 // INTERFACE FcpListener
674 * @see net.pterodactylus.fcp.FcpListener#connectionClosed(net.pterodactylus.fcp.FcpConnection,
677 @SuppressWarnings("synthetic-access")
678 public void connectionClosed(FcpConnection fcpConnection, Throwable throwable) {
679 if (fcpConnection != HighLevelClient.this.fcpConnection) {
682 cancelIdentifier(null);
683 disconnect(throwable);
687 * @see net.pterodactylus.fcp.FcpListener#receivedAllData(net.pterodactylus.fcp.FcpConnection,
688 * net.pterodactylus.fcp.AllData)
690 public void receivedAllData(FcpConnection fcpConnection, AllData allData) {
695 * @see net.pterodactylus.fcp.FcpListener#receivedCloseConnectionDuplicateClientName(net.pterodactylus.fcp.FcpConnection,
696 * net.pterodactylus.fcp.CloseConnectionDuplicateClientName)
698 public void receivedCloseConnectionDuplicateClientName(FcpConnection fcpConnection, CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) {
703 * @see net.pterodactylus.fcp.FcpListener#receivedConfigData(net.pterodactylus.fcp.FcpConnection,
704 * net.pterodactylus.fcp.ConfigData)
706 public void receivedConfigData(FcpConnection fcpConnection, ConfigData configData) {
711 * @see net.pterodactylus.fcp.FcpListener#receivedDataFound(net.pterodactylus.fcp.FcpConnection,
712 * net.pterodactylus.fcp.DataFound)
714 public void receivedDataFound(FcpConnection fcpConnection, DataFound dataFound) {
719 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeerNotes(net.pterodactylus.fcp.FcpConnection,
720 * net.pterodactylus.fcp.EndListPeerNotes)
722 public void receivedEndListPeerNotes(FcpConnection fcpConnection, EndListPeerNotes endListPeerNotes) {
727 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeers(net.pterodactylus.fcp.FcpConnection,
728 * net.pterodactylus.fcp.EndListPeers)
730 @SuppressWarnings("synthetic-access")
731 public void receivedEndListPeers(FcpConnection fcpConnection, EndListPeers endListPeers) {
732 if (fcpConnection != HighLevelClient.this.fcpConnection) {
735 String identifier = endListPeers.getIdentifier();
736 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
737 if (peerListCallback == null) {
740 peerListCallback.setDone();
744 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPersistentRequests(net.pterodactylus.fcp.FcpConnection,
745 * net.pterodactylus.fcp.EndListPersistentRequests)
747 @SuppressWarnings("synthetic-access")
748 public void receivedEndListPersistentRequests(FcpConnection fcpConnection, EndListPersistentRequests endListPersistentRequests) {
749 if (fcpConnection != HighLevelClient.this.fcpConnection) {
752 synchronized (syncObject) {
753 if (HighLevelClient.this.requestListCallback == null) {
754 logger.log(Level.WARNING, "got EndListPersistentRequests without running request!");
757 requestListCallback.setDone();
758 requestListCallback = null;
763 * @see net.pterodactylus.fcp.FcpListener#receivedFCPPluginReply(net.pterodactylus.fcp.FcpConnection,
764 * net.pterodactylus.fcp.FCPPluginReply)
766 public void receivedFCPPluginReply(FcpConnection fcpConnection, FCPPluginReply fcpPluginReply) {
771 * @see net.pterodactylus.fcp.FcpListener#receivedGetFailed(net.pterodactylus.fcp.FcpConnection,
772 * net.pterodactylus.fcp.GetFailed)
774 @SuppressWarnings("synthetic-access")
775 public void receivedGetFailed(FcpConnection fcpConnection, GetFailed getFailed) {
776 if (fcpConnection != HighLevelClient.this.fcpConnection) {
779 String identifier = getFailed.getIdentifier();
780 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
781 if (downloadCallback != null) {
782 downloadCallback.getIntermediaryResult().setFailed(true);
783 downloadCallback.setDone();
786 /* unknown identifier? */
787 logger.warning("unknown identifier for GetFailed: " + identifier);
791 * @see net.pterodactylus.fcp.FcpListener#receivedIdentifierCollision(net.pterodactylus.fcp.FcpConnection,
792 * net.pterodactylus.fcp.IdentifierCollision)
794 public void receivedIdentifierCollision(FcpConnection fcpConnection, IdentifierCollision identifierCollision) {
799 * @see net.pterodactylus.fcp.FcpListener#receivedMessage(net.pterodactylus.fcp.FcpConnection,
800 * net.pterodactylus.fcp.FcpMessage)
802 public void receivedMessage(FcpConnection fcpConnection, FcpMessage fcpMessage) {
807 * @see net.pterodactylus.fcp.FcpListener#receivedNodeData(net.pterodactylus.fcp.FcpConnection,
808 * net.pterodactylus.fcp.NodeData)
810 public void receivedNodeData(FcpConnection fcpConnection, NodeData nodeData) {
815 * @see net.pterodactylus.fcp.FcpListener#receivedNodeHello(net.pterodactylus.fcp.FcpConnection,
816 * net.pterodactylus.fcp.NodeHello)
818 @SuppressWarnings("synthetic-access")
819 public void receivedNodeHello(FcpConnection fcpConnection, NodeHello nodeHello) {
820 if (fcpConnection != HighLevelClient.this.fcpConnection) {
823 synchronized (syncObject) {
824 connectCallback.getIntermediaryResult().setFailed(false);
825 connectCallback.setDone();
826 connectCallback = null;
828 fireClientConnected();
832 * @see net.pterodactylus.fcp.FcpListener#receivedPeer(net.pterodactylus.fcp.FcpConnection,
833 * net.pterodactylus.fcp.Peer)
835 @SuppressWarnings("synthetic-access")
836 public void receivedPeer(FcpConnection fcpConnection, Peer peer) {
837 if (fcpConnection != HighLevelClient.this.fcpConnection) {
840 String identifier = peer.getIdentifier();
841 if (identifier == null) {
844 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.get(identifier);
845 if (peerListCallback != null) {
846 peerListCallback.getIntermediaryResult().addPeer(peer);
849 HighLevelCallback<PeerResult> peerResult = peerCallbacks.remove(identifier);
850 if (peerResult != null) {
851 peerResult.getIntermediaryResult().setPeer(peer);
852 peerResult.setDone();
855 logger.warning("got Peer message with unknown identifier: " + identifier);
859 * @see net.pterodactylus.fcp.FcpListener#receivedPeerNote(net.pterodactylus.fcp.FcpConnection,
860 * net.pterodactylus.fcp.PeerNote)
862 public void receivedPeerNote(FcpConnection fcpConnection, PeerNote peerNote) {
867 * @see net.pterodactylus.fcp.FcpListener#receivedPeerRemoved(net.pterodactylus.fcp.FcpConnection,
868 * net.pterodactylus.fcp.PeerRemoved)
870 public void receivedPeerRemoved(FcpConnection fcpConnection, PeerRemoved peerRemoved) {
875 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentGet(net.pterodactylus.fcp.FcpConnection,
876 * net.pterodactylus.fcp.PersistentGet)
878 @SuppressWarnings("synthetic-access")
879 public void receivedPersistentGet(FcpConnection fcpConnection, PersistentGet persistentGet) {
880 if (fcpConnection != HighLevelClient.this.fcpConnection) {
883 synchronized (syncObject) {
884 if (requestListCallback != null) {
885 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
886 requestListResult.addRequestResult(new GetRequestResult(persistentGet));
890 String identifier = persistentGet.getIdentifier();
891 if (downloadCallbacks.containsKey(identifier)) {
898 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPut(net.pterodactylus.fcp.FcpConnection,
899 * net.pterodactylus.fcp.PersistentPut)
901 @SuppressWarnings("synthetic-access")
902 public void receivedPersistentPut(FcpConnection fcpConnection, PersistentPut persistentPut) {
903 if (fcpConnection != HighLevelClient.this.fcpConnection) {
906 synchronized (syncObject) {
907 if (requestListCallback != null) {
908 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
909 requestListResult.addRequestResult(new PutRequestResult(persistentPut));
916 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPutDir(net.pterodactylus.fcp.FcpConnection,
917 * net.pterodactylus.fcp.PersistentPutDir)
919 @SuppressWarnings("synthetic-access")
920 public void receivedPersistentPutDir(FcpConnection fcpConnection, PersistentPutDir persistentPutDir) {
921 if (fcpConnection != HighLevelClient.this.fcpConnection) {
924 synchronized (syncObject) {
925 if (requestListCallback != null) {
926 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
927 requestListResult.addRequestResult(new PutDirRequestResult(persistentPutDir));
934 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestModified(net.pterodactylus.fcp.FcpConnection,
935 * net.pterodactylus.fcp.PersistentRequestModified)
937 public void receivedPersistentRequestModified(FcpConnection fcpConnection, PersistentRequestModified persistentRequestModified) {
942 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestRemoved(net.pterodactylus.fcp.FcpConnection,
943 * net.pterodactylus.fcp.PersistentRequestRemoved)
945 public void receivedPersistentRequestRemoved(FcpConnection fcpConnection, PersistentRequestRemoved persistentRequestRemoved) {
950 * @see net.pterodactylus.fcp.FcpListener#receivedPluginInfo(net.pterodactylus.fcp.FcpConnection,
951 * net.pterodactylus.fcp.PluginInfo)
953 public void receivedPluginInfo(FcpConnection fcpConnection, PluginInfo pluginInfo) {
958 * @see net.pterodactylus.fcp.FcpListener#receivedProtocolError(net.pterodactylus.fcp.FcpConnection,
959 * net.pterodactylus.fcp.ProtocolError)
961 @SuppressWarnings("synthetic-access")
962 public void receivedProtocolError(FcpConnection fcpConnection, ProtocolError protocolError) {
963 if (fcpConnection != HighLevelClient.this.fcpConnection) {
966 String identifier = protocolError.getIdentifier();
967 if (identifier == null) {
970 cancelIdentifier(identifier);
974 * @see net.pterodactylus.fcp.FcpListener#receivedPutFailed(net.pterodactylus.fcp.FcpConnection,
975 * net.pterodactylus.fcp.PutFailed)
977 public void receivedPutFailed(FcpConnection fcpConnection, PutFailed putFailed) {
982 * @see net.pterodactylus.fcp.FcpListener#receivedPutFetchable(net.pterodactylus.fcp.FcpConnection,
983 * net.pterodactylus.fcp.PutFetchable)
985 public void receivedPutFetchable(FcpConnection fcpConnection, PutFetchable putFetchable) {
990 * @see net.pterodactylus.fcp.FcpListener#receivedPutSuccessful(net.pterodactylus.fcp.FcpConnection,
991 * net.pterodactylus.fcp.PutSuccessful)
993 public void receivedPutSuccessful(FcpConnection fcpConnection, PutSuccessful putSuccessful) {
998 * @see net.pterodactylus.fcp.FcpListener#receivedSSKKeypair(net.pterodactylus.fcp.FcpConnection,
999 * net.pterodactylus.fcp.SSKKeypair)
1001 @SuppressWarnings("synthetic-access")
1002 public void receivedSSKKeypair(FcpConnection fcpConnection, SSKKeypair sskKeypair) {
1003 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1006 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(sskKeypair.getIdentifier());
1007 if (keyGenerationCallback == null) {
1010 KeyGenerationResult keyGenerationResult = keyGenerationCallback.getIntermediaryResult();
1011 keyGenerationResult.setInsertURI(sskKeypair.getInsertURI());
1012 keyGenerationResult.setRequestURI(sskKeypair.getRequestURI());
1013 keyGenerationCallback.setDone();
1017 * @see net.pterodactylus.fcp.FcpListener#receivedSimpleProgress(net.pterodactylus.fcp.FcpConnection,
1018 * net.pterodactylus.fcp.SimpleProgress)
1020 @SuppressWarnings("synthetic-access")
1021 public void receivedSimpleProgress(FcpConnection fcpConnection, SimpleProgress simpleProgress) {
1022 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1025 String identifier = simpleProgress.getIdentifier();
1026 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
1027 if (downloadCallback != null) {
1028 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
1029 downloadResult.setTotalBlocks(simpleProgress.getTotal());
1030 downloadResult.setRequiredBlocks(simpleProgress.getRequired());
1031 downloadResult.setSuccessfulBlocks(simpleProgress.getSucceeded());
1032 downloadResult.setFailedBlocks(simpleProgress.getFailed());
1033 downloadResult.setFatallyFailedBlocks(simpleProgress.getFatallyFailed());
1034 downloadResult.setTotalFinalized(simpleProgress.isFinalizedTotal());
1035 downloadCallback.progressUpdated();
1038 /* unknown identifier? */
1039 logger.warning("unknown identifier for SimpleProgress: " + identifier);
1043 * @see net.pterodactylus.fcp.FcpListener#receivedStartedCompression(net.pterodactylus.fcp.FcpConnection,
1044 * net.pterodactylus.fcp.StartedCompression)
1046 public void receivedStartedCompression(FcpConnection fcpConnection, StartedCompression startedCompression) {
1051 * @see net.pterodactylus.fcp.FcpListener#receivedSubscribedUSKUpdate(net.pterodactylus.fcp.FcpConnection,
1052 * net.pterodactylus.fcp.SubscribedUSKUpdate)
1054 public void receivedSubscribedUSKUpdate(FcpConnection fcpConnection, SubscribedUSKUpdate subscribedUSKUpdate) {
1059 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAComplete(net.pterodactylus.fcp.FcpConnection,
1060 * net.pterodactylus.fcp.TestDDAComplete)
1062 @SuppressWarnings("synthetic-access")
1063 public void receivedTestDDAComplete(FcpConnection fcpConnection, TestDDAComplete testDDAComplete) {
1064 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1067 String directory = testDDAComplete.getDirectory();
1068 if (directory == null) {
1071 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(directory);
1072 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallback.getIntermediaryResult();
1073 cleanFiles(directDiskAccessResult);
1074 directDiskAccessResult.setReadAllowed(testDDAComplete.isReadDirectoryAllowed());
1075 directDiskAccessResult.setWriteAllowed(testDDAComplete.isWriteDirectoryAllowed());
1076 directDiskAccessCallback.setDone();
1080 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAReply(net.pterodactylus.fcp.FcpConnection,
1081 * net.pterodactylus.fcp.TestDDAReply)
1083 @SuppressWarnings("synthetic-access")
1084 public void receivedTestDDAReply(FcpConnection fcpConnection, TestDDAReply testDDAReply) {
1085 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1088 String directory = testDDAReply.getDirectory();
1089 if (directory == null) {
1092 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallbacks.get(directory).getIntermediaryResult();
1093 String readFilename = testDDAReply.getReadFilename();
1094 String readContent = readContent(readFilename);
1095 String writeFilename = testDDAReply.getWriteFilename();
1096 String writeContent = testDDAReply.getContentToWrite();
1097 writeContent(directDiskAccessResult, writeFilename, writeContent);
1098 TestDDAResponse testDDAResponse = new TestDDAResponse(directory, readContent);
1100 fcpConnection.sendMessage(testDDAResponse);
1101 } catch (IOException e) {
1102 /* swallow. I’m verry unhappy about this. */
1107 * @see net.pterodactylus.fcp.FcpListener#receivedURIGenerated(net.pterodactylus.fcp.FcpConnection,
1108 * net.pterodactylus.fcp.URIGenerated)
1110 public void receivedURIGenerated(FcpConnection fcpConnection, URIGenerated uriGenerated) {
1115 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownNodeIdentifier(net.pterodactylus.fcp.FcpConnection,
1116 * net.pterodactylus.fcp.UnknownNodeIdentifier)
1118 public void receivedUnknownNodeIdentifier(FcpConnection fcpConnection, UnknownNodeIdentifier unknownNodeIdentifier) {
1123 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownPeerNoteType(net.pterodactylus.fcp.FcpConnection,
1124 * net.pterodactylus.fcp.UnknownPeerNoteType)
1126 public void receivedUnknownPeerNoteType(FcpConnection fcpConnection, UnknownPeerNoteType unknownPeerNoteType) {
1131 * @see net.pterodactylus.fcp.FcpListener#receviedFinishedCompression(net.pterodactylus.fcp.FcpConnection,
1132 * net.pterodactylus.fcp.FinishedCompression)
1134 public void receviedFinishedCompression(FcpConnection fcpConnection, FinishedCompression finishedCompression) {