Synchronize access on an identity’s trust cache.
[Sone.git] / src / main / java / net / pterodactylus / sone / freenet / plugin / PluginConnector.java
1 /*
2  * Sone - PluginConnector.java - Copyright © 2010 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.freenet.plugin;
19
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import net.pterodactylus.util.collection.Pair;
25 import freenet.pluginmanager.FredPluginTalker;
26 import freenet.pluginmanager.PluginNotFoundException;
27 import freenet.pluginmanager.PluginRespirator;
28 import freenet.pluginmanager.PluginTalker;
29 import freenet.support.SimpleFieldSet;
30 import freenet.support.api.Bucket;
31
32 /**
33  * Interface for talking to other plugins. Other plugins are identified by their
34  * name and a unique connection identifier.
35  *
36  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
37  */
38 public class PluginConnector implements FredPluginTalker {
39
40         /** The plugin respirator. */
41         private final PluginRespirator pluginRespirator;
42
43         /** Connector listener managers for all plugin connections. */
44         private final Map<Pair<String, String>, ConnectorListenerManager> connectorListenerManagers = Collections.synchronizedMap(new HashMap<Pair<String, String>, ConnectorListenerManager>());
45
46         /**
47          * Creates a new plugin connector.
48          *
49          * @param pluginRespirator
50          *            The plugin respirator
51          */
52         public PluginConnector(PluginRespirator pluginRespirator) {
53                 this.pluginRespirator = pluginRespirator;
54         }
55
56         //
57         // LISTENER MANAGEMENT
58         //
59
60         /**
61          * Adds a connection listener for the given plugin connection.
62          *
63          * @param pluginName
64          *            The name of the plugin
65          * @param identifier
66          *            The identifier of the connection
67          * @param connectorListener
68          *            The listener to add
69          */
70         public void addConnectorListener(String pluginName, String identifier, ConnectorListener connectorListener) {
71                 getConnectorListenerManager(pluginName, identifier).addListener(connectorListener);
72         }
73
74         /**
75          * Removes a connection listener for the given plugin connection.
76          *
77          * @param pluginName
78          *            The name of the plugin
79          * @param identifier
80          *            The identifier of the connection
81          * @param connectorListener
82          *            The listener to remove
83          */
84         public void removeConnectorListener(String pluginName, String identifier, ConnectorListener connectorListener) {
85                 getConnectorListenerManager(pluginName, identifier).removeListener(connectorListener);
86         }
87
88         //
89         // ACTIONS
90         //
91
92         /**
93          * Sends a request to the given plugin.
94          *
95          * @param pluginName
96          *            The name of the plugin
97          * @param identifier
98          *            The identifier of the connection
99          * @param fields
100          *            The fields of the message
101          * @throws PluginException
102          *             if the plugin can not be found
103          */
104         public void sendRequest(String pluginName, String identifier, SimpleFieldSet fields) throws PluginException {
105                 sendRequest(pluginName, identifier, fields, null);
106         }
107
108         /**
109          * Sends a request to the given plugin.
110          *
111          * @param pluginName
112          *            The name of the plugin
113          * @param identifier
114          *            The identifier of the connection
115          * @param fields
116          *            The fields of the message
117          * @param data
118          *            The payload of the message (may be null)
119          * @throws PluginException
120          *             if the plugin can not be found
121          */
122         public void sendRequest(String pluginName, String identifier, SimpleFieldSet fields, Bucket data) throws PluginException {
123                 getPluginTalker(pluginName, identifier).send(fields, data);
124         }
125
126         //
127         // PRIVATE METHODS
128         //
129
130         /**
131          * Returns the connection listener manager for the given plugin connection,
132          * creating a new one if none does exist yet.
133          *
134          * @param pluginName
135          *            The name of the plugin
136          * @param identifier
137          *            The identifier of the connection
138          * @return The connection listener manager
139          */
140         private ConnectorListenerManager getConnectorListenerManager(String pluginName, String identifier) {
141                 return getConnectorListenerManager(pluginName, identifier, true);
142         }
143
144         /**
145          * Returns the connection listener manager for the given plugin connection,
146          * optionally creating a new one if none does exist yet.
147          *
148          * @param pluginName
149          *            The name of the plugin
150          * @param identifier
151          *            The identifier of the connection
152          * @param create
153          *            {@code true} to create a new manager if there is none,
154          *            {@code false} to return {@code null} in that case
155          * @return The connection listener manager, or {@code null} if none existed
156          *         and {@code create} is {@code false}
157          */
158         private ConnectorListenerManager getConnectorListenerManager(String pluginName, String identifier, boolean create) {
159                 ConnectorListenerManager connectorListenerManager = connectorListenerManagers.get(new Pair<String, String>(pluginName, identifier));
160                 if (create && (connectorListenerManager == null)) {
161                         connectorListenerManager = new ConnectorListenerManager(this);
162                         connectorListenerManagers.put(new Pair<String, String>(pluginName, identifier), connectorListenerManager);
163                 }
164                 return connectorListenerManager;
165         }
166
167         /**
168          * Returns the plugin talker for the given plugin connection.
169          *
170          * @param pluginName
171          *            The name of the plugin
172          * @param identifier
173          *            The identifier of the connection
174          * @return The plugin talker
175          * @throws PluginException
176          *             if the plugin can not be found
177          */
178         private PluginTalker getPluginTalker(String pluginName, String identifier) throws PluginException {
179                 try {
180                         return pluginRespirator.getPluginTalker(this, pluginName, identifier);
181                 } catch (PluginNotFoundException pnfe1) {
182                         throw new PluginException(pnfe1);
183                 }
184         }
185
186         //
187         // INTERFACE FredPluginTalker
188         //
189
190         /**
191          * {@inheritDoc}
192          */
193         @Override
194         public void onReply(String pluginName, String identifier, SimpleFieldSet params, Bucket data) {
195                 ConnectorListenerManager connectorListenerManager = getConnectorListenerManager(pluginName, identifier, false);
196                 if (connectorListenerManager == null) {
197                         /* we don’t care about events for this plugin. */
198                         return;
199                 }
200                 connectorListenerManager.fireReceivedReply(params, data);
201         }
202
203 }