implement node addition and removal events
[jSite2.git] / src / net / pterodactylus / jsite / core / NodeManager.java
index fe52fd7..b919cfe 100644 (file)
@@ -29,6 +29,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -47,7 +48,7 @@ import net.pterodactylus.util.logging.Logging;
  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
  * @version $Id$
  */
-public class NodeManager implements HighLevelClientListener {
+public class NodeManager implements Iterable<Node>, HighLevelClientListener {
 
        /** Logger. */
        private static final Logger logger = Logging.getLogger(NodeManager.class.getName());
@@ -114,6 +115,30 @@ public class NodeManager implements HighLevelClientListener {
        }
 
        /**
+        * Notifies all listeners that a node was added.
+        * 
+        * @param node
+        *            The node that was added.
+        */
+       private void fireNodeAdded(Node node) {
+               for (NodeListener nodeListener: nodeListeners) {
+                       nodeListener.nodeAdded(node);
+               }
+       }
+
+       /**
+        * Notifies all listeners that a node was removed.
+        * 
+        * @param node
+        *            The node that was removed
+        */
+       private void fireNodeRemoved(Node node) {
+               for (NodeListener nodeListener: nodeListeners) {
+                       nodeListener.nodeRemoved(node);
+               }
+       }
+
+       /**
         * Notifies all listeners that the given node was connected.
         * 
         * @param node
@@ -165,6 +190,13 @@ public class NodeManager implements HighLevelClientListener {
                return nodes.contains(node);
        }
 
+       /**
+        * {@inheritDoc}
+        */
+       public Iterator<Node> iterator() {
+               return nodes.iterator();
+       }
+
        //
        // ACTIONS
        //
@@ -222,10 +254,14 @@ public class NodeManager implements HighLevelClientListener {
                        newNode.setPort(nodePort);
                        loadedNodes.add(newNode);
                }
+               logger.fine("loaded " + loadedNodes.size() + " nodes from config");
                synchronized (syncObject) {
                        nodes.clear();
                        nodes.addAll(loadedNodes);
                }
+               for (Node node: nodes) {
+                       fireNodeAdded(node);
+               }
        }
 
        /**
@@ -270,6 +306,7 @@ public class NodeManager implements HighLevelClientListener {
                synchronized (syncObject) {
                        if (!nodes.contains(node)) {
                                nodes.add(node);
+                               fireNodeAdded(node);
                        }
                }
        }
@@ -289,6 +326,7 @@ public class NodeManager implements HighLevelClientListener {
                        if (nodeClients.containsKey(node)) {
                                disconnect(node);
                        }
+                       fireNodeRemoved(node);
                }
        }
 
@@ -337,6 +375,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
        //