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>
96 public class HighLevelClient {
99 private static final Logger logger = Logger.getLogger(HighLevelClient.class.getName());
101 /** Object for internal synchronization. */
102 private final Object syncObject = new Object();
104 /** The name of the client. */
105 private final String clientName;
107 /** The FCP connection to the node. */
108 private FcpConnection fcpConnection = null;
110 /** Listeners for high-level client events. */
111 private List<HighLevelClientListener> highLevelClientListeners = Collections.synchronizedList(new ArrayList<HighLevelClientListener>());
113 /** The listener for the connection. */
114 private HighLevelClientFcpListener highLevelClientFcpListener = new HighLevelClientFcpListener();
116 /** The listeners for progress events. */
117 private List<HighLevelProgressListener> highLevelProgressListeners = Collections.synchronizedList(new ArrayList<HighLevelProgressListener>());
119 /** The callback for {@link #connect(String)}. */
120 private HighLevelCallback<ConnectResult> connectCallback;
122 /** Mapping from request identifiers to callbacks. */
123 private Map<String, HighLevelCallback<KeyGenerationResult>> keyGenerationCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<KeyGenerationResult>>());
125 /** Mapping from request identifier to peer list callbacks. */
126 private Map<String, HighLevelCallback<PeerListResult>> peerListCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerListResult>>());
128 /** Mapping from request identifier to peer callbacks. */
129 private Map<String, HighLevelCallback<PeerResult>> peerCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerResult>>());
131 /** Mapping from directories to DDA callbacks. */
132 private Map<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<DirectDiskAccessResult>>());
134 /** Mapping from request identifiers to download callbacks. */
135 private Map<String, HighLevelProgressCallback<DownloadResult>> downloadCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelProgressCallback<DownloadResult>>());
137 /** The callback for {@link #getRequests()}. */
138 private HighLevelCallback<RequestListResult> requestListCallback;
141 * Creates a new high-level client that connects to a node on
142 * <code>localhost</code>.
145 * The name of the client
147 public HighLevelClient(String clientName) {
148 this.clientName = clientName;
156 * Adds the given high-level client listener to list of listeners.
158 * @param highLevelClientListener
159 * The listener to add
161 public void addHighLevelClientListener(HighLevelClientListener highLevelClientListener) {
162 highLevelClientListeners.add(highLevelClientListener);
166 * Removes the given high-level client listener from the list of listeners.
168 * @param highLevelClientListener
169 * The listener to remove
171 public void removeHighLevelClientListener(HighLevelClientListener highLevelClientListener) {
172 highLevelClientListeners.remove(highLevelClientListener);
176 * Notifies all listeners that a client has connected.
178 private void fireClientConnected() {
179 for (HighLevelClientListener highLevelClientListener : highLevelClientListeners) {
180 highLevelClientListener.clientConnected(this);
185 * Notifies all listeners that a client has disconnected.
188 * The exception that caused the disconnect, or <code>null</code>
189 * if there was no exception
191 private void fireClientDisconnected(Throwable throwable) {
192 for (HighLevelClientListener highLevelClientListener : highLevelClientListeners) {
193 highLevelClientListener.clientDisconnected(this, throwable);
198 * Adds a high-level progress listener.
200 * @param highLevelProgressListener
201 * The high-level progress listener to add
203 public void addHighLevelProgressListener(HighLevelProgressListener highLevelProgressListener) {
204 highLevelProgressListeners.add(highLevelProgressListener);
208 * Removes a high-level progress listener.
210 * @param highLevelProgressListener
211 * The high-level progress listener to remove
213 public void removeHighLevelProgressListener(HighLevelProgressListener highLevelProgressListener) {
214 highLevelProgressListeners.remove(highLevelProgressListener);
218 * Notifies all listeners that the request with the given identifier made
222 * The identifier of the request
223 * @param highLevelProgress
224 * The progress of the request
226 private void fireProgressReceived(String identifier, HighLevelProgress highLevelProgress) {
227 for (HighLevelProgressListener highLevelProgressListener : highLevelProgressListeners) {
228 highLevelProgressListener.progressReceived(this, identifier, highLevelProgress);
237 * Returns the FCP connection that backs this high-level client. This method
238 * should be used with care as fiddling around with the FCP connection can
239 * easily break the high-level client if you don’t know what you’re doing!
241 * @return The FCP connection of this client
243 public FcpConnection getFcpConnection() {
244 return fcpConnection;
248 * Returns whether the node is connected.
250 * @return <code>true</code> if the node is currently connected,
251 * <code>false</code> otherwise
253 public boolean isConnected() {
254 return fcpConnection != null;
262 * Connects the client.
265 * The hostname of the node
266 * @return A callback with a connection result
267 * @throws UnknownHostException
268 * if the hostname can not be resolved
269 * @throws IOException
270 * if an I/O error occurs communicating with the node
272 public HighLevelCallback<ConnectResult> connect(String hostname) throws UnknownHostException, IOException {
273 return connect(hostname, 9481);
277 * Connects the client.
280 * The hostname of the node
282 * The port number of the node
283 * @return A callback with a connection result
284 * @throws UnknownHostException
285 * if the hostname can not be resolved
286 * @throws IOException
287 * if an I/O error occurs communicating with the node
289 public HighLevelCallback<ConnectResult> connect(String hostname, int port) throws UnknownHostException, IOException {
290 return connect(InetAddress.getByName(hostname), port);
294 * Connects the client.
297 * The address of the node
299 * The port number of the node
300 * @return A callback with a connection result
301 * @throws IOException
302 * if an I/O error occurs communicating with the node
304 public HighLevelCallback<ConnectResult> connect(InetAddress address, int port) throws IOException {
306 synchronized (this) {
307 fcpConnection = new FcpConnection(address, port);
309 fcpConnection.addFcpListener(highLevelClientFcpListener);
310 fcpConnection.connect();
311 ClientHello clientHello = new ClientHello(clientName);
312 connectCallback = new HighLevelCallback<ConnectResult>(new ConnectResult());
313 fcpConnection.sendMessage(clientHello);
314 return connectCallback;
315 } catch (IOException ioe1) {
316 fcpConnection = null;
322 * Disconnects the client from the node.
324 public void disconnect() {
329 * Generates a new SSK keypair.
331 * @return A callback with the keypair
332 * @throws IOException
333 * if an I/O error occurs communicating with the node
334 * @throws HighLevelException
335 * if the client is not connected
337 public HighLevelCallback<KeyGenerationResult> generateKey() throws IOException, HighLevelException {
339 String identifier = generateIdentifier("generateSSK");
340 GenerateSSK generateSSK = new GenerateSSK(identifier);
341 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = new HighLevelCallback<KeyGenerationResult>(new KeyGenerationResult(identifier));
342 keyGenerationCallbacks.put(identifier, keyGenerationCallback);
343 fcpConnection.sendMessage(generateSSK);
344 return keyGenerationCallback;
348 * Sets whether to watch the global queue.
351 * <code>true</code> to watch the global queue in addition to the
352 * client-local queue, <code>false</code> to only watch the
354 * @throws IOException
355 * if an I/O error occurs communicating with the node
356 * @throws HighLevelException
357 * if the client is not connected
359 public void setWatchGlobal(boolean enabled) throws IOException, HighLevelException {
361 WatchGlobal watchGlobal = new WatchGlobal(enabled);
362 fcpConnection.sendMessage(watchGlobal);
366 * Gets a list of all peers from the node.
368 * @return A callback with the peer list
369 * @throws IOException
370 * if an I/O error occurs with the node
371 * @throws HighLevelException
372 * if the client is not connected
374 public HighLevelCallback<PeerListResult> getPeers() throws IOException, HighLevelException {
376 String identifier = generateIdentifier("listPeers");
377 ListPeers listPeers = new ListPeers(identifier, true, true);
378 HighLevelCallback<PeerListResult> peerListCallback = new HighLevelCallback<PeerListResult>(new PeerListResult(identifier));
379 peerListCallbacks.put(identifier, peerListCallback);
380 fcpConnection.sendMessage(listPeers);
381 return peerListCallback;
385 * Adds the peer whose noderef is stored in the given file.
388 * The name of the file the peer’s noderef is stored in
389 * @return A peer callback
390 * @throws IOException
391 * if an I/O error occurs communicating with the node
392 * @throws HighLevelException
393 * if the client is not connected
395 public HighLevelCallback<PeerResult> addPeer(String nodeRefFile) throws IOException, HighLevelException {
397 String identifier = generateIdentifier("addPeer");
398 AddPeer addPeer = new AddPeer(nodeRefFile);
399 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
400 peerCallbacks.put(identifier, peerCallback);
401 fcpConnection.sendMessage(addPeer);
406 * Adds the peer whose noderef is stored in the given file.
409 * The URL where the peer’s noderef is stored
410 * @return A peer callback
411 * @throws IOException
412 * if an I/O error occurs communicating with the node
413 * @throws HighLevelException
414 * if the client is not connected
416 public HighLevelCallback<PeerResult> addPeer(URL nodeRefURL) throws IOException, HighLevelException {
418 String identifier = generateIdentifier("addPeer");
419 AddPeer addPeer = new AddPeer(nodeRefURL);
420 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
421 peerCallbacks.put(identifier, peerCallback);
422 fcpConnection.sendMessage(addPeer);
427 * Adds the peer whose noderef is stored in the given file.
431 * @return A peer callback
432 * @throws IOException
433 * if an I/O error occurs communicating with the node
434 * @throws HighLevelException
435 * if the client is not connected
437 public HighLevelCallback<PeerResult> addPeer(NodeRef nodeRef) throws IOException, HighLevelException {
439 String identifier = generateIdentifier("addPeer");
440 AddPeer addPeer = new AddPeer(nodeRef);
441 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
442 peerCallbacks.put(identifier, peerCallback);
443 fcpConnection.sendMessage(addPeer);
448 * Checks whether direct disk access for the given directory is possible.
449 * You have to perform this check before you can upload or download anything
450 * from or the disk directly!
453 * The directory to check
455 * Whether you want to read the given directory
457 * Whether you want to write to the given directory
458 * @return A direct disk access callback
459 * @throws IOException
460 * if an I/O error occurs communicating with the node
461 * @throws HighLevelException
462 * if the client is not connected
464 public HighLevelCallback<DirectDiskAccessResult> checkDirectDiskAccess(String directory, boolean wantRead, boolean wantWrite) throws IOException, HighLevelException {
466 TestDDARequest testDDARequest = new TestDDARequest(directory, wantRead, wantWrite);
467 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = new HighLevelCallback<DirectDiskAccessResult>(new DirectDiskAccessResult(directory));
468 directDiskAccessCallbacks.put(directory, directDiskAccessCallback);
469 fcpConnection.sendMessage(testDDARequest);
470 return directDiskAccessCallback;
474 * Starts a download. Files can either be download to disk or streamed from
475 * the node. When downloading to disk you have to perform a direct disk
476 * access check for the directory you want to put the downloaded file in!
478 * @see #checkDirectDiskAccess(String, boolean, boolean)
482 * The filename to save the data to, or <code>null</code> to
483 * retrieve the data as InputStream from the
484 * {@link DownloadResult}
486 * Whether to put the download on the global queue
487 * @return A download result
488 * @throws IOException
489 * if an I/O error occurs communicating with the node
490 * @throws HighLevelException
491 * if the client is not connected
493 public HighLevelProgressCallback<DownloadResult> download(String uri, String filename, boolean global) throws IOException, HighLevelException {
495 String identifier = generateIdentifier("download");
496 ClientGet clientGet = new ClientGet(uri, identifier, (filename == null) ? ReturnType.direct : ReturnType.disk);
497 clientGet.setGlobal(global);
498 HighLevelProgressCallback<DownloadResult> downloadCallback = new HighLevelProgressCallback<DownloadResult>(new DownloadResult(identifier));
499 downloadCallbacks.put(identifier, downloadCallback);
500 fcpConnection.sendMessage(clientGet);
501 return downloadCallback;
505 * Requests a list of all running requests from the node.
507 * @return The request list result
508 * @throws IOException
509 * if an I/O errors communicating with the node
510 * @throws HighLevelException
511 * if the client is not connected
513 public HighLevelCallback<RequestListResult> getRequests() throws IOException, HighLevelException {
515 String identifier = generateIdentifier("list-persistent-requests");
516 ListPersistentRequests listPersistentRequests = new ListPersistentRequests();
517 synchronized (syncObject) {
518 if (requestListCallback != null) {
519 logger.log(Level.SEVERE, "getRequests() called with request still running!");
521 requestListCallback = new HighLevelCallback<RequestListResult>(new RequestListResult(identifier));
523 fcpConnection.sendMessage(listPersistentRequests);
524 return requestListCallback;
532 * Checks whether the client is already connected and throws an exception if
535 * @throws NotConnectedException
536 * if the client is not connected
538 private void checkConnection() throws NotConnectedException {
539 synchronized (this) {
540 if (fcpConnection == null) {
541 throw new NotConnectedException("client is not connected");
547 * Generates an identifier for the given function.
550 * The name of the function
551 * @return An identifier
553 private String generateIdentifier(String function) {
554 return "jFCPlib-" + function + "-" + System.currentTimeMillis();
558 * Disconnects the client from the node, handing the given Throwable to
559 * {@link #fireClientDisconnected(Throwable)}.
562 * The exception that caused the disconnect, or <code>null</code>
563 * if there was no exception
565 private void disconnect(Throwable throwable) {
566 if (fcpConnection != null) {
567 fcpConnection.close();
569 fcpConnection = null;
573 * FCP listener for {@link HighLevelClient}.
575 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
577 private class HighLevelClientFcpListener implements FcpListener {
579 /** Mapping from directory to written file (for cleanup). */
580 private final Map<DirectDiskAccessResult, String> writtenFiles = new HashMap<DirectDiskAccessResult, String>();
583 * Creates a new FCP listener for {@link HighLevelClient}.
585 HighLevelClientFcpListener() {
594 * Searches all callback collections for a callback with the given
595 * identifier and cancels it.
598 * The identifier to search for, or <code>null</code> to
599 * cancel all pending requests
601 @SuppressWarnings("synthetic-access")
602 private void cancelIdentifier(String identifier) {
603 synchronized (syncObject) {
604 if (connectCallback != null) {
605 connectCallback.getIntermediaryResult().setFailed(true);
606 connectCallback.setDone();
607 connectCallback = null;
609 if (requestListCallback != null) {
610 requestListCallback.getIntermediaryResult().setFailed(true);
611 requestListCallback.setDone();
612 requestListCallback = null;
615 if (identifier == null) {
616 /* key generation callbacks */
617 for (Entry<String, HighLevelCallback<KeyGenerationResult>> keyGenerationEntry : keyGenerationCallbacks.entrySet()) {
618 keyGenerationEntry.getValue().getIntermediaryResult().setFailed(true);
619 keyGenerationEntry.getValue().setDone();
621 keyGenerationCallbacks.clear();
622 /* peer list callbacks. */
623 for (Entry<String, HighLevelCallback<PeerListResult>> peerListEntry : peerListCallbacks.entrySet()) {
624 peerListEntry.getValue().getIntermediaryResult().setFailed(true);
625 peerListEntry.getValue().setDone();
627 peerListCallbacks.clear();
628 /* peer callbacks. */
629 for (Entry<String, HighLevelCallback<PeerResult>> peerEntry : peerCallbacks.entrySet()) {
630 peerEntry.getValue().getIntermediaryResult().setFailed(true);
631 peerEntry.getValue().setDone();
633 peerCallbacks.clear();
634 /* direct disk access callbacks. */
635 for (Entry<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessEntry : directDiskAccessCallbacks.entrySet()) {
636 directDiskAccessEntry.getValue().getIntermediaryResult().setFailed(true);
637 directDiskAccessEntry.getValue().setDone();
639 directDiskAccessCallbacks.clear();
640 /* download callbacks. */
641 for (Entry<String, HighLevelProgressCallback<DownloadResult>> downloadEntry : downloadCallbacks.entrySet()) {
642 downloadEntry.getValue().getIntermediaryResult().setFailed(true);
643 downloadEntry.getValue().setDone();
645 downloadCallbacks.clear();
647 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(identifier);
648 if (keyGenerationCallback != null) {
649 keyGenerationCallback.getIntermediaryResult().setFailed(true);
650 keyGenerationCallback.setDone();
653 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
654 if (peerListCallback != null) {
655 peerListCallback.getIntermediaryResult().setFailed(true);
656 peerListCallback.setDone();
659 HighLevelCallback<PeerResult> peerCallback = peerCallbacks.remove(identifier);
660 if (peerCallback != null) {
661 peerCallback.getIntermediaryResult().setFailed(true);
662 peerCallback.setDone();
665 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(identifier);
666 if (directDiskAccessCallback != null) {
667 directDiskAccessCallback.getIntermediaryResult().setFailed(true);
668 directDiskAccessCallback.setDone();
671 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
672 if (downloadCallback != null) {
673 downloadCallback.getIntermediaryResult().setFailed(true);
674 downloadCallback.setDone();
681 * Reads the given file and returns the first line of the file.
683 * @param readFilename
684 * The name of the file to read
685 * @return The content of the file
687 private String readContent(String readFilename) {
688 if (readFilename == null) {
691 FileReader fileReader = null;
692 BufferedReader bufferedFileReader = null;
694 fileReader = new FileReader(readFilename);
695 bufferedFileReader = new BufferedReader(fileReader);
696 String content = bufferedFileReader.readLine();
698 } catch (IOException ioe1) {
701 FcpUtils.close(bufferedFileReader);
702 FcpUtils.close(fileReader);
708 * Writes the given content to the given file.
710 * @param directDiskAccessResult
712 * @param writeFilename
713 * The name of the file to write to
714 * @param writeContent
715 * The content to write to the file
717 private void writeContent(DirectDiskAccessResult directDiskAccessResult, String writeFilename, String writeContent) {
718 if ((writeFilename == null) || (writeContent == null)) {
721 writtenFiles.put(directDiskAccessResult, writeFilename);
722 FileWriter fileWriter = null;
724 fileWriter = new FileWriter(writeFilename);
725 fileWriter.write(writeContent);
726 } catch (IOException ioe1) {
729 FcpUtils.close(fileWriter);
734 * Cleans up any files that written for the given result.
736 * @param directDiskAccessResult
737 * The direct disk access result
739 @SuppressWarnings("synthetic-access")
740 private void cleanFiles(DirectDiskAccessResult directDiskAccessResult) {
741 String writeFilename = writtenFiles.remove(directDiskAccessResult);
742 if (writeFilename != null) {
743 if (!new File(writeFilename).delete()) {
744 logger.warning("could not delete " + writeFilename);
750 // INTERFACE FcpListener
754 * @see net.pterodactylus.fcp.FcpListener#connectionClosed(net.pterodactylus.fcp.FcpConnection,
757 @SuppressWarnings("synthetic-access")
758 public void connectionClosed(FcpConnection fcpConnection, Throwable throwable) {
759 if (fcpConnection != HighLevelClient.this.fcpConnection) {
762 cancelIdentifier(null);
763 disconnect(throwable);
764 fireClientDisconnected(throwable);
768 * @see net.pterodactylus.fcp.FcpListener#receivedAllData(net.pterodactylus.fcp.FcpConnection,
769 * net.pterodactylus.fcp.AllData)
771 public void receivedAllData(FcpConnection fcpConnection, AllData allData) {
776 * @see net.pterodactylus.fcp.FcpListener#receivedCloseConnectionDuplicateClientName(net.pterodactylus.fcp.FcpConnection,
777 * net.pterodactylus.fcp.CloseConnectionDuplicateClientName)
779 public void receivedCloseConnectionDuplicateClientName(FcpConnection fcpConnection, CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) {
784 * @see net.pterodactylus.fcp.FcpListener#receivedConfigData(net.pterodactylus.fcp.FcpConnection,
785 * net.pterodactylus.fcp.ConfigData)
787 public void receivedConfigData(FcpConnection fcpConnection, ConfigData configData) {
792 * @see net.pterodactylus.fcp.FcpListener#receivedDataFound(net.pterodactylus.fcp.FcpConnection,
793 * net.pterodactylus.fcp.DataFound)
795 @SuppressWarnings("synthetic-access")
796 public void receivedDataFound(FcpConnection fcpConnection, DataFound dataFound) {
797 if (fcpConnection != HighLevelClient.this.fcpConnection) {
800 String identifier = dataFound.getIdentifier();
801 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
802 if (downloadCallback != null) {
803 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
804 downloadResult.setFinished(true);
805 downloadResult.setFailed(false);
806 downloadCallback.progressUpdated();
807 downloadCallback.setDone();
809 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier, true);
810 fireProgressReceived(identifier, highLevelProgress);
814 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeerNotes(net.pterodactylus.fcp.FcpConnection,
815 * net.pterodactylus.fcp.EndListPeerNotes)
817 public void receivedEndListPeerNotes(FcpConnection fcpConnection, EndListPeerNotes endListPeerNotes) {
822 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeers(net.pterodactylus.fcp.FcpConnection,
823 * net.pterodactylus.fcp.EndListPeers)
825 @SuppressWarnings("synthetic-access")
826 public void receivedEndListPeers(FcpConnection fcpConnection, EndListPeers endListPeers) {
827 if (fcpConnection != HighLevelClient.this.fcpConnection) {
830 String identifier = endListPeers.getIdentifier();
831 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
832 if (peerListCallback == null) {
835 peerListCallback.setDone();
839 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPersistentRequests(net.pterodactylus.fcp.FcpConnection,
840 * net.pterodactylus.fcp.EndListPersistentRequests)
842 @SuppressWarnings("synthetic-access")
843 public void receivedEndListPersistentRequests(FcpConnection fcpConnection, EndListPersistentRequests endListPersistentRequests) {
844 if (fcpConnection != HighLevelClient.this.fcpConnection) {
847 synchronized (syncObject) {
848 if (HighLevelClient.this.requestListCallback == null) {
849 logger.log(Level.WARNING, "got EndListPersistentRequests without running request!");
852 requestListCallback.setDone();
853 requestListCallback = null;
858 * @see net.pterodactylus.fcp.FcpListener#receivedFCPPluginReply(net.pterodactylus.fcp.FcpConnection,
859 * net.pterodactylus.fcp.FCPPluginReply)
861 public void receivedFCPPluginReply(FcpConnection fcpConnection, FCPPluginReply fcpPluginReply) {
866 * @see net.pterodactylus.fcp.FcpListener#receivedGetFailed(net.pterodactylus.fcp.FcpConnection,
867 * net.pterodactylus.fcp.GetFailed)
869 @SuppressWarnings("synthetic-access")
870 public void receivedGetFailed(FcpConnection fcpConnection, GetFailed getFailed) {
871 if (fcpConnection != HighLevelClient.this.fcpConnection) {
874 String identifier = getFailed.getIdentifier();
875 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
876 if (downloadCallback != null) {
877 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
878 downloadResult.setFailed(true);
879 downloadResult.setFinished(true);
880 downloadCallback.setDone();
883 /* unknown identifier? */
884 logger.warning("unknown identifier for GetFailed: " + identifier);
888 * @see net.pterodactylus.fcp.FcpListener#receivedIdentifierCollision(net.pterodactylus.fcp.FcpConnection,
889 * net.pterodactylus.fcp.IdentifierCollision)
891 public void receivedIdentifierCollision(FcpConnection fcpConnection, IdentifierCollision identifierCollision) {
896 * @see net.pterodactylus.fcp.FcpListener#receivedMessage(net.pterodactylus.fcp.FcpConnection,
897 * net.pterodactylus.fcp.FcpMessage)
899 public void receivedMessage(FcpConnection fcpConnection, FcpMessage fcpMessage) {
904 * @see net.pterodactylus.fcp.FcpListener#receivedNodeData(net.pterodactylus.fcp.FcpConnection,
905 * net.pterodactylus.fcp.NodeData)
907 public void receivedNodeData(FcpConnection fcpConnection, NodeData nodeData) {
912 * @see net.pterodactylus.fcp.FcpListener#receivedNodeHello(net.pterodactylus.fcp.FcpConnection,
913 * net.pterodactylus.fcp.NodeHello)
915 @SuppressWarnings("synthetic-access")
916 public void receivedNodeHello(FcpConnection fcpConnection, NodeHello nodeHello) {
917 if (fcpConnection != HighLevelClient.this.fcpConnection) {
920 synchronized (syncObject) {
921 connectCallback.getIntermediaryResult().setFailed(false);
922 connectCallback.setDone();
923 connectCallback = null;
925 fireClientConnected();
929 * @see net.pterodactylus.fcp.FcpListener#receivedPeer(net.pterodactylus.fcp.FcpConnection,
930 * net.pterodactylus.fcp.Peer)
932 @SuppressWarnings("synthetic-access")
933 public void receivedPeer(FcpConnection fcpConnection, Peer peer) {
934 if (fcpConnection != HighLevelClient.this.fcpConnection) {
937 String identifier = peer.getIdentifier();
938 if (identifier == null) {
941 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.get(identifier);
942 if (peerListCallback != null) {
943 peerListCallback.getIntermediaryResult().addPeer(peer);
946 HighLevelCallback<PeerResult> peerResult = peerCallbacks.remove(identifier);
947 if (peerResult != null) {
948 peerResult.getIntermediaryResult().setPeer(peer);
949 peerResult.setDone();
952 logger.warning("got Peer message with unknown identifier: " + identifier);
956 * @see net.pterodactylus.fcp.FcpListener#receivedPeerNote(net.pterodactylus.fcp.FcpConnection,
957 * net.pterodactylus.fcp.PeerNote)
959 public void receivedPeerNote(FcpConnection fcpConnection, PeerNote peerNote) {
964 * @see net.pterodactylus.fcp.FcpListener#receivedPeerRemoved(net.pterodactylus.fcp.FcpConnection,
965 * net.pterodactylus.fcp.PeerRemoved)
967 public void receivedPeerRemoved(FcpConnection fcpConnection, PeerRemoved peerRemoved) {
972 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentGet(net.pterodactylus.fcp.FcpConnection,
973 * net.pterodactylus.fcp.PersistentGet)
975 @SuppressWarnings("synthetic-access")
976 public void receivedPersistentGet(FcpConnection fcpConnection, PersistentGet persistentGet) {
977 if (fcpConnection != HighLevelClient.this.fcpConnection) {
980 synchronized (syncObject) {
981 if (requestListCallback != null) {
982 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
983 requestListResult.addRequestResult(new GetRequestResult(persistentGet));
987 String identifier = persistentGet.getIdentifier();
988 if (downloadCallbacks.containsKey(identifier)) {
995 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPut(net.pterodactylus.fcp.FcpConnection,
996 * net.pterodactylus.fcp.PersistentPut)
998 @SuppressWarnings("synthetic-access")
999 public void receivedPersistentPut(FcpConnection fcpConnection, PersistentPut persistentPut) {
1000 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1003 synchronized (syncObject) {
1004 if (requestListCallback != null) {
1005 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
1006 requestListResult.addRequestResult(new PutRequestResult(persistentPut));
1013 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPutDir(net.pterodactylus.fcp.FcpConnection,
1014 * net.pterodactylus.fcp.PersistentPutDir)
1016 @SuppressWarnings("synthetic-access")
1017 public void receivedPersistentPutDir(FcpConnection fcpConnection, PersistentPutDir persistentPutDir) {
1018 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1021 synchronized (syncObject) {
1022 if (requestListCallback != null) {
1023 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
1024 requestListResult.addRequestResult(new PutDirRequestResult(persistentPutDir));
1031 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestModified(net.pterodactylus.fcp.FcpConnection,
1032 * net.pterodactylus.fcp.PersistentRequestModified)
1034 public void receivedPersistentRequestModified(FcpConnection fcpConnection, PersistentRequestModified persistentRequestModified) {
1039 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestRemoved(net.pterodactylus.fcp.FcpConnection,
1040 * net.pterodactylus.fcp.PersistentRequestRemoved)
1042 public void receivedPersistentRequestRemoved(FcpConnection fcpConnection, PersistentRequestRemoved persistentRequestRemoved) {
1047 * @see net.pterodactylus.fcp.FcpListener#receivedPluginInfo(net.pterodactylus.fcp.FcpConnection,
1048 * net.pterodactylus.fcp.PluginInfo)
1050 public void receivedPluginInfo(FcpConnection fcpConnection, PluginInfo pluginInfo) {
1055 * @see net.pterodactylus.fcp.FcpListener#receivedProtocolError(net.pterodactylus.fcp.FcpConnection,
1056 * net.pterodactylus.fcp.ProtocolError)
1058 @SuppressWarnings("synthetic-access")
1059 public void receivedProtocolError(FcpConnection fcpConnection, ProtocolError protocolError) {
1060 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1063 String identifier = protocolError.getIdentifier();
1064 if (identifier == null) {
1067 cancelIdentifier(identifier);
1071 * @see net.pterodactylus.fcp.FcpListener#receivedPutFailed(net.pterodactylus.fcp.FcpConnection,
1072 * net.pterodactylus.fcp.PutFailed)
1074 @SuppressWarnings("synthetic-access")
1075 public void receivedPutFailed(FcpConnection fcpConnection, PutFailed putFailed) {
1076 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1079 String identifier = putFailed.getIdentifier();
1080 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
1081 if (downloadCallback != null) {
1082 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
1083 downloadResult.setFailed(true);
1084 downloadResult.setFinished(true);
1085 downloadCallback.progressUpdated();
1086 downloadCallback.setDone();
1088 /* TODO - check inserts */
1089 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier, true);
1090 fireProgressReceived(identifier, highLevelProgress);
1094 * @see net.pterodactylus.fcp.FcpListener#receivedPutFetchable(net.pterodactylus.fcp.FcpConnection,
1095 * net.pterodactylus.fcp.PutFetchable)
1097 @SuppressWarnings("synthetic-access")
1098 public void receivedPutFetchable(FcpConnection fcpConnection, PutFetchable putFetchable) {
1099 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1102 String identifier = putFetchable.getIdentifier();
1103 /* TODO - check inserts */
1104 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier);
1105 highLevelProgress.setFetchable(true);
1106 fireProgressReceived(identifier, highLevelProgress);
1110 * @see net.pterodactylus.fcp.FcpListener#receivedPutSuccessful(net.pterodactylus.fcp.FcpConnection,
1111 * net.pterodactylus.fcp.PutSuccessful)
1113 @SuppressWarnings("synthetic-access")
1114 public void receivedPutSuccessful(FcpConnection fcpConnection, PutSuccessful putSuccessful) {
1115 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1118 String identifier = putSuccessful.getIdentifier();
1119 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
1120 if (downloadCallback != null) {
1121 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
1122 downloadResult.setFinished(true);
1123 downloadResult.setFailed(false);
1124 downloadCallback.progressUpdated();
1126 /* TODO - check inserts */
1127 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier, true);
1128 fireProgressReceived(identifier, highLevelProgress);
1132 * @see net.pterodactylus.fcp.FcpListener#receivedSSKKeypair(net.pterodactylus.fcp.FcpConnection,
1133 * net.pterodactylus.fcp.SSKKeypair)
1135 @SuppressWarnings("synthetic-access")
1136 public void receivedSSKKeypair(FcpConnection fcpConnection, SSKKeypair sskKeypair) {
1137 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1140 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(sskKeypair.getIdentifier());
1141 if (keyGenerationCallback == null) {
1144 KeyGenerationResult keyGenerationResult = keyGenerationCallback.getIntermediaryResult();
1145 keyGenerationResult.setInsertURI(sskKeypair.getInsertURI());
1146 keyGenerationResult.setRequestURI(sskKeypair.getRequestURI());
1147 keyGenerationCallback.setDone();
1151 * @see net.pterodactylus.fcp.FcpListener#receivedSimpleProgress(net.pterodactylus.fcp.FcpConnection,
1152 * net.pterodactylus.fcp.SimpleProgress)
1154 @SuppressWarnings("synthetic-access")
1155 public void receivedSimpleProgress(FcpConnection fcpConnection, SimpleProgress simpleProgress) {
1156 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1159 String identifier = simpleProgress.getIdentifier();
1160 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
1161 if (downloadCallback != null) {
1162 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
1163 downloadResult.setTotalBlocks(simpleProgress.getTotal());
1164 downloadResult.setRequiredBlocks(simpleProgress.getRequired());
1165 downloadResult.setSuccessfulBlocks(simpleProgress.getSucceeded());
1166 downloadResult.setFailedBlocks(simpleProgress.getFailed());
1167 downloadResult.setFatallyFailedBlocks(simpleProgress.getFatallyFailed());
1168 downloadResult.setTotalFinalized(simpleProgress.isFinalizedTotal());
1169 downloadCallback.progressUpdated();
1171 /* TODO - check inserts */
1172 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier, simpleProgress.getTotal(), simpleProgress.getRequired(), simpleProgress.getSucceeded(), simpleProgress.getFailed(), simpleProgress.getFatallyFailed(), simpleProgress.isFinalizedTotal());
1173 fireProgressReceived(identifier, highLevelProgress);
1177 * @see net.pterodactylus.fcp.FcpListener#receivedStartedCompression(net.pterodactylus.fcp.FcpConnection,
1178 * net.pterodactylus.fcp.StartedCompression)
1180 public void receivedStartedCompression(FcpConnection fcpConnection, StartedCompression startedCompression) {
1185 * @see net.pterodactylus.fcp.FcpListener#receivedSubscribedUSKUpdate(net.pterodactylus.fcp.FcpConnection,
1186 * net.pterodactylus.fcp.SubscribedUSKUpdate)
1188 public void receivedSubscribedUSKUpdate(FcpConnection fcpConnection, SubscribedUSKUpdate subscribedUSKUpdate) {
1193 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAComplete(net.pterodactylus.fcp.FcpConnection,
1194 * net.pterodactylus.fcp.TestDDAComplete)
1196 @SuppressWarnings("synthetic-access")
1197 public void receivedTestDDAComplete(FcpConnection fcpConnection, TestDDAComplete testDDAComplete) {
1198 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1201 String directory = testDDAComplete.getDirectory();
1202 if (directory == null) {
1205 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(directory);
1206 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallback.getIntermediaryResult();
1207 cleanFiles(directDiskAccessResult);
1208 directDiskAccessResult.setReadAllowed(testDDAComplete.isReadDirectoryAllowed());
1209 directDiskAccessResult.setWriteAllowed(testDDAComplete.isWriteDirectoryAllowed());
1210 directDiskAccessCallback.setDone();
1214 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAReply(net.pterodactylus.fcp.FcpConnection,
1215 * net.pterodactylus.fcp.TestDDAReply)
1217 @SuppressWarnings("synthetic-access")
1218 public void receivedTestDDAReply(FcpConnection fcpConnection, TestDDAReply testDDAReply) {
1219 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1222 String directory = testDDAReply.getDirectory();
1223 if (directory == null) {
1226 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallbacks.get(directory).getIntermediaryResult();
1227 String readFilename = testDDAReply.getReadFilename();
1228 String readContent = readContent(readFilename);
1229 String writeFilename = testDDAReply.getWriteFilename();
1230 String writeContent = testDDAReply.getContentToWrite();
1231 writeContent(directDiskAccessResult, writeFilename, writeContent);
1232 TestDDAResponse testDDAResponse = new TestDDAResponse(directory, readContent);
1234 fcpConnection.sendMessage(testDDAResponse);
1235 } catch (IOException e) {
1236 /* swallow. I’m verry unhappy about this. */
1241 * @see net.pterodactylus.fcp.FcpListener#receivedURIGenerated(net.pterodactylus.fcp.FcpConnection,
1242 * net.pterodactylus.fcp.URIGenerated)
1244 @SuppressWarnings("synthetic-access")
1245 public void receivedURIGenerated(FcpConnection fcpConnection, URIGenerated uriGenerated) {
1246 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1249 String identifier = uriGenerated.getIdentifier();
1250 /* TODO - check inserts */
1251 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier, uriGenerated.getURI());
1252 fireProgressReceived(identifier, highLevelProgress);
1256 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownNodeIdentifier(net.pterodactylus.fcp.FcpConnection,
1257 * net.pterodactylus.fcp.UnknownNodeIdentifier)
1259 public void receivedUnknownNodeIdentifier(FcpConnection fcpConnection, UnknownNodeIdentifier unknownNodeIdentifier) {
1264 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownPeerNoteType(net.pterodactylus.fcp.FcpConnection,
1265 * net.pterodactylus.fcp.UnknownPeerNoteType)
1267 public void receivedUnknownPeerNoteType(FcpConnection fcpConnection, UnknownPeerNoteType unknownPeerNoteType) {
1272 * @see net.pterodactylus.fcp.FcpListener#receviedFinishedCompression(net.pterodactylus.fcp.FcpConnection,
1273 * net.pterodactylus.fcp.FinishedCompression)
1275 public void receviedFinishedCompression(FcpConnection fcpConnection, FinishedCompression finishedCompression) {