add request management
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 12 May 2008 21:29:45 +0000 (21:29 +0000)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 12 May 2008 21:29:45 +0000 (21:29 +0000)
git-svn-id: http://trooper/svn/projects/jSite/trunk@804 c3eda9e8-030b-0410-8277-bc7414b0a119

src/net/pterodactylus/jsite/core/CoreImpl.java
src/net/pterodactylus/jsite/core/CoreListener.java
src/net/pterodactylus/jsite/core/NodeListener.java
src/net/pterodactylus/jsite/core/NodeManager.java
src/net/pterodactylus/jsite/core/Request.java [new file with mode: 0644]
src/net/pterodactylus/jsite/core/RequestListener.java [new file with mode: 0644]
src/net/pterodactylus/jsite/core/RequestManager.java [new file with mode: 0644]
src/net/pterodactylus/jsite/gui/SwingInterface.java
src/net/pterodactylus/jsite/main/Main.java

index 8fe64da..9c68d44 100644 (file)
@@ -25,11 +25,11 @@ import java.util.List;
 
 /**
  * The core of jSite.
- *
+ * 
  * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
  * @version $Id$
  */
-public class CoreImpl implements Core, NodeListener {
+public class CoreImpl implements Core, NodeListener, RequestListener {
 
        /** The core listeners. */
        private final List<CoreListener> coreListeners = new ArrayList<CoreListener>();
@@ -40,6 +40,11 @@ public class CoreImpl implements Core, NodeListener {
        /** The node manager. */
        private NodeManager nodeManager;
 
+       /** The request manager. */
+       /* TODO - remove */
+       @SuppressWarnings("unused")
+       private RequestManager requestManager;
+
        //
        // LISTENER MANAGEMENT
        //
@@ -60,7 +65,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Notifies all listeners that the projects were loaded successfully.
-        *
+        * 
         * @param directory
         *            The directory the projects were loaded from
         */
@@ -73,7 +78,7 @@ public class CoreImpl implements Core, NodeListener {
        /**
         * Notifies all core listeners that loading the projects from the given
         * directory has failed.
-        *
+        * 
         * @param directory
         *            The directory the projects were tried to load from
         * @param throwable
@@ -87,7 +92,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Notifies all listeners that the projects were successfully saved.
-        *
+        * 
         * @param directory
         *            The directory the projects were saved to
         */
@@ -99,7 +104,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Notifies all listeners that the projects could not be saved.
-        *
+        * 
         * @param directory
         *            The directory the projects were to be saved to
         * @param throwable
@@ -113,7 +118,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Notifies all listeners that the nodes were successfully loaded.
-        *
+        * 
         * @param directory
         *            The directory the nodes were loaded from
         */
@@ -125,7 +130,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Notifies all listeners that loading the nodes has failed.
-        *
+        * 
         * @param directory
         *            The directory the nodes were loaded from
         * @param throwable
@@ -139,7 +144,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Notifies all listeners that the nodes were saved successfully.
-        *
+        * 
         * @param directory
         *            The directory the nodes were saved to
         */
@@ -151,7 +156,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Notifies all listeners that saving the nodes has failed.
-        *
+        * 
         * @param directory
         *            The directory the nodes were saved to
         * @param throwable
@@ -184,7 +189,7 @@ public class CoreImpl implements Core, NodeListener {
        /**
         * Notifies all listeners that a connection to the given node is now being
         * established.
-        *
+        * 
         * @param node
         *            The node that is being connected to
         */
@@ -196,7 +201,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Notifies all listeners that the given node is now connected.
-        *
+        * 
         * @param node
         *            The node that is now connected
         */
@@ -208,7 +213,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Notifies all listeners that the given node was disconnected.
-        *
+        * 
         * @param node
         *            The node that is now disconnected
         * @param throwable
@@ -221,13 +226,27 @@ public class CoreImpl implements Core, NodeListener {
                }
        }
 
+       /**
+        * Notifies all listeners that a request was added to a node.
+        * 
+        * @param node
+        *            The node the request was added to
+        * @param request
+        *            The request that was added
+        */
+       private void fireRequestAdded(Node node, Request request) {
+               for (CoreListener coreListener: coreListeners) {
+                       coreListener.requestAdded(node, request);
+               }
+       }
+
        //
        // ACCESSORS
        //
 
        /**
         * Returns the project manager.
-        *
+        * 
         * @return The project manager
         */
        public ProjectManager getProjectManager() {
@@ -236,7 +255,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Sets the project manager to use.
-        *
+        * 
         * @param projectManager
         *            The project manager to use
         */
@@ -246,7 +265,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Returns the node manager.
-        *
+        * 
         * @return The node manager
         */
        public NodeManager getNodeManager() {
@@ -255,7 +274,7 @@ public class CoreImpl implements Core, NodeListener {
 
        /**
         * Sets the node manager to use.
-        *
+        * 
         * @param nodeManager
         *            The node manager to use
         */
@@ -264,6 +283,16 @@ public class CoreImpl implements Core, NodeListener {
        }
 
        /**
+        * Sets the request manager to use.
+        * 
+        * @param requestManager
+        *            The request manager to use
+        */
+       public void setRequestManager(RequestManager requestManager) {
+               this.requestManager = requestManager;
+       }
+
+       /**
         * {@inheritDoc}
         */
        public List<Node> getNodes() {
@@ -373,4 +402,15 @@ public class CoreImpl implements Core, NodeListener {
                fireNodeDisconnected(node, throwable);
        }
 
+       //
+       // INTERFACE RequestListener
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       public void requestAdded(Node node, Request request) {
+               fireRequestAdded(node, request);
+       }
+
 }
index b4a2574..cef057a 100644 (file)
@@ -21,7 +21,7 @@ package net.pterodactylus.jsite.core;
 
 /**
  * Interface definition for user interfaces.
- *
+ * 
  * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
  * @version $Id$
  */
@@ -33,7 +33,7 @@ public interface CoreListener {
 
        /**
         * Notifies a listener that loading the projects finished successfully.
-        *
+        * 
         * @param directory
         *            The directory the nodes were loaded from
         */
@@ -41,7 +41,7 @@ public interface CoreListener {
 
        /**
         * Notifies all listeners that loading the projects has failed.
-        *
+        * 
         * @param directory
         *            The directory the projects were tried to load from
         * @param throwable
@@ -52,7 +52,7 @@ public interface CoreListener {
        /**
         * Notifies a listener that the projects were successfully saved to the
         * given directory.
-        *
+        * 
         * @param directory
         *            The directory the projects were saved to
         */
@@ -60,7 +60,7 @@ public interface CoreListener {
 
        /**
         * Notifies a listener that saving the projects has failed.
-        *
+        * 
         * @param directory
         *            The directory the projects were to be saved to
         * @param throwable
@@ -74,7 +74,7 @@ public interface CoreListener {
 
        /**
         * Notifies a listener that the nodes were successfully loaded.
-        *
+        * 
         * @param directory
         *            The directory the nodes were loaded from
         */
@@ -82,7 +82,7 @@ public interface CoreListener {
 
        /**
         * Notifies a listener that loading the nodes has failed.
-        *
+        * 
         * @param directory
         *            The directory the nodes were loaded from
         * @param throwable
@@ -92,7 +92,7 @@ public interface CoreListener {
 
        /**
         * Notifies a listener that the nodes were successfully saved.
-        *
+        * 
         * @param directory
         *            The directory the nodes were saved to
         */
@@ -100,7 +100,7 @@ public interface CoreListener {
 
        /**
         * Notifies a listener that saving the nodes has failed.
-        *
+        * 
         * @param directory
         *            The directory the nodes were saved to
         * @param throwable
@@ -129,7 +129,7 @@ public interface CoreListener {
        /**
         * Notifies all listeners that the core started connecting to the given
         * node.
-        *
+        * 
         * @param node
         *            The node that is being connected
         */
@@ -137,7 +137,7 @@ public interface CoreListener {
 
        /**
         * Notifies all listeners that the core connected to the given node.
-        *
+        * 
         * @param node
         *            The node that is connected
         */
@@ -145,7 +145,7 @@ public interface CoreListener {
 
        /**
         * Notifies all listeners that the core disconnected from the given node.
-        *
+        * 
         * @param node
         *            The node that was diconnected
         * @param throwable
@@ -154,4 +154,18 @@ public interface CoreListener {
         */
        public void nodeDisconnected(Node node, Throwable throwable);
 
+       //
+       // request stuff
+       //
+
+       /**
+        * Notifies a listener that a request was added to a node.
+        * 
+        * @param node
+        *            The node the request was added to
+        * @param request
+        *            The request that was added
+        */
+       public void requestAdded(Node node, Request request);
+
 }
index 80a01ce..23f1a4c 100644 (file)
@@ -23,7 +23,7 @@ import java.util.EventListener;
 
 /**
  * Interface for listeners that want to be notified about node events.
- *
+ * 
  * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
  * @version $Id$
  */
@@ -31,7 +31,7 @@ public interface NodeListener extends EventListener {
 
        /**
         * Notifies a listener that a connection to the given node was established.
-        *
+        * 
         * @param node
         *            The node that is now connected
         */
@@ -40,7 +40,7 @@ public interface NodeListener extends EventListener {
        /**
         * Notifies a listener that a connection to the given node was severed. The
         * listener is responsible for
-        *
+        * 
         * @param node
         *            The node that is now disconnected
         * @param throwable
index fe52fd7..70da6d6 100644 (file)
@@ -337,6 +337,56 @@ public class NodeManager implements HighLevelClientListener {
                return Collections.unmodifiableList(nodes);
        }
 
+       /**
+        * “Borrows” a high-level client for the given node. A borrowed client
+        * <strong>has</strong> to be returned to the node manager using
+        * {@link #returnHighLevelClient(HighLevelClient)} when it is no longer in
+        * use, i.e. after a message has been sent! This method will block until a
+        * high-level client for the given node is available.
+        * 
+        * @param node
+        *            The node to get a high-level client for
+        * @return The high-level client for a node, or <code>null</code> if the
+        *         node was disconnected or removed
+        */
+       public HighLevelClient borrowHighLevelClient(Node node) {
+               synchronized (syncObject) {
+                       if (!nodeClients.containsKey(node)) {
+                               return null;
+                       }
+                       HighLevelClient highLevelClient = nodeClients.get(node);
+                       while (nodeClients.containsKey(node) && usedConnections.contains(highLevelClient)) {
+                               try {
+                                       syncObject.wait();
+                               } catch (InterruptedException ie1) {
+                                       /* ignore. TODO - check. */
+                               }
+                       }
+                       if (!nodeClients.containsKey(node)) {
+                               return null;
+                       }
+                       usedConnections.add(highLevelClient);
+                       return highLevelClient;
+               }
+       }
+
+       /**
+        * Returns a borrowed high-level client.
+        * 
+        * @see #borrowHighLevelClient(Node)
+        * @param highLevelClient
+        *            The high-level client to return
+        */
+       public void returnHighLevelClient(HighLevelClient highLevelClient) {
+               synchronized (syncObject) {
+                       if (!clientNodes.containsKey(highLevelClient)) {
+                               return;
+                       }
+                       usedConnections.remove(highLevelClient);
+                       syncObject.notifyAll();
+               }
+       }
+
        //
        // PRIVATE METHODS
        //
diff --git a/src/net/pterodactylus/jsite/core/Request.java b/src/net/pterodactylus/jsite/core/Request.java
new file mode 100644 (file)
index 0000000..47349ca
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * jSite2 - Request.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.jsite.core;
+
+/**
+ * A request is an ongoing download or upload reported by the freenet node.
+ * 
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ * @version $Id$
+ */
+public class Request {
+
+       /** The identifier of the request. */
+       private final String identifier;
+
+       /**
+        * Creates a new request with the given identifier.
+        * 
+        * @param identifier
+        *            The identifier of the request
+        */
+       Request(String identifier) {
+               this.identifier = identifier;
+       }
+
+       /**
+        * Returns the identifier of the request. It is unique per node.
+        * 
+        * @return The identifier of the request
+        */
+       public String getIdentifier() {
+               return identifier;
+       }
+
+}
diff --git a/src/net/pterodactylus/jsite/core/RequestListener.java b/src/net/pterodactylus/jsite/core/RequestListener.java
new file mode 100644 (file)
index 0000000..eb0433a
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * jSite2 - RequestListener.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.jsite.core;
+
+import java.util.EventListener;
+
+/**
+ * Interface for objects that want to be notified on request events.
+ * 
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ * @version $Id$
+ */
+public interface RequestListener extends EventListener {
+
+       /**
+        * Notifies a listener that a request was added to a node.
+        * 
+        * @param node
+        *            The node the request was added to
+        * @param request
+        *            The request that was added
+        */
+       public void requestAdded(Node node, Request request);
+
+}
diff --git a/src/net/pterodactylus/jsite/core/RequestManager.java b/src/net/pterodactylus/jsite/core/RequestManager.java
new file mode 100644 (file)
index 0000000..f2aa23f
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * jSite2 - RequestManager.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.jsite.core;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.pterodactylus.fcp.highlevel.HighLevelCallback;
+import net.pterodactylus.fcp.highlevel.HighLevelCallbackListener;
+import net.pterodactylus.fcp.highlevel.HighLevelClient;
+import net.pterodactylus.fcp.highlevel.RequestListResult;
+import net.pterodactylus.fcp.highlevel.RequestResult;
+import net.pterodactylus.util.logging.Logging;
+
+/**
+ * The request manager keeps track of all the request on all connected nodes.
+ * The request manager is added to the {@link NodeManager} as a
+ * {@link NodeListener} so that it can fire request-removed events in case a
+ * node is disconnected.
+ * 
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ * @version $Id$
+ */
+public class RequestManager implements NodeListener {
+
+       /** Logger. */
+       private static final Logger logger = Logging.getLogger(RequestManager.class.getName());
+
+       /** Request listeners. */
+       private List<RequestListener> requestListeners = Collections.synchronizedList(new ArrayList<RequestListener>());
+
+       /** The node manager. */
+       private NodeManager nodeManager;
+
+       //
+       // EVENT MANAGEMENT
+       //
+
+       /**
+        * Adds a request listener.
+        * 
+        * @param requestListener
+        *            The request listener to add
+        */
+       public void addRequestListener(RequestListener requestListener) {
+               requestListeners.add(requestListener);
+       }
+
+       /**
+        * Removes a request listener.
+        * 
+        * @param requestListener
+        *            The request listener to remove
+        */
+       public void removeRequestListener(RequestListener requestListener) {
+               requestListeners.remove(requestListener);
+       }
+
+       /**
+        * Notifies all listeners that a request was added.
+        * 
+        * @param node
+        *            The node that added the request
+        * @param request
+        *            The request that was added
+        */
+       private void fireRequestAdded(Node node, Request request) {
+               for (RequestListener requestListener: requestListeners) {
+                       requestListener.requestAdded(node, request);
+               }
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Sets the node manager to use.
+        * 
+        * @param nodeManager
+        *            The node manager
+        */
+       public void setNodeManager(NodeManager nodeManager) {
+               this.nodeManager = nodeManager;
+       }
+
+       //
+       // ACTIONS
+       //
+
+       /**
+        * Requests a list of all running requests from a node. This method will
+        * block until the request has been sent!
+        * 
+        * @param node
+        *            The node to get all requests for
+        * @throws IOException
+        *             if an I/O error occurs while communicating with the node
+        */
+       public void getRequests(final Node node) throws IOException {
+               HighLevelClient highLevelClient = nodeManager.borrowHighLevelClient(node);
+               if (highLevelClient == null) {
+                       logger.log(Level.WARNING, "no client for node: " + node);
+                       return;
+               }
+               try {
+                       HighLevelCallback<RequestListResult> requestListCallback = highLevelClient.getRequests();
+                       requestListCallback.addHighLevelCallbackListener(new HighLevelCallbackListener<RequestListResult>() {
+
+                               @SuppressWarnings("synthetic-access")
+                               public void gotResult(HighLevelCallback<RequestListResult> highLevelCallback) {
+                                       RequestListResult requestListResult;
+                                       try {
+                                               requestListResult = highLevelCallback.getResult();
+                                       } catch (InterruptedException e) {
+                                               logger.log(Level.SEVERE, "getResult() blocked and was interrupted");
+                                               return;
+                                       }
+                                       for (RequestResult requestResult: requestListResult) {
+                                               Request request = new Request(requestResult.getIdentifier());
+                                               /* TODO - fill request */
+                                               fireRequestAdded(node, request);
+                                       }
+                               }
+                       });
+               } finally {
+                       nodeManager.returnHighLevelClient(highLevelClient);
+               }
+       }
+
+       //
+       // INTERFACE NodeListener
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       public void nodeConnected(Node node) {
+               /* TODO - get all requests. */
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void nodeDisconnected(Node node, Throwable throwable) {
+               /* TODO - remove all requests. */
+       }
+
+}
index b79cdc9..f868f85 100644 (file)
@@ -47,6 +47,7 @@ import net.pterodactylus.jsite.core.Core;
 import net.pterodactylus.jsite.core.CoreListener;
 import net.pterodactylus.jsite.core.Node;
 import net.pterodactylus.jsite.core.Project;
+import net.pterodactylus.jsite.core.Request;
 import net.pterodactylus.jsite.i18n.I18n;
 import net.pterodactylus.jsite.i18n.gui.I18nAction;
 import net.pterodactylus.util.image.IconLoader;
@@ -889,6 +890,14 @@ public class SwingInterface implements CoreListener, LoggingListener {
                mainWindow.refreshNodeMenuItems();
        }
 
+       /**
+        * {@inheritDoc}
+        */
+       public void requestAdded(Node node, Request request) {
+               logger.log(Level.INFO, "request added to node: " + request + ", " + node);
+               /* TODO - implement */
+       }
+       
        //
        // INTERFACE LoggingListener
        //
index dab65f5..be543eb 100644 (file)
@@ -24,12 +24,13 @@ import java.io.File;
 import net.pterodactylus.jsite.core.CoreImpl;
 import net.pterodactylus.jsite.core.NodeManager;
 import net.pterodactylus.jsite.core.ProjectManager;
+import net.pterodactylus.jsite.core.RequestManager;
 import net.pterodactylus.jsite.gui.SwingInterface;
 import net.pterodactylus.util.logging.Logging;
 
 /**
  * Main class that is called by the VM.
- *
+ * 
  * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
  * @version $Id$
  */
@@ -37,7 +38,7 @@ public class Main {
 
        /**
         * Main entry method for the VM.
-        *
+        * 
         * @param args
         *            The command-line arguments
         */
@@ -62,6 +63,12 @@ public class Main {
                core.setNodeManager(nodeManager);
                nodeManager.addNodeListener(core);
 
+               RequestManager requestManager = new RequestManager();
+               core.setRequestManager(requestManager);
+               nodeManager.addNodeListener(requestManager);
+               requestManager.setNodeManager(nodeManager);
+               requestManager.addRequestListener(core);
+
                SwingInterface swingInterface = new SwingInterface(core, configDirectory);
                core.addCoreListener(swingInterface);
                Logging.addLoggingListener(swingInterface);