+++ /dev/null
-/*
- * 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);
-
-}
+++ /dev/null
-/*
- * 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);
- }
- }
-
-}
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;
*/
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
//
//
/**
- * 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
*/
@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));
}
}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
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;
/** 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.
* 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);
}
}
} 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));
}
/**
+ * 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>
}
+ /**
+ * 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);
+ }
+
+ }
+
}