(Current state.)
[jSite2.git] / src / net / pterodactylus / jsite / core / RequestManager.java
index 477028d..54ae5ac 100644 (file)
 package net.pterodactylus.jsite.core;
 
 import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.pterodactylus.fcp.highlevel.FcpClient;
+import net.pterodactylus.fcp.highlevel.FcpException;
+import net.pterodactylus.jsite.util.IdGenerator;
+import net.pterodactylus.util.number.Hex;
 
 /**
  * Manages requests.
@@ -28,17 +40,158 @@ import java.io.IOException;
  */
 public class RequestManager implements NodeListener {
 
+       /** The logger. */
+       private static final Logger logger = Logger.getLogger(RequestManager.class.getName());
+
+       /** Request event manager. */
+       private final RequestListenerManager requestListenerManager = new RequestListenerManager();
+
+       /** The node manager. */
+       private final NodeManager nodeManager;
+
+       /** Maps request IDs to requests. */
+       private final Map<String, Request> idRequests = Collections.synchronizedMap(new HashMap<String, Request>());
+
+       /**
+        * Creates a new request manager.
+        *
+        * @param nodeManager
+        *            The node manager to utilize
+        */
+       public RequestManager(NodeManager nodeManager) {
+               this.nodeManager = nodeManager;
+       }
+
+       //
+       // LISTENER MANAGEMENT
+       //
+
+       /**
+        * Adds the given request listener to the list of registered listeners.
+        *
+        * @see RequestListenerManager#addListener(RequestListener)
+        * @param requestListener
+        *            The request listener to add
+        */
+       public void addRequestListener(RequestListener requestListener) {
+               requestListenerManager.addListener(requestListener);
+       }
+
+       /**
+        * Removes the given request listener from the list of registered listeners.
+        *
+        * @see RequestListenerManager#removeListener(RequestListener)
+        * @param requestListener
+        *            The request listener to remove
+        */
+       public void removeRequestListener(RequestListener requestListener) {
+               requestListenerManager.removeListener(requestListener);
+       }
+
        //
        // ACTIONS
        //
 
        public void load() throws IOException {
-
        }
 
        public void save() throws IOException {
        }
 
+       /**
+        * Starts inserting the given project.
+        *
+        * @param project
+        *            The project to insert
+        * @throws JSiteException
+        *             if the project’s node is not connected, or no node is
+        *             connected at all
+        */
+       public void insertProject(Project project) throws JSiteException {
+               Request request = new Request();
+               request.setClientToken(generateClientToken(project));
+               Node wantedNode = project.getNode();
+               if (wantedNode == null) {
+                       for (Node node : nodeManager.getNodes()) {
+                               if (nodeManager.getFcpClient(node) != null) {
+                                       wantedNode = node;
+                                       break;
+                               }
+                       }
+               }
+               if (wantedNode == null) {
+                       /* TODO use custom exception */
+                       throw new JSiteException("No node connected.");
+               }
+               FcpClient fcpClient = nodeManager.getFcpClient(wantedNode);
+       }
+
+       //
+       // PRIVATE METHODS
+       //
+
+       /**
+        * Checks whether the given client token is a client token created by this
+        * request manager.
+        *
+        * @param clientToken
+        *            The client token to check
+        * @return {@code true} if the client token was created by this request
+        *         manager, {@code false} otherwise
+        */
+       private boolean isKnownClientToken(String clientToken) {
+               String[] clientTokenParts = clientToken.split("\\.");
+               if (clientTokenParts.length != 3) {
+                       return false;
+               }
+               String projectIdString = clientTokenParts[0];
+               if (projectIdString.length() != (IdGenerator.DEFAULT_LENGTH * 2)) {
+                       return false;
+               }
+               int clientTokenHashCode = -1;
+               try {
+                       Hex.toByte(projectIdString);
+                       Long.valueOf(clientTokenParts[1]);
+                       clientTokenHashCode = Integer.valueOf(clientTokenParts[2]);
+               } catch (NumberFormatException nfe1) {
+                       return false;
+               }
+               if ((clientTokenParts[0] + "." + clientTokenParts[1]).hashCode() != clientTokenHashCode) {
+                       return false;
+               }
+               return true;
+       }
+
+       /**
+        * Generates a client token for the given project.
+        *
+        * @param project
+        *            The project to generate a client token for
+        * @return The generated client token
+        */
+       public String generateClientToken(Project project) {
+               String clientToken = project.getId() + "." + System.currentTimeMillis();
+               clientToken += "." + clientToken.hashCode();
+               return clientToken;
+       }
+
+       /**
+        * Wraps the requests of the FCP API into jSite requests.
+        *
+        * @param requests
+        *            The requests to wrap
+        * @return The wrapped requests
+        */
+       private Collection<Request> wrapRequests(Collection<net.pterodactylus.fcp.highlevel.Request> requests) {
+               Collection<Request> wrappedRequests = new HashSet<Request>();
+               for (net.pterodactylus.fcp.highlevel.Request request : requests) {
+                       Request wrappedRequest = new Request(request.getIdentifier());
+                       wrappedRequest.setClientToken(request.getClientToken());
+                       wrappedRequests.add(wrappedRequest);
+               }
+               return wrappedRequests;
+       }
+
        //
        // INTERFACE NodeListener
        //
@@ -47,21 +200,42 @@ public class RequestManager implements NodeListener {
         * {@inheritDoc}
         */
        public void nodeAdded(Node node) {
-               /* TODO */
+               /* ignore. */
        }
 
        /**
         * {@inheritDoc}
         */
        public void nodeConnected(Node node) {
-               /* TODO */
+               FcpClient fcpClient = nodeManager.getFcpClient(node);
+               if (fcpClient == null) {
+                       logger.log(Level.WARNING, "Got no FCP client for node (" + node + ")!");
+                       return;
+               }
+               try {
+                       Collection<Request> requests = wrapRequests(fcpClient.getRequests(true));
+                       for (Request request : requests) {
+                               String clientToken = request.getClientToken();
+                               if ((clientToken == null) || (clientToken.trim().length() == 0)) {
+                                       continue;
+                               }
+                               if (!isKnownClientToken(clientToken)) {
+                                       continue;
+                               }
+                               /* TODO - process request. */
+                       }
+               } catch (IOException ioe1) {
+                       logger.log(Level.WARNING, "Could not get requests from node (" + node + ")!", ioe1);
+               } catch (FcpException fe1) {
+                       logger.log(Level.WARNING, "Could not get requests from node (" + node + ")!", fe1);
+               }
        }
 
        /**
         * {@inheritDoc}
         */
        public void nodeConnectionFailed(Node node, Throwable cause) {
-               /* TODO */
+               /* ignore. */
        }
 
        /**
@@ -75,7 +249,7 @@ public class RequestManager implements NodeListener {
         * {@inheritDoc}
         */
        public void nodeRemoved(Node node) {
-               /* TODO */
+               /* ignore. */
        }
 
 }