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 FCP connection to the node. */
109 private FcpConnection fcpConnection = null;
111 /** Listeners for high-level client events. */
112 private List<HighLevelClientListener> highLevelClientListeners = Collections.synchronizedList(new ArrayList<HighLevelClientListener>());
114 /** The listener for the connection. */
115 private HighLevelClientFcpListener highLevelClientFcpListener = new HighLevelClientFcpListener();
117 /** The listeners for progress events. */
118 private List<HighLevelProgressListener> highLevelProgressListeners = Collections.synchronizedList(new ArrayList<HighLevelProgressListener>());
120 /** The callback for {@link #connect(String)}. */
121 private HighLevelCallback<ConnectResult> connectCallback;
123 /** Mapping from request identifiers to callbacks. */
124 private Map<String, HighLevelCallback<KeyGenerationResult>> keyGenerationCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<KeyGenerationResult>>());
126 /** Mapping from request identifier to peer list callbacks. */
127 private Map<String, HighLevelCallback<PeerListResult>> peerListCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerListResult>>());
129 /** Mapping from request identifier to peer callbacks. */
130 private Map<String, HighLevelCallback<PeerResult>> peerCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerResult>>());
132 /** Mapping from directories to DDA callbacks. */
133 private Map<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<DirectDiskAccessResult>>());
135 /** Mapping from request identifiers to download callbacks. */
136 private Map<String, HighLevelProgressCallback<DownloadResult>> downloadCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelProgressCallback<DownloadResult>>());
138 /** The callback for {@link #getRequests()}. */
139 private HighLevelCallback<RequestListResult> requestListCallback;
142 * Creates a new high-level client that connects to a node on
143 * <code>localhost</code>.
146 * The name of the client
148 public HighLevelClient(String clientName) {
149 this.clientName = clientName;
157 * Adds the given high-level client listener to list of listeners.
159 * @param highLevelClientListener
160 * The listener to add
162 public void addHighLevelClientListener(HighLevelClientListener highLevelClientListener) {
163 highLevelClientListeners.add(highLevelClientListener);
167 * Removes the given high-level client listener from the list of listeners.
169 * @param highLevelClientListener
170 * The listener to remove
172 public void removeHighLevelClientListener(HighLevelClientListener highLevelClientListener) {
173 highLevelClientListeners.remove(highLevelClientListener);
177 * Notifies all listeners that a client has connected.
179 private void fireClientConnected() {
180 for (HighLevelClientListener highLevelClientListener : highLevelClientListeners) {
181 highLevelClientListener.clientConnected(this);
186 * Notifies all listeners that a client has disconnected.
189 * The exception that caused the disconnect, or <code>null</code>
190 * if there was no exception
192 private void fireClientDisconnected(Throwable throwable) {
193 for (HighLevelClientListener highLevelClientListener : highLevelClientListeners) {
194 highLevelClientListener.clientDisconnected(this, throwable);
199 * Adds a high-level progress listener.
201 * @param highLevelProgressListener
202 * The high-level progress listener to add
204 public void addHighLevelProgressListener(HighLevelProgressListener highLevelProgressListener) {
205 highLevelProgressListeners.add(highLevelProgressListener);
209 * Removes a high-level progress listener.
211 * @param highLevelProgressListener
212 * The high-level progress listener to remove
214 public void removeHighLevelProgressListener(HighLevelProgressListener highLevelProgressListener) {
215 highLevelProgressListeners.remove(highLevelProgressListener);
219 * Notifies all listeners that the request with the given identifier made
223 * The identifier of the request
224 * @param highLevelProgress
225 * The progress of the request
227 private void fireProgressReceived(String identifier, HighLevelProgress highLevelProgress) {
228 for (HighLevelProgressListener highLevelProgressListener : highLevelProgressListeners) {
229 highLevelProgressListener.progressReceived(this, identifier, highLevelProgress);
238 * Returns the FCP connection that backs this high-level client. This method
239 * should be used with care as fiddling around with the FCP connection can
240 * easily break the high-level client if you don’t know what you’re doing!
242 * @return The FCP connection of this client
244 public FcpConnection getFcpConnection() {
245 return fcpConnection;
249 * Returns whether the node is connected.
251 * @return <code>true</code> if the node is currently connected,
252 * <code>false</code> otherwise
254 public boolean isConnected() {
255 return fcpConnection != null;
263 * Connects the client.
266 * The hostname of the node
267 * @return A callback with a connection result
268 * @throws UnknownHostException
269 * if the hostname can not be resolved
270 * @throws IOException
271 * if an I/O error occurs communicating with the node
273 public HighLevelCallback<ConnectResult> connect(String hostname) throws UnknownHostException, IOException {
274 return connect(hostname, 9481);
278 * Connects the client.
281 * The hostname of the node
283 * The port number of the node
284 * @return A callback with a connection result
285 * @throws UnknownHostException
286 * if the hostname can not be resolved
287 * @throws IOException
288 * if an I/O error occurs communicating with the node
290 public HighLevelCallback<ConnectResult> connect(String hostname, int port) throws UnknownHostException, IOException {
291 return connect(InetAddress.getByName(hostname), port);
295 * Connects the client.
298 * The address of the node
300 * The port number of the node
301 * @return A callback with a connection result
302 * @throws IOException
303 * if an I/O error occurs communicating with the node
305 public HighLevelCallback<ConnectResult> connect(InetAddress address, int port) throws IOException {
307 synchronized (this) {
308 fcpConnection = new FcpConnection(address, port);
310 fcpConnection.addFcpListener(highLevelClientFcpListener);
311 fcpConnection.connect();
312 ClientHello clientHello = new ClientHello(clientName);
313 connectCallback = new HighLevelCallback<ConnectResult>(new ConnectResult());
314 fcpConnection.sendMessage(clientHello);
315 return connectCallback;
316 } catch (IOException ioe1) {
317 fcpConnection = null;
323 * Disconnects the client from the node.
325 public void disconnect() {
330 * Generates a new SSK keypair.
332 * @return A callback with the keypair
333 * @throws IOException
334 * if an I/O error occurs communicating with the node
335 * @throws HighLevelException
336 * if the client is not connected
338 public HighLevelCallback<KeyGenerationResult> generateKey() throws IOException, HighLevelException {
340 String identifier = generateIdentifier("generateSSK");
341 GenerateSSK generateSSK = new GenerateSSK(identifier);
342 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = new HighLevelCallback<KeyGenerationResult>(new KeyGenerationResult(identifier));
343 keyGenerationCallbacks.put(identifier, keyGenerationCallback);
344 fcpConnection.sendMessage(generateSSK);
345 return keyGenerationCallback;
349 * Sets whether to watch the global queue.
352 * <code>true</code> to watch the global queue in addition to
353 * the client-local queue, <code>false</code> to only watch the
355 * @throws IOException
356 * if an I/O error occurs communicating with the node
357 * @throws HighLevelException
358 * if the client is not connected
360 public void setWatchGlobal(boolean enabled) throws IOException, HighLevelException {
362 WatchGlobal watchGlobal = new WatchGlobal(enabled);
363 fcpConnection.sendMessage(watchGlobal);
367 * Gets a list of all peers from the node.
369 * @return A callback with the peer list
370 * @throws IOException
371 * if an I/O error occurs with the node
372 * @throws HighLevelException
373 * if the client is not connected
375 public HighLevelCallback<PeerListResult> getPeers() throws IOException, HighLevelException {
377 String identifier = generateIdentifier("listPeers");
378 ListPeers listPeers = new ListPeers(identifier, true, true);
379 HighLevelCallback<PeerListResult> peerListCallback = new HighLevelCallback<PeerListResult>(new PeerListResult(identifier));
380 peerListCallbacks.put(identifier, peerListCallback);
381 fcpConnection.sendMessage(listPeers);
382 return peerListCallback;
386 * Adds the peer whose noderef is stored in the given file.
389 * The name of the file the peer’s noderef is stored in
390 * @return A peer callback
391 * @throws IOException
392 * if an I/O error occurs communicating with the node
393 * @throws HighLevelException
394 * if the client is not connected
396 public HighLevelCallback<PeerResult> addPeer(String nodeRefFile) throws IOException, HighLevelException {
398 String identifier = generateIdentifier("addPeer");
399 AddPeer addPeer = new AddPeer(nodeRefFile);
400 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
401 peerCallbacks.put(identifier, peerCallback);
402 fcpConnection.sendMessage(addPeer);
407 * Adds the peer whose noderef is stored in the given file.
410 * The URL where the peer’s noderef is stored
411 * @return A peer callback
412 * @throws IOException
413 * if an I/O error occurs communicating with the node
414 * @throws HighLevelException
415 * if the client is not connected
417 public HighLevelCallback<PeerResult> addPeer(URL nodeRefURL) throws IOException, HighLevelException {
419 String identifier = generateIdentifier("addPeer");
420 AddPeer addPeer = new AddPeer(nodeRefURL);
421 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
422 peerCallbacks.put(identifier, peerCallback);
423 fcpConnection.sendMessage(addPeer);
428 * Adds the peer whose noderef is stored in the given file.
432 * @return A peer callback
433 * @throws IOException
434 * if an I/O error occurs communicating with the node
435 * @throws HighLevelException
436 * if the client is not connected
438 public HighLevelCallback<PeerResult> addPeer(NodeRef nodeRef) throws IOException, HighLevelException {
440 String identifier = generateIdentifier("addPeer");
441 AddPeer addPeer = new AddPeer(nodeRef);
442 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
443 peerCallbacks.put(identifier, peerCallback);
444 fcpConnection.sendMessage(addPeer);
449 * Checks whether direct disk access for the given directory is possible.
450 * You have to perform this check before you can upload or download anything
451 * from or the disk directly!
454 * The directory to check
456 * Whether you want to read the given directory
458 * Whether you want to write to the given directory
459 * @return A direct disk access callback
460 * @throws IOException
461 * if an I/O error occurs communicating with the node
462 * @throws HighLevelException
463 * if the client is not connected
465 public HighLevelCallback<DirectDiskAccessResult> checkDirectDiskAccess(String directory, boolean wantRead, boolean wantWrite) throws IOException, HighLevelException {
467 TestDDARequest testDDARequest = new TestDDARequest(directory, wantRead, wantWrite);
468 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = new HighLevelCallback<DirectDiskAccessResult>(new DirectDiskAccessResult(directory));
469 directDiskAccessCallbacks.put(directory, directDiskAccessCallback);
470 fcpConnection.sendMessage(testDDARequest);
471 return directDiskAccessCallback;
475 * Starts a download. Files can either be download to disk or streamed from
476 * the node. When downloading to disk you have to perform a direct disk
477 * access check for the directory you want to put the downloaded file in!
479 * @see #checkDirectDiskAccess(String, boolean, boolean)
483 * The filename to save the data to, or <code>null</code> to
484 * retrieve the data as InputStream from the
485 * {@link DownloadResult}
487 * Whether to put the download on the global queue
488 * @return A download result
489 * @throws IOException
490 * if an I/O error occurs communicating with the node
491 * @throws HighLevelException
492 * if the client is not connected
494 public HighLevelProgressCallback<DownloadResult> download(String uri, String filename, boolean global) throws IOException, HighLevelException {
496 String identifier = generateIdentifier("download");
497 ClientGet clientGet = new ClientGet(uri, identifier, (filename == null) ? ReturnType.direct : ReturnType.disk);
498 clientGet.setGlobal(global);
499 HighLevelProgressCallback<DownloadResult> downloadCallback = new HighLevelProgressCallback<DownloadResult>(new DownloadResult(identifier));
500 downloadCallbacks.put(identifier, downloadCallback);
501 fcpConnection.sendMessage(clientGet);
502 return downloadCallback;
506 * Requests a list of all running requests from the node.
508 * @return The request list result
509 * @throws IOException
510 * if an I/O errors communicating with the node
511 * @throws HighLevelException
512 * if the client is not connected
514 public HighLevelCallback<RequestListResult> getRequests() throws IOException, HighLevelException {
516 String identifier = generateIdentifier("list-persistent-requests");
517 ListPersistentRequests listPersistentRequests = new ListPersistentRequests();
518 synchronized (syncObject) {
519 if (requestListCallback != null) {
520 logger.log(Level.SEVERE, "getRequests() called with request still running!");
522 requestListCallback = new HighLevelCallback<RequestListResult>(new RequestListResult(identifier));
524 fcpConnection.sendMessage(listPersistentRequests);
525 return requestListCallback;
533 * Checks whether the client is already connected and throws an exception if
536 * @throws NotConnectedException
537 * if the client is not connected
539 private void checkConnection() throws NotConnectedException {
540 synchronized (this) {
541 if (fcpConnection == null) {
542 throw new NotConnectedException("client is not connected");
548 * Generates an identifier for the given function.
551 * The name of the function
552 * @return An identifier
554 private String generateIdentifier(String function) {
555 return "jFCPlib-" + function + "-" + System.currentTimeMillis();
559 * Disconnects the client from the node, handing the given Throwable to
560 * {@link #fireClientDisconnected(Throwable)}.
563 * The exception that caused the disconnect, or <code>null</code>
564 * if there was no exception
566 private void disconnect(Throwable throwable) {
567 if (fcpConnection != null) {
568 fcpConnection.close();
570 fcpConnection = null;
574 * FCP listener for {@link HighLevelClient}.
576 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
579 private class HighLevelClientFcpListener implements FcpListener {
581 /** Mapping from directory to written file (for cleanup). */
582 private final Map<DirectDiskAccessResult, String> writtenFiles = new HashMap<DirectDiskAccessResult, String>();
585 * Creates a new FCP listener for {@link HighLevelClient}.
587 HighLevelClientFcpListener() {
596 * Searches all callback collections for a callback with the given
597 * identifier and cancels it.
600 * The identifier to search for, or <code>null</code> to
601 * cancel all pending requests
603 @SuppressWarnings("synthetic-access")
604 private void cancelIdentifier(String identifier) {
605 synchronized (syncObject) {
606 if (connectCallback != null) {
607 connectCallback.getIntermediaryResult().setFailed(true);
608 connectCallback.setDone();
609 connectCallback = null;
611 if (requestListCallback != null) {
612 requestListCallback.getIntermediaryResult().setFailed(true);
613 requestListCallback.setDone();
614 requestListCallback = null;
617 if (identifier == null) {
618 /* key generation callbacks */
619 for (Entry<String, HighLevelCallback<KeyGenerationResult>> keyGenerationEntry : keyGenerationCallbacks.entrySet()) {
620 keyGenerationEntry.getValue().getIntermediaryResult().setFailed(true);
621 keyGenerationEntry.getValue().setDone();
623 keyGenerationCallbacks.clear();
624 /* peer list callbacks. */
625 for (Entry<String, HighLevelCallback<PeerListResult>> peerListEntry : peerListCallbacks.entrySet()) {
626 peerListEntry.getValue().getIntermediaryResult().setFailed(true);
627 peerListEntry.getValue().setDone();
629 peerListCallbacks.clear();
630 /* peer callbacks. */
631 for (Entry<String, HighLevelCallback<PeerResult>> peerEntry : peerCallbacks.entrySet()) {
632 peerEntry.getValue().getIntermediaryResult().setFailed(true);
633 peerEntry.getValue().setDone();
635 peerCallbacks.clear();
636 /* direct disk access callbacks. */
637 for (Entry<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessEntry : directDiskAccessCallbacks.entrySet()) {
638 directDiskAccessEntry.getValue().getIntermediaryResult().setFailed(true);
639 directDiskAccessEntry.getValue().setDone();
641 directDiskAccessCallbacks.clear();
642 /* download callbacks. */
643 for (Entry<String, HighLevelProgressCallback<DownloadResult>> downloadEntry : downloadCallbacks.entrySet()) {
644 downloadEntry.getValue().getIntermediaryResult().setFailed(true);
645 downloadEntry.getValue().setDone();
647 downloadCallbacks.clear();
649 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(identifier);
650 if (keyGenerationCallback != null) {
651 keyGenerationCallback.getIntermediaryResult().setFailed(true);
652 keyGenerationCallback.setDone();
655 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
656 if (peerListCallback != null) {
657 peerListCallback.getIntermediaryResult().setFailed(true);
658 peerListCallback.setDone();
661 HighLevelCallback<PeerResult> peerCallback = peerCallbacks.remove(identifier);
662 if (peerCallback != null) {
663 peerCallback.getIntermediaryResult().setFailed(true);
664 peerCallback.setDone();
667 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(identifier);
668 if (directDiskAccessCallback != null) {
669 directDiskAccessCallback.getIntermediaryResult().setFailed(true);
670 directDiskAccessCallback.setDone();
673 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
674 if (downloadCallback != null) {
675 downloadCallback.getIntermediaryResult().setFailed(true);
676 downloadCallback.setDone();
683 * Reads the given file and returns the first line of the file.
685 * @param readFilename
686 * The name of the file to read
687 * @return The content of the file
689 private String readContent(String readFilename) {
690 FileReader fileReader = null;
691 BufferedReader bufferedFileReader = null;
693 fileReader = new FileReader(readFilename);
694 bufferedFileReader = new BufferedReader(fileReader);
695 String content = bufferedFileReader.readLine();
697 } catch (IOException ioe1) {
700 FcpUtils.close(bufferedFileReader);
701 FcpUtils.close(fileReader);
707 * Writes the given content to the given file.
709 * @param directDiskAccessResult
711 * @param writeFilename
712 * The name of the file to write to
713 * @param writeContent
714 * The content to write to the file
716 private void writeContent(DirectDiskAccessResult directDiskAccessResult, String writeFilename, String writeContent) {
717 if ((writeFilename == null) || (writeContent == null)) {
720 writtenFiles.put(directDiskAccessResult, writeFilename);
721 FileWriter fileWriter = null;
723 fileWriter = new FileWriter(writeFilename);
724 fileWriter.write(writeContent);
725 } catch (IOException ioe1) {
728 FcpUtils.close(fileWriter);
733 * Cleans up any files that written for the given result.
735 * @param directDiskAccessResult
736 * The direct disk access result
738 @SuppressWarnings("synthetic-access")
739 private void cleanFiles(DirectDiskAccessResult directDiskAccessResult) {
740 String writeFilename = writtenFiles.remove(directDiskAccessResult);
741 if (writeFilename != null) {
742 if (!new File(writeFilename).delete()) {
743 logger.warning("could not delete " + writeFilename);
749 // INTERFACE FcpListener
753 * @see net.pterodactylus.fcp.FcpListener#connectionClosed(net.pterodactylus.fcp.FcpConnection,
756 @SuppressWarnings("synthetic-access")
757 public void connectionClosed(FcpConnection fcpConnection, Throwable throwable) {
758 if (fcpConnection != HighLevelClient.this.fcpConnection) {
761 cancelIdentifier(null);
762 disconnect(throwable);
763 fireClientDisconnected(throwable);
767 * @see net.pterodactylus.fcp.FcpListener#receivedAllData(net.pterodactylus.fcp.FcpConnection,
768 * net.pterodactylus.fcp.AllData)
770 public void receivedAllData(FcpConnection fcpConnection, AllData allData) {
775 * @see net.pterodactylus.fcp.FcpListener#receivedCloseConnectionDuplicateClientName(net.pterodactylus.fcp.FcpConnection,
776 * net.pterodactylus.fcp.CloseConnectionDuplicateClientName)
778 public void receivedCloseConnectionDuplicateClientName(FcpConnection fcpConnection, CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) {
783 * @see net.pterodactylus.fcp.FcpListener#receivedConfigData(net.pterodactylus.fcp.FcpConnection,
784 * net.pterodactylus.fcp.ConfigData)
786 public void receivedConfigData(FcpConnection fcpConnection, ConfigData configData) {
791 * @see net.pterodactylus.fcp.FcpListener#receivedDataFound(net.pterodactylus.fcp.FcpConnection,
792 * net.pterodactylus.fcp.DataFound)
794 public void receivedDataFound(FcpConnection fcpConnection, DataFound dataFound) {
795 if (fcpConnection != HighLevelClient.this.fcpConnection) {
798 String identifier = dataFound.getIdentifier();
799 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
800 if (downloadCallback != null) {
801 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
802 downloadResult.setFinished(true);
803 downloadResult.setFailed(false);
804 downloadCallback.progressUpdated();
805 downloadCallback.setDone();
807 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier, true);
808 fireProgressReceived(identifier , highLevelProgress);
812 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeerNotes(net.pterodactylus.fcp.FcpConnection,
813 * net.pterodactylus.fcp.EndListPeerNotes)
815 public void receivedEndListPeerNotes(FcpConnection fcpConnection, EndListPeerNotes endListPeerNotes) {
820 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeers(net.pterodactylus.fcp.FcpConnection,
821 * net.pterodactylus.fcp.EndListPeers)
823 @SuppressWarnings("synthetic-access")
824 public void receivedEndListPeers(FcpConnection fcpConnection, EndListPeers endListPeers) {
825 if (fcpConnection != HighLevelClient.this.fcpConnection) {
828 String identifier = endListPeers.getIdentifier();
829 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
830 if (peerListCallback == null) {
833 peerListCallback.setDone();
837 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPersistentRequests(net.pterodactylus.fcp.FcpConnection,
838 * net.pterodactylus.fcp.EndListPersistentRequests)
840 @SuppressWarnings("synthetic-access")
841 public void receivedEndListPersistentRequests(FcpConnection fcpConnection, EndListPersistentRequests endListPersistentRequests) {
842 if (fcpConnection != HighLevelClient.this.fcpConnection) {
845 synchronized (syncObject) {
846 if (HighLevelClient.this.requestListCallback == null) {
847 logger.log(Level.WARNING, "got EndListPersistentRequests without running request!");
850 requestListCallback.setDone();
851 requestListCallback = null;
856 * @see net.pterodactylus.fcp.FcpListener#receivedFCPPluginReply(net.pterodactylus.fcp.FcpConnection,
857 * net.pterodactylus.fcp.FCPPluginReply)
859 public void receivedFCPPluginReply(FcpConnection fcpConnection, FCPPluginReply fcpPluginReply) {
864 * @see net.pterodactylus.fcp.FcpListener#receivedGetFailed(net.pterodactylus.fcp.FcpConnection,
865 * net.pterodactylus.fcp.GetFailed)
867 @SuppressWarnings("synthetic-access")
868 public void receivedGetFailed(FcpConnection fcpConnection, GetFailed getFailed) {
869 if (fcpConnection != HighLevelClient.this.fcpConnection) {
872 String identifier = getFailed.getIdentifier();
873 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
874 if (downloadCallback != null) {
875 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
876 downloadResult.setFailed(true);
877 downloadResult.setFinished(true);
878 downloadCallback.setDone();
881 /* unknown identifier? */
882 logger.warning("unknown identifier for GetFailed: " + identifier);
886 * @see net.pterodactylus.fcp.FcpListener#receivedIdentifierCollision(net.pterodactylus.fcp.FcpConnection,
887 * net.pterodactylus.fcp.IdentifierCollision)
889 public void receivedIdentifierCollision(FcpConnection fcpConnection, IdentifierCollision identifierCollision) {
894 * @see net.pterodactylus.fcp.FcpListener#receivedMessage(net.pterodactylus.fcp.FcpConnection,
895 * net.pterodactylus.fcp.FcpMessage)
897 public void receivedMessage(FcpConnection fcpConnection, FcpMessage fcpMessage) {
902 * @see net.pterodactylus.fcp.FcpListener#receivedNodeData(net.pterodactylus.fcp.FcpConnection,
903 * net.pterodactylus.fcp.NodeData)
905 public void receivedNodeData(FcpConnection fcpConnection, NodeData nodeData) {
910 * @see net.pterodactylus.fcp.FcpListener#receivedNodeHello(net.pterodactylus.fcp.FcpConnection,
911 * net.pterodactylus.fcp.NodeHello)
913 @SuppressWarnings("synthetic-access")
914 public void receivedNodeHello(FcpConnection fcpConnection, NodeHello nodeHello) {
915 if (fcpConnection != HighLevelClient.this.fcpConnection) {
918 synchronized (syncObject) {
919 connectCallback.getIntermediaryResult().setFailed(false);
920 connectCallback.setDone();
921 connectCallback = null;
923 fireClientConnected();
927 * @see net.pterodactylus.fcp.FcpListener#receivedPeer(net.pterodactylus.fcp.FcpConnection,
928 * net.pterodactylus.fcp.Peer)
930 @SuppressWarnings("synthetic-access")
931 public void receivedPeer(FcpConnection fcpConnection, Peer peer) {
932 if (fcpConnection != HighLevelClient.this.fcpConnection) {
935 String identifier = peer.getIdentifier();
936 if (identifier == null) {
939 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.get(identifier);
940 if (peerListCallback != null) {
941 peerListCallback.getIntermediaryResult().addPeer(peer);
944 HighLevelCallback<PeerResult> peerResult = peerCallbacks.remove(identifier);
945 if (peerResult != null) {
946 peerResult.getIntermediaryResult().setPeer(peer);
947 peerResult.setDone();
950 logger.warning("got Peer message with unknown identifier: " + identifier);
954 * @see net.pterodactylus.fcp.FcpListener#receivedPeerNote(net.pterodactylus.fcp.FcpConnection,
955 * net.pterodactylus.fcp.PeerNote)
957 public void receivedPeerNote(FcpConnection fcpConnection, PeerNote peerNote) {
962 * @see net.pterodactylus.fcp.FcpListener#receivedPeerRemoved(net.pterodactylus.fcp.FcpConnection,
963 * net.pterodactylus.fcp.PeerRemoved)
965 public void receivedPeerRemoved(FcpConnection fcpConnection, PeerRemoved peerRemoved) {
970 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentGet(net.pterodactylus.fcp.FcpConnection,
971 * net.pterodactylus.fcp.PersistentGet)
973 @SuppressWarnings("synthetic-access")
974 public void receivedPersistentGet(FcpConnection fcpConnection, PersistentGet persistentGet) {
975 if (fcpConnection != HighLevelClient.this.fcpConnection) {
978 synchronized (syncObject) {
979 if (requestListCallback != null) {
980 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
981 requestListResult.addRequestResult(new GetRequestResult(persistentGet));
985 String identifier = persistentGet.getIdentifier();
986 if (downloadCallbacks.containsKey(identifier)) {
993 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPut(net.pterodactylus.fcp.FcpConnection,
994 * net.pterodactylus.fcp.PersistentPut)
996 @SuppressWarnings("synthetic-access")
997 public void receivedPersistentPut(FcpConnection fcpConnection, PersistentPut persistentPut) {
998 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1001 synchronized (syncObject) {
1002 if (requestListCallback != null) {
1003 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
1004 requestListResult.addRequestResult(new PutRequestResult(persistentPut));
1011 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPutDir(net.pterodactylus.fcp.FcpConnection,
1012 * net.pterodactylus.fcp.PersistentPutDir)
1014 @SuppressWarnings("synthetic-access")
1015 public void receivedPersistentPutDir(FcpConnection fcpConnection, PersistentPutDir persistentPutDir) {
1016 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1019 synchronized (syncObject) {
1020 if (requestListCallback != null) {
1021 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
1022 requestListResult.addRequestResult(new PutDirRequestResult(persistentPutDir));
1029 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestModified(net.pterodactylus.fcp.FcpConnection,
1030 * net.pterodactylus.fcp.PersistentRequestModified)
1032 public void receivedPersistentRequestModified(FcpConnection fcpConnection, PersistentRequestModified persistentRequestModified) {
1037 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestRemoved(net.pterodactylus.fcp.FcpConnection,
1038 * net.pterodactylus.fcp.PersistentRequestRemoved)
1040 public void receivedPersistentRequestRemoved(FcpConnection fcpConnection, PersistentRequestRemoved persistentRequestRemoved) {
1045 * @see net.pterodactylus.fcp.FcpListener#receivedPluginInfo(net.pterodactylus.fcp.FcpConnection,
1046 * net.pterodactylus.fcp.PluginInfo)
1048 public void receivedPluginInfo(FcpConnection fcpConnection, PluginInfo pluginInfo) {
1053 * @see net.pterodactylus.fcp.FcpListener#receivedProtocolError(net.pterodactylus.fcp.FcpConnection,
1054 * net.pterodactylus.fcp.ProtocolError)
1056 @SuppressWarnings("synthetic-access")
1057 public void receivedProtocolError(FcpConnection fcpConnection, ProtocolError protocolError) {
1058 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1061 String identifier = protocolError.getIdentifier();
1062 if (identifier == null) {
1065 cancelIdentifier(identifier);
1069 * @see net.pterodactylus.fcp.FcpListener#receivedPutFailed(net.pterodactylus.fcp.FcpConnection,
1070 * net.pterodactylus.fcp.PutFailed)
1072 public void receivedPutFailed(FcpConnection fcpConnection, PutFailed putFailed) {
1073 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1076 String identifier = putFailed.getIdentifier();
1077 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
1078 if (downloadCallback != null) {
1079 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
1080 downloadResult.setFailed(true);
1081 downloadResult.setFinished(true);
1082 downloadCallback.progressUpdated();
1083 downloadCallback.setDone();
1085 /* TODO - check inserts */
1086 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier, true);
1087 fireProgressReceived(identifier, highLevelProgress);
1091 * @see net.pterodactylus.fcp.FcpListener#receivedPutFetchable(net.pterodactylus.fcp.FcpConnection,
1092 * net.pterodactylus.fcp.PutFetchable)
1094 public void receivedPutFetchable(FcpConnection fcpConnection, PutFetchable putFetchable) {
1095 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1098 String identifier = putFetchable.getIdentifier();
1099 /* TODO - check inserts */
1100 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier);
1101 highLevelProgress.setFetchable(true);
1102 fireProgressReceived(identifier, highLevelProgress);
1106 * @see net.pterodactylus.fcp.FcpListener#receivedPutSuccessful(net.pterodactylus.fcp.FcpConnection,
1107 * net.pterodactylus.fcp.PutSuccessful)
1109 public void receivedPutSuccessful(FcpConnection fcpConnection, PutSuccessful putSuccessful) {
1110 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1113 String identifier = putSuccessful.getIdentifier();
1114 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
1115 if (downloadCallback != null) {
1116 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
1117 downloadResult.setFinished(true);
1118 downloadResult.setFailed(false);
1119 downloadCallback.progressUpdated();
1121 /* TODO - check inserts */
1122 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier, true);
1123 fireProgressReceived(identifier, highLevelProgress);
1127 * @see net.pterodactylus.fcp.FcpListener#receivedSSKKeypair(net.pterodactylus.fcp.FcpConnection,
1128 * net.pterodactylus.fcp.SSKKeypair)
1130 @SuppressWarnings("synthetic-access")
1131 public void receivedSSKKeypair(FcpConnection fcpConnection, SSKKeypair sskKeypair) {
1132 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1135 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(sskKeypair.getIdentifier());
1136 if (keyGenerationCallback == null) {
1139 KeyGenerationResult keyGenerationResult = keyGenerationCallback.getIntermediaryResult();
1140 keyGenerationResult.setInsertURI(sskKeypair.getInsertURI());
1141 keyGenerationResult.setRequestURI(sskKeypair.getRequestURI());
1142 keyGenerationCallback.setDone();
1146 * @see net.pterodactylus.fcp.FcpListener#receivedSimpleProgress(net.pterodactylus.fcp.FcpConnection,
1147 * net.pterodactylus.fcp.SimpleProgress)
1149 @SuppressWarnings("synthetic-access")
1150 public void receivedSimpleProgress(FcpConnection fcpConnection, SimpleProgress simpleProgress) {
1151 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1154 String identifier = simpleProgress.getIdentifier();
1155 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
1156 if (downloadCallback != null) {
1157 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
1158 downloadResult.setTotalBlocks(simpleProgress.getTotal());
1159 downloadResult.setRequiredBlocks(simpleProgress.getRequired());
1160 downloadResult.setSuccessfulBlocks(simpleProgress.getSucceeded());
1161 downloadResult.setFailedBlocks(simpleProgress.getFailed());
1162 downloadResult.setFatallyFailedBlocks(simpleProgress.getFatallyFailed());
1163 downloadResult.setTotalFinalized(simpleProgress.isFinalizedTotal());
1164 downloadCallback.progressUpdated();
1166 /* TODO - check inserts */
1167 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier, simpleProgress.getTotal(), simpleProgress.getRequired(), simpleProgress.getSucceeded(), simpleProgress.getFailed(), simpleProgress.getFatallyFailed(), simpleProgress.isFinalizedTotal());
1168 fireProgressReceived(identifier, highLevelProgress);
1172 * @see net.pterodactylus.fcp.FcpListener#receivedStartedCompression(net.pterodactylus.fcp.FcpConnection,
1173 * net.pterodactylus.fcp.StartedCompression)
1175 public void receivedStartedCompression(FcpConnection fcpConnection, StartedCompression startedCompression) {
1180 * @see net.pterodactylus.fcp.FcpListener#receivedSubscribedUSKUpdate(net.pterodactylus.fcp.FcpConnection,
1181 * net.pterodactylus.fcp.SubscribedUSKUpdate)
1183 public void receivedSubscribedUSKUpdate(FcpConnection fcpConnection, SubscribedUSKUpdate subscribedUSKUpdate) {
1188 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAComplete(net.pterodactylus.fcp.FcpConnection,
1189 * net.pterodactylus.fcp.TestDDAComplete)
1191 @SuppressWarnings("synthetic-access")
1192 public void receivedTestDDAComplete(FcpConnection fcpConnection, TestDDAComplete testDDAComplete) {
1193 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1196 String directory = testDDAComplete.getDirectory();
1197 if (directory == null) {
1200 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(directory);
1201 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallback.getIntermediaryResult();
1202 cleanFiles(directDiskAccessResult);
1203 directDiskAccessResult.setReadAllowed(testDDAComplete.isReadDirectoryAllowed());
1204 directDiskAccessResult.setWriteAllowed(testDDAComplete.isWriteDirectoryAllowed());
1205 directDiskAccessCallback.setDone();
1209 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAReply(net.pterodactylus.fcp.FcpConnection,
1210 * net.pterodactylus.fcp.TestDDAReply)
1212 @SuppressWarnings("synthetic-access")
1213 public void receivedTestDDAReply(FcpConnection fcpConnection, TestDDAReply testDDAReply) {
1214 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1217 String directory = testDDAReply.getDirectory();
1218 if (directory == null) {
1221 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallbacks.get(directory).getIntermediaryResult();
1222 String readFilename = testDDAReply.getReadFilename();
1223 String readContent = readContent(readFilename);
1224 String writeFilename = testDDAReply.getWriteFilename();
1225 String writeContent = testDDAReply.getContentToWrite();
1226 writeContent(directDiskAccessResult, writeFilename, writeContent);
1227 TestDDAResponse testDDAResponse = new TestDDAResponse(directory, readContent);
1229 fcpConnection.sendMessage(testDDAResponse);
1230 } catch (IOException e) {
1231 /* swallow. I’m verry unhappy about this. */
1236 * @see net.pterodactylus.fcp.FcpListener#receivedURIGenerated(net.pterodactylus.fcp.FcpConnection,
1237 * net.pterodactylus.fcp.URIGenerated)
1239 public void receivedURIGenerated(FcpConnection fcpConnection, URIGenerated uriGenerated) {
1244 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownNodeIdentifier(net.pterodactylus.fcp.FcpConnection,
1245 * net.pterodactylus.fcp.UnknownNodeIdentifier)
1247 public void receivedUnknownNodeIdentifier(FcpConnection fcpConnection, UnknownNodeIdentifier unknownNodeIdentifier) {
1252 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownPeerNoteType(net.pterodactylus.fcp.FcpConnection,
1253 * net.pterodactylus.fcp.UnknownPeerNoteType)
1255 public void receivedUnknownPeerNoteType(FcpConnection fcpConnection, UnknownPeerNoteType unknownPeerNoteType) {
1260 * @see net.pterodactylus.fcp.FcpListener#receviedFinishedCompression(net.pterodactylus.fcp.FcpConnection,
1261 * net.pterodactylus.fcp.FinishedCompression)
1263 public void receviedFinishedCompression(FcpConnection fcpConnection, FinishedCompression finishedCompression) {