Convert plugin replies to EventBus-based events.
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Thu, 17 Jan 2013 06:38:03 +0000 (07:38 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Thu, 17 Jan 2013 06:55:59 +0000 (07:55 +0100)
src/main/java/net/pterodactylus/sone/freenet/plugin/ConnectorListener.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/plugin/ConnectorListenerManager.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/plugin/PluginConnector.java
src/main/java/net/pterodactylus/sone/freenet/plugin/event/ReceivedReplyEvent.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/freenet/wot/WebOfTrustConnector.java

diff --git a/src/main/java/net/pterodactylus/sone/freenet/plugin/ConnectorListener.java b/src/main/java/net/pterodactylus/sone/freenet/plugin/ConnectorListener.java
deleted file mode 100644 (file)
index 76a5497..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Sone - ConnectorListener.java - Copyright © 2010–2012 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.freenet.plugin;
-
-import java.util.EventListener;
-
-import freenet.support.SimpleFieldSet;
-import freenet.support.api.Bucket;
-
-/**
- * Interface for objects that want to be notified if a {@link PluginConnector}
- * receives a reply from a plugin. As a connection listener is always
- * {@link PluginConnector#addConnectorListener(String, String, ConnectorListener)
- * added} for a specific plugin, it will always be notified for replies from the
- * correct plugin (unless you register the same listener for multiple
- * plugins—which you subsequently should not do).
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public interface ConnectorListener extends EventListener {
-
-       /**
-        * A reply was received from the plugin this connection listener was added
-        * for.
-        *
-        * @param pluginConnector
-        *            The plugin connector that received the reply
-        * @param fields
-        *            The fields of the reply
-        * @param data
-        *            The data of the reply (may be null)
-        */
-       public void receivedReply(PluginConnector pluginConnector, SimpleFieldSet fields, Bucket data);
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/freenet/plugin/ConnectorListenerManager.java b/src/main/java/net/pterodactylus/sone/freenet/plugin/ConnectorListenerManager.java
deleted file mode 100644 (file)
index 742a514..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Sone - ConnectorListenerManager.java - Copyright © 2010–2012 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.freenet.plugin;
-
-import net.pterodactylus.util.event.AbstractListenerManager;
-import freenet.support.SimpleFieldSet;
-import freenet.support.api.Bucket;
-
-/**
- * Manages {@link ConnectorListener}s and fire events.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class ConnectorListenerManager extends AbstractListenerManager<PluginConnector, ConnectorListener> {
-
-       /**
-        * Creates a new manager for {@link ConnectorListener}s.
-        *
-        * @param pluginConnector
-        *            The plugin connector that is the source for all events
-        */
-       public ConnectorListenerManager(PluginConnector pluginConnector) {
-               super(pluginConnector);
-       }
-
-       //
-       // ACTIONS
-       //
-
-       /**
-        * Notifies all registered listeners that a reply from the plugin was
-        * received.
-        *
-        * @param fields
-        *            The fields of the reply
-        * @param data
-        *            The data of the reply (may be null)
-        */
-       public void fireReceivedReply(SimpleFieldSet fields, Bucket data) {
-               for (ConnectorListener connectorListener : getListeners()) {
-                       connectorListener.receivedReply(getSource(), fields, data);
-               }
-       }
-
-}
index d556a6c..b842350 100644 (file)
 
 package net.pterodactylus.sone.freenet.plugin;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+import net.pterodactylus.sone.freenet.plugin.event.ReceivedReplyEvent;
 
+import com.google.common.eventbus.EventBus;
 import com.google.inject.Inject;
 
 import freenet.pluginmanager.FredPluginTalker;
@@ -38,56 +37,27 @@ import freenet.support.api.Bucket;
  */
 public class PluginConnector implements FredPluginTalker {
 
+       /** The event bus. */
+       private final EventBus eventBus;
+
        /** The plugin respirator. */
        private final PluginRespirator pluginRespirator;
 
-       /** Connector listener managers for all plugin connections. */
-       private final Map<PluginIdentifier, ConnectorListenerManager> connectorListenerManagers = Collections.synchronizedMap(new HashMap<PluginIdentifier, ConnectorListenerManager>());
-
        /**
         * Creates a new plugin connector.
         *
+        * @param eventBus
+        *            The event bus
         * @param pluginRespirator
         *            The plugin respirator
         */
        @Inject
-       public PluginConnector(PluginRespirator pluginRespirator) {
+       public PluginConnector(EventBus eventBus, PluginRespirator pluginRespirator) {
+               this.eventBus = eventBus;
                this.pluginRespirator = pluginRespirator;
        }
 
        //
-       // LISTENER MANAGEMENT
-       //
-
-       /**
-        * Adds a connection listener for the given plugin connection.
-        *
-        * @param pluginName
-        *            The name of the plugin
-        * @param identifier
-        *            The identifier of the connection
-        * @param connectorListener
-        *            The listener to add
-        */
-       public void addConnectorListener(String pluginName, String identifier, ConnectorListener connectorListener) {
-               getConnectorListenerManager(pluginName, identifier).addListener(connectorListener);
-       }
-
-       /**
-        * Removes a connection listener for the given plugin connection.
-        *
-        * @param pluginName
-        *            The name of the plugin
-        * @param identifier
-        *            The identifier of the connection
-        * @param connectorListener
-        *            The listener to remove
-        */
-       public void removeConnectorListener(String pluginName, String identifier, ConnectorListener connectorListener) {
-               getConnectorListenerManager(pluginName, identifier).removeListener(connectorListener);
-       }
-
-       //
        // ACTIONS
        //
 
@@ -130,43 +100,6 @@ public class PluginConnector implements FredPluginTalker {
        //
 
        /**
-        * Returns the connection listener manager for the given plugin connection,
-        * creating a new one if none does exist yet.
-        *
-        * @param pluginName
-        *            The name of the plugin
-        * @param identifier
-        *            The identifier of the connection
-        * @return The connection listener manager
-        */
-       private ConnectorListenerManager getConnectorListenerManager(String pluginName, String identifier) {
-               return getConnectorListenerManager(pluginName, identifier, true);
-       }
-
-       /**
-        * Returns the connection listener manager for the given plugin connection,
-        * optionally creating a new one if none does exist yet.
-        *
-        * @param pluginName
-        *            The name of the plugin
-        * @param identifier
-        *            The identifier of the connection
-        * @param create
-        *            {@code true} to create a new manager if there is none,
-        *            {@code false} to return {@code null} in that case
-        * @return The connection listener manager, or {@code null} if none existed
-        *         and {@code create} is {@code false}
-        */
-       private ConnectorListenerManager getConnectorListenerManager(String pluginName, String identifier, boolean create) {
-               ConnectorListenerManager connectorListenerManager = connectorListenerManagers.get(new PluginIdentifier(pluginName, identifier));
-               if (create && (connectorListenerManager == null)) {
-                       connectorListenerManager = new ConnectorListenerManager(this);
-                       connectorListenerManagers.put(new PluginIdentifier(pluginName, identifier), connectorListenerManager);
-               }
-               return connectorListenerManager;
-       }
-
-       /**
         * Returns the plugin talker for the given plugin connection.
         *
         * @param pluginName
@@ -194,65 +127,7 @@ public class PluginConnector implements FredPluginTalker {
         */
        @Override
        public void onReply(String pluginName, String identifier, SimpleFieldSet params, Bucket data) {
-               ConnectorListenerManager connectorListenerManager = getConnectorListenerManager(pluginName, identifier, false);
-               if (connectorListenerManager == null) {
-                       /* we don’t care about events for this plugin. */
-                       return;
-               }
-               connectorListenerManager.fireReceivedReply(params, data);
-       }
-
-       /**
-        * Container for identifying plugins. Plugins are identified by their plugin
-        * name and their unique identifier.
-        *
-        * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
-        */
-       private static class PluginIdentifier {
-
-               /** The plugin name. */
-               private final String pluginName;
-
-               /** The plugin identifier. */
-               private final String identifier;
-
-               /**
-                * Creates a new plugin identifier.
-                *
-                * @param pluginName
-                *            The name of the plugin
-                * @param identifier
-                *            The identifier of the plugin
-                */
-               public PluginIdentifier(String pluginName, String identifier) {
-                       this.pluginName = pluginName;
-                       this.identifier = identifier;
-               }
-
-               //
-               // OBJECT METHODS
-               //
-
-               /**
-                * {@inheritDoc}
-                */
-               @Override
-               public int hashCode() {
-                       return pluginName.hashCode() ^ identifier.hashCode();
-               }
-
-               /**
-                * {@inheritDoc}
-                */
-               @Override
-               public boolean equals(Object object) {
-                       if (!(object instanceof PluginIdentifier)) {
-                               return false;
-                       }
-                       PluginIdentifier pluginIdentifier = (PluginIdentifier) object;
-                       return pluginName.equals(pluginIdentifier.pluginName) && identifier.equals(pluginIdentifier.identifier);
-               }
-
+               eventBus.post(new ReceivedReplyEvent(this, pluginName, identifier, params, data));
        }
 
 }
diff --git a/src/main/java/net/pterodactylus/sone/freenet/plugin/event/ReceivedReplyEvent.java b/src/main/java/net/pterodactylus/sone/freenet/plugin/event/ReceivedReplyEvent.java
new file mode 100644 (file)
index 0000000..89a8df3
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Sone - ReceivedReplyEvent.java - Copyright © 2013 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.freenet.plugin.event;
+
+import net.pterodactylus.sone.freenet.plugin.PluginConnector;
+import freenet.support.SimpleFieldSet;
+import freenet.support.api.Bucket;
+
+/**
+ * Event that signals that a plugin reply was received.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ReceivedReplyEvent {
+
+       /** The connector that received the reply. */
+       private final PluginConnector pluginConnector;
+
+       /** The name of the plugin that sent the reply. */
+       private final String pluginName;
+
+       /** The identifier of the initial request. */
+       private final String identifier;
+
+       /** The fields containing the reply. */
+       private final SimpleFieldSet fieldSet;
+
+       /** The optional reply data. */
+       private final Bucket data;
+
+       /**
+        * Creates a new “reply received” event.
+        *
+        * @param pluginConnector
+        *            The connector that received the event
+        * @param pluginName
+        *            The name of the plugin that sent the reply
+        * @param identifier
+        *            The identifier of the initial request
+        * @param fieldSet
+        *            The fields containing the reply
+        * @param data
+        *            The optional data of the reply
+        */
+       public ReceivedReplyEvent(PluginConnector pluginConnector, String pluginName, String identifier, SimpleFieldSet fieldSet, Bucket data) {
+               this.pluginConnector = pluginConnector;
+               this.pluginName = pluginName;
+               this.identifier = identifier;
+               this.fieldSet = fieldSet;
+               this.data = data;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the plugin connector that received the reply.
+        *
+        * @return The plugin connector that received the reply
+        */
+       public PluginConnector pluginConnector() {
+               return pluginConnector;
+       }
+
+       /**
+        * Returns the name of the plugin that sent the reply.
+        *
+        * @return The name of the plugin that sent the reply
+        */
+       public String pluginName() {
+               return pluginName;
+       }
+
+       /**
+        * Returns the identifier of the initial request.
+        *
+        * @return The identifier of the initial request
+        */
+       public String identifier() {
+               return identifier;
+       }
+
+       /**
+        * Returns the fields containing the reply.
+        *
+        * @return The fields containing the reply
+        */
+       public SimpleFieldSet fieldSet() {
+               return fieldSet;
+       }
+
+       /**
+        * Returns the optional data of the reply.
+        *
+        * @return The optional data of the reply (may be {@code null})
+        */
+       public Bucket data() {
+               return data;
+       }
+
+}
index 18dbaff..28c9f01 100644 (file)
@@ -25,12 +25,14 @@ import java.util.concurrent.atomic.AtomicLong;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import net.pterodactylus.sone.freenet.plugin.ConnectorListener;
 import net.pterodactylus.sone.freenet.plugin.PluginConnector;
 import net.pterodactylus.sone.freenet.plugin.PluginException;
+import net.pterodactylus.sone.freenet.plugin.event.ReceivedReplyEvent;
 import net.pterodactylus.util.logging.Logging;
 import net.pterodactylus.util.number.Numbers;
 
+import com.google.common.collect.MapMaker;
+import com.google.common.eventbus.Subscribe;
 import com.google.inject.Inject;
 
 import freenet.support.SimpleFieldSet;
@@ -55,6 +57,9 @@ public class WebOfTrustConnector {
        /** The plugin connector. */
        private final PluginConnector pluginConnector;
 
+       /** Map for replies. */
+       private final Map<PluginIdentifier, Reply> replies = new MapMaker().makeMap();
+
        /**
         * Creates a new Web of Trust connector that uses the given plugin
         * connector.
@@ -384,24 +389,12 @@ public class WebOfTrustConnector {
         *             if the request could not be sent
         */
        private Reply performRequest(SimpleFieldSet fields, Bucket data) throws PluginException {
-               final String identifier = "FCP-Command-" + System.currentTimeMillis() + "-" + counter.getAndIncrement();
-               final Reply reply = new Reply();
+               String identifier = "FCP-Command-" + System.currentTimeMillis() + "-" + counter.getAndIncrement();
+               Reply reply = new Reply();
+               PluginIdentifier pluginIdentifier = new PluginIdentifier(WOT_PLUGIN_NAME, identifier);
+               replies.put(pluginIdentifier, reply);
+
                logger.log(Level.FINE, String.format("Sending FCP Request: %s", fields.get("Message")));
-               ConnectorListener connectorListener = new ConnectorListener() {
-
-                       @Override
-                       @SuppressWarnings("synthetic-access")
-                       public void receivedReply(PluginConnector pluginConnector, SimpleFieldSet fields, Bucket data) {
-                               String messageName = fields.get("Message");
-                               logger.log(Level.FINEST, String.format("Received Reply from Plugin: %s", messageName));
-                               synchronized (reply) {
-                                       reply.setFields(fields);
-                                       reply.setData(data);
-                                       reply.notify();
-                               }
-                       }
-               };
-               pluginConnector.addConnectorListener(WOT_PLUGIN_NAME, identifier, connectorListener);
                synchronized (reply) {
                        try {
                                pluginConnector.sendRequest(WOT_PLUGIN_NAME, identifier, fields, data);
@@ -413,7 +406,7 @@ public class WebOfTrustConnector {
                                        }
                                }
                        } finally {
-                               pluginConnector.removeConnectorListener(WOT_PLUGIN_NAME, identifier, connectorListener);
+                               replies.remove(pluginIdentifier);
                        }
                }
                logger.log(Level.FINEST, String.format("Received FCP Response for %s: %s", fields.get("Message"), (reply.getFields() != null) ? reply.getFields().get("Message") : null));
@@ -424,6 +417,27 @@ public class WebOfTrustConnector {
        }
 
        /**
+        * Notifies the connector that a plugin reply was received.
+        *
+        * @param receivedReplyEvent
+        *            The event
+        */
+       @Subscribe
+       public void receivedReply(ReceivedReplyEvent receivedReplyEvent) {
+               PluginIdentifier pluginIdentifier = new PluginIdentifier(receivedReplyEvent.pluginName(), receivedReplyEvent.identifier());
+               Reply reply = replies.remove(pluginIdentifier);
+               if (reply == null) {
+                       return;
+               }
+               logger.log(Level.FINEST, String.format("Received Reply from Plugin: %s", receivedReplyEvent.fieldSet().get("Message")));
+               synchronized (reply) {
+                       reply.setFields(receivedReplyEvent.fieldSet());
+                       reply.setData(receivedReplyEvent.data());
+                       reply.notify();
+               }
+       }
+
+       /**
         * Container for the data of the reply from a plugin.
         *
         * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
@@ -558,4 +572,57 @@ public class WebOfTrustConnector {
 
        }
 
+       /**
+        * Container for identifying plugins. Plugins are identified by their plugin
+        * name and their unique identifier.
+        *
+        * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
+        */
+       private static class PluginIdentifier {
+
+               /** The plugin name. */
+               private final String pluginName;
+
+               /** The plugin identifier. */
+               private final String identifier;
+
+               /**
+                * Creates a new plugin identifier.
+                *
+                * @param pluginName
+                *            The name of the plugin
+                * @param identifier
+                *            The identifier of the plugin
+                */
+               public PluginIdentifier(String pluginName, String identifier) {
+                       this.pluginName = pluginName;
+                       this.identifier = identifier;
+               }
+
+               //
+               // OBJECT METHODS
+               //
+
+               /**
+                * {@inheritDoc}
+                */
+               @Override
+               public int hashCode() {
+                       return pluginName.hashCode() ^ identifier.hashCode();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               @Override
+               public boolean equals(Object object) {
+                       if (!(object instanceof PluginIdentifier)) {
+                               return false;
+                       }
+                       PluginIdentifier pluginIdentifier = (PluginIdentifier) object;
+                       return pluginName.equals(pluginIdentifier.pluginName) && identifier.equals(pluginIdentifier.identifier);
+               }
+
+       }
+
 }