2 * Sone - IdentityManager.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;
23 import java.util.Map.Entry;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
28 import net.pterodactylus.util.filter.Filter;
29 import net.pterodactylus.util.filter.Filters;
30 import net.pterodactylus.util.logging.Logging;
31 import net.pterodactylus.util.service.AbstractService;
34 * The identity manager takes care of loading and storing identities, their
35 * contexts, and properties. It does so in a way that does not expose errors via
36 * exceptions but it only logs them and tries to return sensible defaults.
38 * It is also responsible for polling identities from the Web of Trust plugin
39 * and notifying registered {@link IdentityListener}s when {@link Identity}s and
40 * {@link OwnIdentity}s are discovered or disappearing.
42 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
44 public class IdentityManager extends AbstractService {
47 private static final Logger logger = Logging.getLogger(IdentityManager.class);
49 /** The event manager. */
50 private final IdentityListenerManager identityListenerManager = new IdentityListenerManager();
52 /** The Web of Trust connector. */
53 private final WebOfTrustConnector webOfTrustConnector;
55 /** The context to filter for. */
56 private volatile String context;
58 /** Whether the Web of Trust plugin is connected. */
59 private volatile boolean wotPluginConnected = false;
62 * Creates a new identity manager.
64 * @param webOfTrustConnector
65 * The Web of Trust connector
67 public IdentityManager(WebOfTrustConnector webOfTrustConnector) {
68 super("Sone Identity Manager", false);
69 this.webOfTrustConnector = webOfTrustConnector;
73 // LISTENER MANAGEMENT
77 * Adds a listener for identity events.
79 * @param identityListener
82 public void addIdentityListener(IdentityListener identityListener) {
83 identityListenerManager.addListener(identityListener);
87 * Removes a listener for identity events.
89 * @param identityListener
90 * The listener to remove
92 public void removeIdentityListener(IdentityListener identityListener) {
93 identityListenerManager.removeListener(identityListener);
101 * Sets the context to filter own identities and trusted identities for.
104 * The context to filter for, or {@code null} to not filter
106 public void setContext(String context) {
107 this.context = context;
111 * Returns whether the Web of Trust plugin could be reached during the last
114 * @return {@code true} if the Web of Trust plugin is connected,
115 * {@code false} otherwise
117 public boolean isConnected() {
118 return wotPluginConnected;
122 * Returns the own identity with the given ID.
125 * The ID of the own identity
126 * @return The own identity, or {@code null} if there is no such identity
128 public OwnIdentity getOwnIdentity(String id) {
129 Set<OwnIdentity> allOwnIdentities = getAllOwnIdentities();
130 for (OwnIdentity ownIdentity : allOwnIdentities) {
131 if (ownIdentity.getId().equals(id)) {
139 * Returns all own identities.
141 * @return All own identities
143 public Set<OwnIdentity> getAllOwnIdentities() {
145 Set<OwnIdentity> allOwnIdentities = webOfTrustConnector.loadAllOwnIdentities();
146 wotPluginConnected = true;
147 return allOwnIdentities;
148 } catch (PluginException pe1) {
149 logger.log(Level.WARNING, "Could not load all own identities!", pe1);
150 wotPluginConnected = false;
151 return Collections.emptySet();
160 * Adds a context to the given own identity.
167 public void addContext(OwnIdentity ownIdentity, String context) {
168 if (ownIdentity.hasContext(context)) {
172 webOfTrustConnector.addContext(ownIdentity, context);
173 wotPluginConnected = true;
174 ownIdentity.addContext(context);
175 } catch (PluginException pe1) {
176 logger.log(Level.WARNING, "Could not add context " + context + " to OwnIdentity " + ownIdentity + ".", pe1);
177 wotPluginConnected = false;
182 * Removes a context from the given own identity.
187 * The context to remove
189 public void removeContext(OwnIdentity ownIdentity, String context) {
190 if (!ownIdentity.hasContext(context)) {
194 webOfTrustConnector.removeContext(ownIdentity, context);
195 wotPluginConnected = true;
196 ownIdentity.removeContext(context);
197 } catch (PluginException pe1) {
198 logger.log(Level.WARNING, "Could not remove context " + context + " from OwnIdentity " + ownIdentity + ".", pe1);
199 wotPluginConnected = false;
204 * Sets the property with the given name to the given value.
209 * The name of the property
211 * The value of the property
213 public void setProperty(OwnIdentity ownIdentity, String name, String value) {
215 webOfTrustConnector.setProperty(ownIdentity, name, value);
216 wotPluginConnected = true;
217 ownIdentity.setProperty(name, value);
218 } catch (PluginException pe1) {
219 logger.log(Level.WARNING, "Could not set property “" + name + "” to “" + value + "” for OwnIdentity: " + ownIdentity, pe1);
220 wotPluginConnected = false;
225 * Removes the property with the given name.
230 * The name of the property to remove
232 public void removeProperty(OwnIdentity ownIdentity, String name) {
234 webOfTrustConnector.removeProperty(ownIdentity, name);
235 wotPluginConnected = true;
236 ownIdentity.removeProperty(name);
237 } catch (PluginException pe1) {
238 logger.log(Level.WARNING, "Could not remove property “" + name + "” from OwnIdentity: " + ownIdentity, pe1);
239 wotPluginConnected = false;
251 protected void serviceRun() {
252 Map<String, Identity> oldIdentities = Collections.emptyMap();
253 Map<String, OwnIdentity> oldOwnIdentities = Collections.emptyMap();
254 while (!shouldStop()) {
255 Map<String, Identity> currentIdentities = new HashMap<String, Identity>();
256 Map<String, OwnIdentity> currentOwnIdentities = new HashMap<String, OwnIdentity>();
258 /* get all identities with the wanted context from WoT. */
259 Set<OwnIdentity> ownIdentities;
261 ownIdentities = Filters.filteredSet(webOfTrustConnector.loadAllOwnIdentities(), new Filter<OwnIdentity>() {
264 @SuppressWarnings("synthetic-access")
265 public boolean filterObject(OwnIdentity ownIdentity) {
266 return (context == null) || ownIdentity.hasContext(context);
270 for (OwnIdentity ownIdentity : ownIdentities) {
271 currentOwnIdentities.put(ownIdentity.getId(), ownIdentity);
272 for (Identity identity : webOfTrustConnector.loadTrustedIdentities(ownIdentity, context)) {
273 currentIdentities.put(identity.getId(), identity);
277 /* find removed own identities: */
278 for (OwnIdentity oldOwnIdentity : oldOwnIdentities.values()) {
279 if (!currentOwnIdentities.containsKey(oldOwnIdentity.getId())) {
280 identityListenerManager.fireOwnIdentityRemoved(oldOwnIdentity);
284 /* find added own identities. */
285 for (OwnIdentity currentOwnIdentity : currentOwnIdentities.values()) {
286 if (!oldOwnIdentities.containsKey(currentOwnIdentity.getId())) {
287 identityListenerManager.fireOwnIdentityAdded(currentOwnIdentity);
291 /* find removed identities. */
292 for (Identity oldIdentity : oldIdentities.values()) {
293 if (!currentIdentities.containsKey(oldIdentity.getId())) {
294 identityListenerManager.fireIdentityRemoved(oldIdentity);
298 /* find new identities. */
299 for (Identity currentIdentity : currentIdentities.values()) {
300 if (!oldIdentities.containsKey(currentIdentity.getId())) {
301 identityListenerManager.fireIdentityAdded(currentIdentity);
305 /* check for changes in the properties. */
306 for (Identity oldIdentity : oldIdentities.values()) {
307 if (!currentIdentities.containsKey(oldIdentity.getId())) {
310 Identity newIdentity = currentIdentities.get(oldIdentity.getId());
311 Map<String, String> oldProperties = oldIdentity.getProperties();
312 Map<String, String> newProperties = newIdentity.getProperties();
313 if (oldProperties.size() != newProperties.size()) {
314 identityListenerManager.fireIdentityUpdated(newIdentity);
317 for (Entry<String, String> oldProperty : oldProperties.entrySet()) {
318 if (!newProperties.containsKey(oldProperty.getKey()) || !newProperties.get(oldProperty.getKey()).equals(oldProperty.getValue())) {
319 identityListenerManager.fireIdentityUpdated(newIdentity);
325 /* remember the current set of identities. */
326 oldIdentities = currentIdentities;
327 oldOwnIdentities = currentOwnIdentities;
329 } catch (PluginException pe1) {
330 logger.log(Level.WARNING, "WoT has disappeared!", pe1);
333 /* wait a minute before checking again. */