2 * Sone - WebOfTrustConnector.java - Copyright © 2010 David Roden
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.
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.
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/>.
18 package net.pterodactylus.sone.freenet.wot;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
28 import net.pterodactylus.util.logging.Logging;
29 import freenet.support.SimpleFieldSet;
30 import freenet.support.api.Bucket;
33 * Connector for the Web of Trust plugin.
35 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
37 public class WebOfTrustConnector implements ConnectorListener {
40 private static final Logger logger = Logging.getLogger(WebOfTrustConnector.class);
42 /** The name of the WoT plugin. */
43 private static final String WOT_PLUGIN_NAME = "plugins.WoT.WoT";
45 /** A random connection identifier. */
46 private static final String PLUGIN_CONNECTION_IDENTIFIER = "Sone-WoT-Connector-" + Math.abs(Math.random());
48 /** The current replies that we wait for. */
49 private final Map<String, Reply> replies = Collections.synchronizedMap(new HashMap<String, Reply>());
51 /** The plugin connector. */
52 private final PluginConnector pluginConnector;
55 * Creates a new Web of Trust connector that uses the given plugin
58 * @param pluginConnector
59 * The plugin connector
61 public WebOfTrustConnector(PluginConnector pluginConnector) {
62 this.pluginConnector = pluginConnector;
63 pluginConnector.addConnectorListener(WOT_PLUGIN_NAME, PLUGIN_CONNECTION_IDENTIFIER, this);
71 * Loads all own identities from the Web of Trust plugin.
73 * @return All own identity
74 * @throws PluginException
75 * if the own identities can not be loaded
77 public Set<OwnIdentity> loadAllOwnIdentities() throws PluginException {
78 Reply reply = performRequest("OwnIdentities", SimpleFieldSetConstructor.create().put("Message", "GetOwnIdentities").get());
79 SimpleFieldSet fields = reply.getFields();
80 int ownIdentityCounter = -1;
81 Set<OwnIdentity> ownIdentities = new HashSet<OwnIdentity>();
83 String id = fields.get("Identity" + ++ownIdentityCounter);
87 String requestUri = fields.get("RequestURI" + ownIdentityCounter);
88 String insertUri = fields.get("InsertURI" + ownIdentityCounter);
89 String nickname = fields.get("Nickname" + ownIdentityCounter);
90 OwnIdentity ownIdentity = new OwnIdentity(this, id, nickname, requestUri, insertUri);
91 ownIdentities.add(ownIdentity);
97 * Loads the contexts of the given identity.
100 * The identity to load the contexts for
101 * @return The contexts of the identity
102 * @throws PluginException
103 * if an error occured talking to the Web of Trust plugin
105 public Set<String> loadIdentityContexts(Identity identity) throws PluginException {
106 Reply reply = performRequest("Identity", SimpleFieldSetConstructor.create().put("Message", "GetIdentity").put("TreeOwner", identity.getId()).put("Identity", identity.getId()).get());
107 SimpleFieldSet fields = reply.getFields();
108 int contextCounter = -1;
109 Set<String> contexts = new HashSet<String>();
111 String context = fields.get("Context" + ++contextCounter);
112 if (context == null) {
115 contexts.add(context);
121 * Loads all identities that the given identities trusts with a score of
126 * @return All trusted identities
127 * @throws PluginException
128 * if an error occured talking to the Web of Trust plugin
130 public Set<Identity> loadTrustedIdentities(OwnIdentity ownIdentity) throws PluginException {
131 return loadTrustedIdentities(ownIdentity, null);
135 * Loads all identities that the given identities trusts with a score of
136 * more than 0 and the (optional) given context.
141 * The context to filter, or {@code null}
142 * @return All trusted identities
143 * @throws PluginException
144 * if an error occured talking to the Web of Trust plugin
146 public Set<Identity> loadTrustedIdentities(OwnIdentity ownIdentity, String context) throws PluginException {
147 Reply reply = performRequest("Identities", SimpleFieldSetConstructor.create().put("Message", "GetIdentitiesByScore").put("TreeOwner", ownIdentity.getId()).put("Selection", "+").put("Context", (context == null) ? "" : context).get());
148 SimpleFieldSet fields = reply.getFields();
149 Set<Identity> identities = new HashSet<Identity>();
150 int identityCounter = -1;
152 String id = fields.get("Identity" + ++identityCounter);
156 String nickname = fields.get("Nickname" + identityCounter);
157 String requestUri = fields.get("RequestURI" + identityCounter);
158 identities.add(new Identity(this, id, nickname, requestUri));
164 * Adds the given context to the given identity.
167 * The identity to add the context to
170 * @throws PluginException
171 * if an error occured talking to the Web of Trust plugin
173 public void addContext(OwnIdentity ownIdentity, String context) throws PluginException {
174 performRequest("ContextAdded", SimpleFieldSetConstructor.create().put("Message", "AddContext").put("Identity", ownIdentity.getId()).put("Context", context).get());
178 * Removes the given context from the given identity.
181 * The identity to remove the context from
183 * The context to remove
184 * @throws PluginException
185 * if an error occured talking to the Web of Trust plugin
187 public void removeContext(OwnIdentity ownIdentity, String context) throws PluginException {
188 performRequest("ContextRemoved", SimpleFieldSetConstructor.create().put("Message", "RemoveContext").put("Identity", ownIdentity.getId()).put("Context", context).get());
196 * Sends a request containing the given fields and waits for the target
199 * @param targetMessage
200 * The message of the reply to wait for
202 * The fields of the message
203 * @return The reply message
204 * @throws PluginException
205 * if the request could not be sent
207 private Reply performRequest(String targetMessage, SimpleFieldSet fields) throws PluginException {
208 return performRequest(targetMessage, fields, null);
212 * Sends a request containing the given fields and waits for the target
215 * @param targetMessage
216 * The message of the reply to wait for
218 * The fields of the message
220 * The payload of the message
221 * @return The reply message
222 * @throws PluginException
223 * if the request could not be sent
225 private Reply performRequest(String targetMessage, SimpleFieldSet fields, Bucket data) throws PluginException {
226 @SuppressWarnings("synthetic-access")
227 Reply reply = new Reply();
228 replies.put(targetMessage, reply);
229 synchronized (reply) {
230 pluginConnector.sendRequest(WOT_PLUGIN_NAME, PLUGIN_CONNECTION_IDENTIFIER, fields, data);
233 } catch (InterruptedException ie1) {
234 logger.log(Level.WARNING, "Got interrupted while waiting for reply on GetOwnIdentities.", ie1);
241 // INTERFACE ConnectorListener
248 public void receivedReply(PluginConnector pluginConnector, SimpleFieldSet fields, Bucket data) {
249 String messageName = fields.get("Message");
250 Reply reply = replies.remove(messageName);
252 logger.log(Level.FINE, "Not waiting for a “%s” message.", messageName);
255 synchronized (reply) {
256 reply.setFields(fields);
263 * Container for the data of the reply from a plugin.
265 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
267 private static class Reply {
269 /** The fields of the reply. */
270 private SimpleFieldSet fields;
272 /** The payload of the reply. */
276 * Returns the fields of the reply.
278 * @return The fields of the reply
280 public SimpleFieldSet getFields() {
285 * Sets the fields of the reply.
288 * The fields of the reply
290 public void setFields(SimpleFieldSet fields) {
291 this.fields = fields;
295 * Returns the payload of the reply.
297 * @return The payload of the reply (may be {@code null})
299 @SuppressWarnings("unused")
300 public Bucket getData() {
305 * Sets the payload of the reply.
308 * The payload of the reply (may be {@code null})
310 public void setData(Bucket data) {
317 * Helper method to create {@link SimpleFieldSet}s with terser code.
319 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
321 private static class SimpleFieldSetConstructor {
323 /** The field set being created. */
324 private SimpleFieldSet simpleFieldSet;
327 * Creates a new simple field set constructor.
330 * {@code true} if the resulting simple field set should be
331 * short-lived, {@code false} otherwise
333 private SimpleFieldSetConstructor(boolean shortLived) {
334 simpleFieldSet = new SimpleFieldSet(shortLived);
342 * Returns the created simple field set.
344 * @return The created simple field set
346 public SimpleFieldSet get() {
347 return simpleFieldSet;
351 * Sets the field with the given name to the given value.
354 * The name of the fleld
356 * The value of the field
357 * @return This constructor (for method chaining)
359 public SimpleFieldSetConstructor put(String name, String value) {
360 simpleFieldSet.putOverwrite(name, value);
369 * Creates a new simple field set constructor.
371 * @return The created simple field set constructor
373 public static SimpleFieldSetConstructor create() {
378 * Creates a new simple field set constructor.
381 * {@code true} if the resulting simple field set should be
382 * short-lived, {@code false} otherwise
383 * @return The created simple field set constructor
385 public static SimpleFieldSetConstructor create(boolean shortLived) {
386 SimpleFieldSetConstructor simpleFieldSetConstructor = new SimpleFieldSetConstructor(shortLived);
387 return simpleFieldSetConstructor;