add identifier to all requests
authorDavid ‘Bombe’ Roden <bombe@freenetproject.org>
Thu, 17 Apr 2008 00:34:07 +0000 (00:34 +0000)
committerDavid ‘Bombe’ Roden <bombe@freenetproject.org>
Thu, 17 Apr 2008 00:34:07 +0000 (00:34 +0000)
start implementation of download

git-svn-id: http://trooper/svn/projects/jFCPlib/branch/high-level-client@839 c3eda9e8-030b-0410-8277-bc7414b0a119

16 files changed:
src/net/pterodactylus/fcp/highlevel/ConnectResult.java
src/net/pterodactylus/fcp/highlevel/DirectDiskAccessResult.java
src/net/pterodactylus/fcp/highlevel/DownloadResult.java [new file with mode: 0644]
src/net/pterodactylus/fcp/highlevel/HighLevelCallback.java
src/net/pterodactylus/fcp/highlevel/HighLevelCallbackListener.java
src/net/pterodactylus/fcp/highlevel/HighLevelClient.java
src/net/pterodactylus/fcp/highlevel/HighLevelContinuousCallback.java [deleted file]
src/net/pterodactylus/fcp/highlevel/HighLevelContinuousCallbackListener.java [deleted file]
src/net/pterodactylus/fcp/highlevel/HighLevelContinuousResult.java [deleted file]
src/net/pterodactylus/fcp/highlevel/HighLevelProgress.java [new file with mode: 0644]
src/net/pterodactylus/fcp/highlevel/HighLevelProgressCallback.java [new file with mode: 0644]
src/net/pterodactylus/fcp/highlevel/HighLevelProgressCallbackListener.java [new file with mode: 0644]
src/net/pterodactylus/fcp/highlevel/HighLevelResult.java
src/net/pterodactylus/fcp/highlevel/KeyGenerationResult.java
src/net/pterodactylus/fcp/highlevel/PeerListResult.java
src/net/pterodactylus/fcp/highlevel/PeerResult.java

index d922292..1236038 100644 (file)
@@ -34,6 +34,7 @@ public class ConnectResult extends HighLevelResult {
         * Package-private constructor.
         */
        ConnectResult() {
+               super(null);
        }
 
        /**
index fc841d2..84f33c3 100644 (file)
@@ -35,8 +35,12 @@ public class DirectDiskAccessResult extends HighLevelResult {
 
        /**
         * Package-private constructor.
+        * 
+        * @param identifier
+        *            The identifier of the request
         */
-       DirectDiskAccessResult() {
+       DirectDiskAccessResult(String identifier) {
+               super(identifier);
        }
 
        /**
diff --git a/src/net/pterodactylus/fcp/highlevel/DownloadResult.java b/src/net/pterodactylus/fcp/highlevel/DownloadResult.java
new file mode 100644 (file)
index 0000000..c6a237a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * jFCPlib-high-level-client - DownloadResult.java -
+ * Copyright © 2008 David Roden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.fcp.highlevel;
+
+/**
+ * The result of a download.
+ * 
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ * @version $Id$
+ */
+public class DownloadResult extends HighLevelProgress {
+
+       /**
+        * Package-private constructor.
+        * 
+        * @param identifier
+        *            The identifier of the request
+        */
+       public DownloadResult(String identifier) {
+               super(identifier);
+       }
+
+}
index 27fc6bb..ac448a6 100644 (file)
@@ -35,13 +35,13 @@ import java.util.List;
 public class HighLevelCallback<R extends HighLevelResult> {
 
        /** Object used for synchronization. */
-       private final Object syncObject = new Object();
+       protected final Object syncObject = new Object();
 
        /** The list of callback listeners. */
        private final List<HighLevelCallbackListener<R>> highLevelCallbackListeners = Collections.synchronizedList(new ArrayList<HighLevelCallbackListener<R>>());
 
        /** Whether the result is complete. */
-       private boolean resultComplete = false;
+       protected boolean resultComplete = false;
 
        /** The result of the operation. */
        private R result = null;
index 36a2cc4..78d41b0 100644 (file)
@@ -26,7 +26,7 @@ import java.util.EventListener;
  * {@link HighLevelCallback} received a result.
  * 
  * @param <R>
- *            The type of the high-level operation result
+ *            The type of the high-level operation progress
  * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
  * @version $Id$
  */
index 089c205..0ec6da6 100644 (file)
@@ -35,6 +35,7 @@ import java.util.logging.Logger;
 
 import net.pterodactylus.fcp.AddPeer;
 import net.pterodactylus.fcp.AllData;
+import net.pterodactylus.fcp.ClientGet;
 import net.pterodactylus.fcp.ClientHello;
 import net.pterodactylus.fcp.CloseConnectionDuplicateClientName;
 import net.pterodactylus.fcp.ConfigData;
@@ -68,6 +69,7 @@ import net.pterodactylus.fcp.ProtocolError;
 import net.pterodactylus.fcp.PutFailed;
 import net.pterodactylus.fcp.PutFetchable;
 import net.pterodactylus.fcp.PutSuccessful;
+import net.pterodactylus.fcp.ReturnType;
 import net.pterodactylus.fcp.SSKKeypair;
 import net.pterodactylus.fcp.SimpleProgress;
 import net.pterodactylus.fcp.StartedCompression;
@@ -125,6 +127,9 @@ public class HighLevelClient {
        /** Mapping from directories to DDA callbacks. */
        private Map<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<DirectDiskAccessResult>>());
 
+       /** Mapping from request identifiers to download callbacks. */
+       private Map<String, HighLevelProgressCallback<DownloadResult>> downloadCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelProgressCallback<DownloadResult>>());
+
        /**
         * Creates a new high-level client that connects to a node on
         * <code>localhost</code>.
@@ -227,7 +232,7 @@ public class HighLevelClient {
        public HighLevelCallback<KeyGenerationResult> generateKey() throws IOException {
                String identifier = generateIdentifier("generateSSK");
                GenerateSSK generateSSK = new GenerateSSK(identifier);
-               HighLevelCallback<KeyGenerationResult> keyGenerationCallback = new HighLevelCallback<KeyGenerationResult>(new KeyGenerationResult());
+               HighLevelCallback<KeyGenerationResult> keyGenerationCallback = new HighLevelCallback<KeyGenerationResult>(new KeyGenerationResult(identifier));
                keyGenerationCallbacks.put(identifier, keyGenerationCallback);
                fcpConnection.sendMessage(generateSSK);
                return keyGenerationCallback;
@@ -243,7 +248,7 @@ public class HighLevelClient {
        public HighLevelCallback<PeerListResult> getPeers() throws IOException {
                String identifier = generateIdentifier("listPeers");
                ListPeers listPeers = new ListPeers(identifier, true, true);
-               HighLevelCallback<PeerListResult> peerListCallback = new HighLevelCallback<PeerListResult>(new PeerListResult());
+               HighLevelCallback<PeerListResult> peerListCallback = new HighLevelCallback<PeerListResult>(new PeerListResult(identifier));
                peerListCallbacks.put(identifier, peerListCallback);
                fcpConnection.sendMessage(listPeers);
                return peerListCallback;
@@ -261,7 +266,7 @@ public class HighLevelClient {
        public HighLevelCallback<PeerResult> addPeer(String nodeRefFile) throws IOException {
                String identifier = generateIdentifier("addPeer");
                AddPeer addPeer = new AddPeer(nodeRefFile);
-               HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult());
+               HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
                peerCallbacks.put(identifier, peerCallback);
                fcpConnection.sendMessage(addPeer);
                return peerCallback;
@@ -279,7 +284,7 @@ public class HighLevelClient {
        public HighLevelCallback<PeerResult> addPeer(URL nodeRefURL) throws IOException {
                String identifier = generateIdentifier("addPeer");
                AddPeer addPeer = new AddPeer(nodeRefURL);
-               HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult());
+               HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
                peerCallbacks.put(identifier, peerCallback);
                fcpConnection.sendMessage(addPeer);
                return peerCallback;
@@ -297,7 +302,7 @@ public class HighLevelClient {
        public HighLevelCallback<PeerResult> addPeer(NodeRef nodeRef) throws IOException {
                String identifier = generateIdentifier("addPeer");
                AddPeer addPeer = new AddPeer(nodeRef);
-               HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult());
+               HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
                peerCallbacks.put(identifier, peerCallback);
                fcpConnection.sendMessage(addPeer);
                return peerCallback;
@@ -319,12 +324,40 @@ public class HighLevelClient {
         */
        public HighLevelCallback<DirectDiskAccessResult> checkDirectDiskAccess(String directory, boolean wantRead, boolean wantWrite) throws IOException {
                TestDDARequest testDDARequest = new TestDDARequest(directory, wantRead, wantWrite);
-               HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = new HighLevelCallback<DirectDiskAccessResult>(new DirectDiskAccessResult());
+               HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = new HighLevelCallback<DirectDiskAccessResult>(new DirectDiskAccessResult(directory));
                directDiskAccessCallbacks.put(directory, directDiskAccessCallback);
                fcpConnection.sendMessage(testDDARequest);
                return directDiskAccessCallback;
        }
 
+       /**
+        * Starts a download. Files can either be download to disk or streamed from
+        * the node. When downloading to disk you have to perform a direct disk
+        * access check for the directory you want to put the downloaded file in!
+        * 
+        * @see #checkDirectDiskAccess(String, boolean, boolean)
+        * @param uri
+        *            The URI to get
+        * @param filename
+        *            The filename to save the data to, or <code>null</code> to
+        *            retrieve the data as InputStream from the
+        *            {@link DownloadResult}
+        * @param global
+        *            Whether to put the download on the global queue
+        * @return A download result
+        * @throws IOException
+        *             if an I/O error occurs communicating with the node
+        */
+       public HighLevelProgressCallback<DownloadResult> download(String uri, String filename, boolean global) throws IOException {
+               String identifier = generateIdentifier("download");
+               ClientGet clientGet = new ClientGet(uri, identifier, (filename == null) ? ReturnType.direct : ReturnType.disk);
+               clientGet.setGlobal(global);
+               HighLevelProgressCallback<DownloadResult> downloadCallback = new HighLevelProgressCallback<DownloadResult>(new DownloadResult(identifier));
+               downloadCallbacks.put(identifier, downloadCallback);
+               fcpConnection.sendMessage(clientGet);
+               return downloadCallback;
+       }
+
        //
        // PRIVATE METHODS
        //
@@ -403,6 +436,12 @@ public class HighLevelClient {
                                        directDiskAccessEntry.getValue().setDone();
                                }
                                directDiskAccessCallbacks.clear();
+                               /* download callbacks. */
+                               for (Entry<String, HighLevelProgressCallback<DownloadResult>> downloadEntry: downloadCallbacks.entrySet()) {
+                                       downloadEntry.getValue().getIntermediaryResult().setFailed(true);
+                                       downloadEntry.getValue().setDone();
+                               }
+                               downloadCallbacks.clear();
                        } else {
                                HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(identifier);
                                if (keyGenerationCallback != null) {
@@ -428,6 +467,12 @@ public class HighLevelClient {
                                        directDiskAccessCallback.setDone();
                                        return;
                                }
+                               HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
+                               if (downloadCallback != null) {
+                                       downloadCallback.getIntermediaryResult().setFailed(true);
+                                       downloadCallback.setDone();
+                                       return;
+                               }
                        }
                }
 
@@ -582,7 +627,20 @@ public class HighLevelClient {
                 * @see net.pterodactylus.fcp.FcpListener#receivedGetFailed(net.pterodactylus.fcp.FcpConnection,
                 *      net.pterodactylus.fcp.GetFailed)
                 */
+               @SuppressWarnings("synthetic-access")
                public void receivedGetFailed(FcpConnection fcpConnection, GetFailed getFailed) {
+                       if (fcpConnection != HighLevelClient.this.fcpConnection) {
+                               return;
+                       }
+                       String identifier = getFailed.getIdentifier();
+                       HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
+                       if (downloadCallback != null) {
+                               downloadCallback.getIntermediaryResult().setFailed(true);
+                               downloadCallback.setDone();
+                               return;
+                       }
+                       /* unknown identifier? */
+                       logger.warning("unknown identifier for GetFailed: " + identifier);
                }
 
                /**
@@ -644,7 +702,9 @@ public class HighLevelClient {
                        if (peerResult != null) {
                                peerResult.getIntermediaryResult().setPeer(peer);
                                peerResult.setDone();
+                               return;
                        }
+                       logger.warning("got Peer message with unknown identifier: " + identifier);
                }
 
                /**
@@ -665,7 +725,16 @@ public class HighLevelClient {
                 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentGet(net.pterodactylus.fcp.FcpConnection,
                 *      net.pterodactylus.fcp.PersistentGet)
                 */
+               @SuppressWarnings("synthetic-access")
                public void receivedPersistentGet(FcpConnection fcpConnection, PersistentGet persistentGet) {
+                       if (fcpConnection != HighLevelClient.this.fcpConnection) {
+                               return;
+                       }
+                       String identifier = persistentGet.getIdentifier();
+                       if (downloadCallbacks.containsKey(identifier)) {
+                               /* ignore, because a download does not care about this. */
+                               return;
+                       }
                }
 
                /**
@@ -763,7 +832,26 @@ public class HighLevelClient {
                 * @see net.pterodactylus.fcp.FcpListener#receivedSimpleProgress(net.pterodactylus.fcp.FcpConnection,
                 *      net.pterodactylus.fcp.SimpleProgress)
                 */
+               @SuppressWarnings("synthetic-access")
                public void receivedSimpleProgress(FcpConnection fcpConnection, SimpleProgress simpleProgress) {
+                       if (fcpConnection != HighLevelClient.this.fcpConnection) {
+                               return;
+                       }
+                       String identifier = simpleProgress.getIdentifier();
+                       HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
+                       if (downloadCallback != null) {
+                               DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
+                               downloadResult.setTotalBlocks(simpleProgress.getTotal());
+                               downloadResult.setRequiredBlocks(simpleProgress.getRequired());
+                               downloadResult.setSuccessfulBlocks(simpleProgress.getSucceeded());
+                               downloadResult.setFailedBlocks(simpleProgress.getFailed());
+                               downloadResult.setFatallyFailedBlocks(simpleProgress.getFatallyFailed());
+                               downloadResult.setTotalFinalized(simpleProgress.isFinalizedTotal());
+                               downloadCallback.progressUpdated();
+                               return;
+                       }
+                       /* unknown identifier? */
+                       logger.warning("unknown identifier for SimpleProgress: " + identifier);
                }
 
                /**
diff --git a/src/net/pterodactylus/fcp/highlevel/HighLevelContinuousCallback.java b/src/net/pterodactylus/fcp/highlevel/HighLevelContinuousCallback.java
deleted file mode 100644 (file)
index 4f82b70..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * jFCPlib-high-level-client - HighLevelContinousCallback.java -
- * Copyright © 2008 David Roden
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-package net.pterodactylus.fcp.highlevel;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Callback for an operation that sends progress messages before completion.
- * 
- * @param <R>
- *            The type of the continuous result
- * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
- * @version $Id$
- */
-public class HighLevelContinuousCallback<R extends HighLevelContinuousResult> extends HighLevelCallback<R> {
-
-       /** Callback listeners. */
-       private final List<HighLevelContinuousCallbackListener<R>> highLevelContinuousCallbackListeners = new ArrayList<HighLevelContinuousCallbackListener<R>>();
-
-       /** List of progress results. */
-       private final List<R> progressQueue = new ArrayList<R>();
-
-       /**
-        * Creates a new continuous callback with the given result.
-        * 
-        * @see HighLevelCallback#HighLevelCallback(HighLevelResult)
-        * @param progress
-        *            The result of the operation
-        */
-       HighLevelContinuousCallback(R progress) {
-               super(progress);
-       }
-
-       //
-       // EVENT MANAGEMENT
-       //
-
-       /**
-        * Adds a callback listener to this callback. If this callback already has
-        * some progress results, the listener is notified immediately.
-        * 
-        * @param highLevelContinuousCallbackListener
-        *            The callback listener to add
-        */
-       public void addHighLevelContinuousCallbackListener(HighLevelContinuousCallbackListener<R> highLevelContinuousCallbackListener) {
-               highLevelContinuousCallbackListeners.add(highLevelContinuousCallbackListener);
-               synchronized (progressQueue) {
-                       if (!progressQueue.isEmpty()) {
-                               fireGotProgress();
-                       }
-               }
-       }
-
-       /**
-        * Removes a callback listener from this callback.
-        * 
-        * @param highLevelContinuousCallbackListener
-        *            The callback listener to remove
-        */
-       public void removeHighLevelContinuousCallbackListener(HighLevelContinuousCallbackListener<R> highLevelContinuousCallbackListener) {
-               highLevelContinuousCallbackListeners.remove(highLevelContinuousCallbackListener);
-       }
-
-       /**
-        * Notifies all listeners that progress results have been received.
-        */
-       private void fireGotProgress() {
-               for (HighLevelContinuousCallbackListener<R> highLevelContinuousCallbackListener: highLevelContinuousCallbackListeners) {
-                       highLevelContinuousCallbackListener.gotProgress(this);
-               }
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the next progress result and removes it from the queue. If no
-        * progress result is yet available, this method will block.
-        * 
-        * @return The next progress result
-        * @throws InterruptedException
-        *             if {@link Object#wait()} is interrupted
-        */
-       public R getProgress() throws InterruptedException {
-               return getProgress(0);
-       }
-
-       /**
-        * Returns the next progress result and removes it from the queue. If no
-        * progress result is yet available, this method will block until either a
-        * progress result is available or the given time (in milliseconds) has
-        * passed.
-        * 
-        * @param waitTime
-        *            The maximum time to wait for a progress result
-        * @return The next progress result
-        * @throws InterruptedException
-        *             if {@link Object#wait()} is interrupted
-        */
-       public R getProgress(long waitTime) throws InterruptedException {
-               synchronized (progressQueue) {
-                       if (progressQueue.isEmpty()) {
-                               progressQueue.wait(waitTime);
-                       }
-                       return progressQueue.remove(0);
-               }
-       }
-
-       /**
-        * Returns the latest progress result and clears the queue.
-        * 
-        * @return The latest progress result, or <code>null</code> if the queue
-        *         is empty
-        */
-       public R getLatestProgress() {
-               synchronized (progressQueue) {
-                       if (progressQueue.isEmpty()) {
-                               return null;
-                       }
-                       R latestProgress = progressQueue.get(progressQueue.size() - 1);
-                       progressQueue.clear();
-                       return latestProgress;
-               }
-       }
-
-       /**
-        * Adds a progress result and notifies all listeners.
-        * 
-        * @param progress
-        *            The progress result to add
-        */
-       void addProgress(R progress) {
-               synchronized (progressQueue) {
-                       progressQueue.add(progress);
-                       progressQueue.notify();
-               }
-               fireGotProgress();
-       }
-
-}
diff --git a/src/net/pterodactylus/fcp/highlevel/HighLevelContinuousCallbackListener.java b/src/net/pterodactylus/fcp/highlevel/HighLevelContinuousCallbackListener.java
deleted file mode 100644 (file)
index 09636bc..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * jFCPlib-high-level-client - HighLevelContinuousCallbackListener.java -
- * Copyright © 2008 David Roden
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-package net.pterodactylus.fcp.highlevel;
-
-/**
- * Interface for objects that want to be notified as soon as a lengthy operation
- * made some progress.
- * 
- * @param <R>
- *            The type of the progress result
- * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
- * @version $Id$
- */
-public interface HighLevelContinuousCallbackListener<R extends HighLevelContinuousResult> extends HighLevelCallbackListener<R> {
-
-       /**
-        * Notifies a listener that a progress message has been received.
-        * 
-        * @param highLevelContinuousCallback
-        *            The callback that made the progress
-        */
-       public void gotProgress(HighLevelContinuousCallback<R> highLevelContinuousCallback);
-
-}
diff --git a/src/net/pterodactylus/fcp/highlevel/HighLevelContinuousResult.java b/src/net/pterodactylus/fcp/highlevel/HighLevelContinuousResult.java
deleted file mode 100644 (file)
index 397b4a9..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * jFCPlib-high-level-client - HighLevelContinuosResult.java -
- * Copyright © 2008 David Roden
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-package net.pterodactylus.fcp.highlevel;
-
-/**
- * Result for operations that send progress messages until they have completed.
- * 
- * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
- * @version $Id$
- */
-public abstract class HighLevelContinuousResult extends HighLevelResult {
-
-       /** The number of total blocks. */
-       private int totalBlocks;
-
-       /** The number of required blocks. */
-       private int requiredBlocks;
-
-       /** The number of successfully transferred blocks. */
-       private int successfulBlocks;
-
-       /** The number of failed blocks. */
-       private int failedBlocks;
-
-       /** The number of fatally failed blocks. */
-       private int fatallyFailedBlocks;
-
-       /** Whether the total number is finalized. */
-       private boolean totalFinalized;
-
-       /**
-        * Returns the number of total blocks.
-        * 
-        * @return The number of total blocks
-        */
-       public int getTotalBlocks() {
-               return totalBlocks;
-       }
-
-       /**
-        * Sets the number of total blocks.
-        * 
-        * @param totalBlocks
-        *            The number of total blocks
-        */
-       void setTotalBlocks(int totalBlocks) {
-               this.totalBlocks = totalBlocks;
-       }
-
-       /**
-        * Returns the number of required blocks. For downloads, this number is
-        * smaller than {@link #getTotalBlocks()}.
-        * 
-        * @return The number of required blocks
-        */
-       public int getRequiredBlocks() {
-               return requiredBlocks;
-       }
-
-       /**
-        * Sets the number of required blocks.
-        * 
-        * @param requiredBlocks
-        *            The number of required blocks
-        */
-       void setRequiredBlocks(int requiredBlocks) {
-               this.requiredBlocks = requiredBlocks;
-       }
-
-       /**
-        * Returns the number of successfully transferred blocks.
-        * 
-        * @return The number of successfully transferred blocks
-        */
-       public int getSuccessfulBlocks() {
-               return successfulBlocks;
-       }
-
-       /**
-        * Sets the number of successfully transferred blocks.
-        * 
-        * @param successfulBlocks
-        *            The number of successfully transferred blocks
-        */
-       void setSuccessfulBlocks(int successfulBlocks) {
-               this.successfulBlocks = successfulBlocks;
-       }
-
-       /**
-        * Returns the number of failed blocks. Blocks that have failed can be
-        * retried.
-        * 
-        * @return The number of failed blocks
-        */
-       public int getFailedBlocks() {
-               return failedBlocks;
-       }
-
-       /**
-        * Sets the number of failed blocks.
-        * 
-        * @param failedBlocks
-        *            The number of failed blocks
-        */
-       void setFailedBlocks(int failedBlocks) {
-               this.failedBlocks = failedBlocks;
-       }
-
-       /**
-        * Returns the number of fatally failed blocks. Fatally failed blocks will
-        * never complete, even with endless retries.
-        * 
-        * @return The number of fatally failed blocks
-        */
-       public int getFatallyFailedBlocks() {
-               return fatallyFailedBlocks;
-       }
-
-       /**
-        * Sets the number of fatally failed blocks.
-        * 
-        * @param fatallyFailedBlocks
-        *            The number fatally failed blocks
-        */
-       void setFatallyFailedBlocks(int fatallyFailedBlocks) {
-               this.fatallyFailedBlocks = fatallyFailedBlocks;
-       }
-
-       /**
-        * Returns whether the result of {@link #getTotalBlocks()} is final, i.e. it
-        * won’t change anymore.
-        * 
-        * @return <code>true</code> if the result of {@link #getTotalBlocks()} is
-        *         final, <code>false</code> otherwise
-        */
-       public boolean isTotalFinalized() {
-               return totalFinalized;
-       }
-
-       /**
-        * Sets whether the result of {@link #getTotalBlocks()} is final, i.e. it
-        * won’t change anymore.
-        * 
-        * @param totalFinalized
-        *            <code>true</code> if the result of {@link #getTotalBlocks()}
-        *            is final, <code>false</code> otherwise
-        */
-       void setTotalFinalized(boolean totalFinalized) {
-               this.totalFinalized = totalFinalized;
-       }
-
-}
diff --git a/src/net/pterodactylus/fcp/highlevel/HighLevelProgress.java b/src/net/pterodactylus/fcp/highlevel/HighLevelProgress.java
new file mode 100644 (file)
index 0000000..ec648f8
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * jFCPlib-high-level-client - HighLevelContinuosResult.java -
+ * Copyright © 2008 David Roden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.fcp.highlevel;
+
+/**
+ * Result for operations that send progress messages until they have completed.
+ * 
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ * @version $Id$
+ */
+public abstract class HighLevelProgress extends HighLevelResult {
+
+       /** The number of total blocks. */
+       private int totalBlocks;
+
+       /** The number of required blocks. */
+       private int requiredBlocks;
+
+       /** The number of successfully transferred blocks. */
+       private int successfulBlocks;
+
+       /** The number of failed blocks. */
+       private int failedBlocks;
+
+       /** The number of fatally failed blocks. */
+       private int fatallyFailedBlocks;
+
+       /** Whether the total number is finalized. */
+       private boolean totalFinalized;
+
+       /**
+        * Package-private constructor.
+        * 
+        * @param identifier
+        *            The identifier of the request
+        */
+       public HighLevelProgress(String identifier) {
+               super(identifier);
+       }
+
+       /**
+        * Returns the number of total blocks.
+        * 
+        * @return The number of total blocks
+        */
+       public int getTotalBlocks() {
+               return totalBlocks;
+       }
+
+       /**
+        * Sets the number of total blocks.
+        * 
+        * @param totalBlocks
+        *            The number of total blocks
+        */
+       void setTotalBlocks(int totalBlocks) {
+               this.totalBlocks = totalBlocks;
+       }
+
+       /**
+        * Returns the number of required blocks. For downloads, this number is
+        * smaller than {@link #getTotalBlocks()}.
+        * 
+        * @return The number of required blocks
+        */
+       public int getRequiredBlocks() {
+               return requiredBlocks;
+       }
+
+       /**
+        * Sets the number of required blocks.
+        * 
+        * @param requiredBlocks
+        *            The number of required blocks
+        */
+       void setRequiredBlocks(int requiredBlocks) {
+               this.requiredBlocks = requiredBlocks;
+       }
+
+       /**
+        * Returns the number of successfully transferred blocks.
+        * 
+        * @return The number of successfully transferred blocks
+        */
+       public int getSuccessfulBlocks() {
+               return successfulBlocks;
+       }
+
+       /**
+        * Sets the number of successfully transferred blocks.
+        * 
+        * @param successfulBlocks
+        *            The number of successfully transferred blocks
+        */
+       void setSuccessfulBlocks(int successfulBlocks) {
+               this.successfulBlocks = successfulBlocks;
+       }
+
+       /**
+        * Returns the number of failed blocks. Blocks that have failed can be
+        * retried.
+        * 
+        * @return The number of failed blocks
+        */
+       public int getFailedBlocks() {
+               return failedBlocks;
+       }
+
+       /**
+        * Sets the number of failed blocks.
+        * 
+        * @param failedBlocks
+        *            The number of failed blocks
+        */
+       void setFailedBlocks(int failedBlocks) {
+               this.failedBlocks = failedBlocks;
+       }
+
+       /**
+        * Returns the number of fatally failed blocks. Fatally failed blocks will
+        * never complete, even with endless retries.
+        * 
+        * @return The number of fatally failed blocks
+        */
+       public int getFatallyFailedBlocks() {
+               return fatallyFailedBlocks;
+       }
+
+       /**
+        * Sets the number of fatally failed blocks.
+        * 
+        * @param fatallyFailedBlocks
+        *            The number fatally failed blocks
+        */
+       void setFatallyFailedBlocks(int fatallyFailedBlocks) {
+               this.fatallyFailedBlocks = fatallyFailedBlocks;
+       }
+
+       /**
+        * Returns whether the result of {@link #getTotalBlocks()} is final, i.e. it
+        * won’t change anymore.
+        * 
+        * @return <code>true</code> if the result of {@link #getTotalBlocks()} is
+        *         final, <code>false</code> otherwise
+        */
+       public boolean isTotalFinalized() {
+               return totalFinalized;
+       }
+
+       /**
+        * Sets whether the result of {@link #getTotalBlocks()} is final, i.e. it
+        * won’t change anymore.
+        * 
+        * @param totalFinalized
+        *            <code>true</code> if the result of {@link #getTotalBlocks()}
+        *            is final, <code>false</code> otherwise
+        */
+       void setTotalFinalized(boolean totalFinalized) {
+               this.totalFinalized = totalFinalized;
+       }
+
+}
diff --git a/src/net/pterodactylus/fcp/highlevel/HighLevelProgressCallback.java b/src/net/pterodactylus/fcp/highlevel/HighLevelProgressCallback.java
new file mode 100644 (file)
index 0000000..a292df8
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * jFCPlib-high-level-client - HighLevelContinousCallback.java -
+ * Copyright © 2008 David Roden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.fcp.highlevel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Callback for an operation that sends progress messages before completion.
+ * 
+ * @param
+ * <P>
+ * The type of the high-level progress
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ * @version $Id$
+ */
+public class HighLevelProgressCallback<P extends HighLevelProgress> extends HighLevelCallback<P> {
+
+       /** Callback listeners. */
+       private final List<HighLevelProgressCallbackListener<P>> highLevelContinuousCallbackListeners = new ArrayList<HighLevelProgressCallbackListener<P>>();
+
+       /**
+        * Creates a new continuous callback with the given result.
+        * 
+        * @see HighLevelCallback#HighLevelCallback(HighLevelResult)
+        * @param progress
+        *            The result of the operation
+        */
+       HighLevelProgressCallback(P progress) {
+               super(progress);
+       }
+
+       //
+       // EVENT MANAGEMENT
+       //
+
+       /**
+        * Adds a callback listener to this callback.
+        * 
+        * @param highLevelContinuousCallbackListener
+        *            The callback listener to add
+        */
+       public void addHighLevelContinuousCallbackListener(HighLevelProgressCallbackListener<P> highLevelContinuousCallbackListener) {
+               highLevelContinuousCallbackListeners.add(highLevelContinuousCallbackListener);
+               fireGotProgress();
+       }
+
+       /**
+        * Removes a callback listener from this callback.
+        * 
+        * @param highLevelContinuousCallbackListener
+        *            The callback listener to remove
+        */
+       public void removeHighLevelContinuousCallbackListener(HighLevelProgressCallbackListener<P> highLevelContinuousCallbackListener) {
+               highLevelContinuousCallbackListeners.remove(highLevelContinuousCallbackListener);
+       }
+
+       /**
+        * Notifies all listeners that progress results have been received.
+        */
+       private void fireGotProgress() {
+               for (HighLevelProgressCallbackListener<P> highLevelContinuousCallbackListener: highLevelContinuousCallbackListeners) {
+                       highLevelContinuousCallbackListener.gotProgress(this);
+               }
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Waits for the next progress on this callback. Completion of the result
+        * also counts as progress.
+        * 
+        * @throws InterruptedException
+        *             if {@link Object#wait()} is interrupted
+        */
+       public void waitForProgress() throws InterruptedException {
+               synchronized (syncObject) {
+                       syncObject.wait();
+               }
+       }
+
+       /**
+        * Waits for the given amount of time (in milliseconds) for the next
+        * progress on this callback. Completion of the result also counts as
+        * progress.
+        * 
+        * @param waitTime
+        *            The maximum time to wait for progress
+        * @throws InterruptedException
+        *             if {@link Object#wait()} is interrupted
+        */
+       public void waitForProgress(long waitTime) throws InterruptedException {
+               synchronized (syncObject) {
+                       syncObject.wait(waitTime);
+               }
+       }
+
+       /**
+        * Notifies all listeners that the progress was updated.
+        */
+       void progressUpdated() {
+               synchronized (syncObject) {
+                       syncObject.notify();
+               }
+               fireGotProgress();
+       }
+
+}
diff --git a/src/net/pterodactylus/fcp/highlevel/HighLevelProgressCallbackListener.java b/src/net/pterodactylus/fcp/highlevel/HighLevelProgressCallbackListener.java
new file mode 100644 (file)
index 0000000..e0683fb
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * jFCPlib-high-level-client - HighLevelContinuousCallbackListener.java -
+ * Copyright © 2008 David Roden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.fcp.highlevel;
+
+/**
+ * Interface for objects that want to be notified as soon as a lengthy operation
+ * made some progress.
+ * 
+ * @param
+ * <P>
+ * The type of the high-level progress
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ * @version $Id: HighLevelContinuousCallbackListener.java 29 2008-04-15
+ *          23:15:49Z bombe $
+ */
+public interface HighLevelProgressCallbackListener<P extends HighLevelProgress> extends HighLevelCallbackListener<P> {
+
+       /**
+        * Notifies a listener that a progress message has been received.
+        * 
+        * @param highLevelContinuousCallback
+        *            The callback that made the progress
+        */
+       public void gotProgress(HighLevelProgressCallback<P> highLevelContinuousCallback);
+
+}
index 3be5b2c..5975394 100644 (file)
@@ -27,10 +27,32 @@ package net.pterodactylus.fcp.highlevel;
  */
 public abstract class HighLevelResult {
 
+       /** The identifier of the request. */
+       private final String identifier;
+
        /** Whether the operation failed. */
        private boolean failed;
 
        /**
+        * Package-private constructor.
+        * 
+        * @param identifier
+        *            The identifier of the request
+        */
+       HighLevelResult(String identifier) {
+               this.identifier = identifier;
+       }
+
+       /**
+        * Returns the identifier of the underlying request.
+        * 
+        * @return The identifier of the request
+        */
+       public String getIdentifier() {
+               return identifier;
+       }
+
+       /**
         * Returns whether the operation failed.
         * 
         * @return <code>true</code> if the operation failed, <code>false</code>
index eeaa4a9..5d66351 100644 (file)
@@ -35,8 +35,12 @@ public class KeyGenerationResult extends HighLevelResult {
 
        /**
         * Package-private constructor.
+        * 
+        * @param identifier
+        *            The identifier of the request
         */
-       KeyGenerationResult() {
+       KeyGenerationResult(String identifier) {
+               super(identifier);
        }
 
        /**
index 1d6e91f..456e01e 100644 (file)
@@ -37,6 +37,16 @@ public class PeerListResult extends HighLevelResult implements Iterable<Peer> {
        private final List<Peer> peers = new ArrayList<Peer>();
 
        /**
+        * Package-private constructor.
+        * 
+        * @param identifier
+        *            The identifier of the request
+        */
+       PeerListResult(String identifier) {
+               super(identifier);
+       }
+
+       /**
         * Adds a peer to the list.
         * 
         * @param peer
index 47e78b5..a332761 100644 (file)
@@ -36,6 +36,16 @@ public class PeerResult extends HighLevelResult {
        private Peer peer;
 
        /**
+        * Package-private constructor.
+        * 
+        * @param identifier
+        *            The identifier of the request
+        */
+       PeerResult(String identifier) {
+               super(identifier);
+       }
+
+       /**
         * Returns the peer.
         * 
         * @return The peer