X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Ffreenet%2Fwot%2FIdentityManager.java;h=2459c069487b69be21c6b6c31ebb7642ea0103d6;hb=abdbf862767ed420c556669bf002960968f0090b;hp=e7a82b51f7e9c466acfd824555dbed1384b2debc;hpb=e7d03da9fe88c41edf8b3bffa7a6c0717653d834;p=Sone.git diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManager.java b/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManager.java index e7a82b5..2459c06 100644 --- a/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManager.java +++ b/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManager.java @@ -1,5 +1,5 @@ /* - * Sone - IdentityManager.java - Copyright © 2010 David Roden + * Sone - IdentityManager.java - Copyright © 2010–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 @@ -17,27 +17,38 @@ package net.pterodactylus.sone.freenet.wot; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; +import static com.google.common.collect.HashMultimap.create; + +import java.util.Collection; +import java.util.HashSet; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import net.pterodactylus.util.filter.Filter; -import net.pterodactylus.util.filter.Filters; +import net.pterodactylus.sone.freenet.plugin.PluginException; +import net.pterodactylus.sone.freenet.wot.IdentityChangeDetector.IdentityProcessor; +import net.pterodactylus.sone.freenet.wot.event.IdentityAddedEvent; +import net.pterodactylus.sone.freenet.wot.event.IdentityRemovedEvent; +import net.pterodactylus.sone.freenet.wot.event.IdentityUpdatedEvent; +import net.pterodactylus.sone.freenet.wot.event.OwnIdentityAddedEvent; +import net.pterodactylus.sone.freenet.wot.event.OwnIdentityRemovedEvent; import net.pterodactylus.util.logging.Logging; import net.pterodactylus.util.service.AbstractService; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; +import com.google.common.eventbus.EventBus; +import com.google.inject.Inject; +import com.google.inject.name.Named; + /** * The identity manager takes care of loading and storing identities, their * contexts, and properties. It does so in a way that does not expose errors via * exceptions but it only logs them and tries to return sensible defaults. - *

+ *

* It is also responsible for polling identities from the Web of Trust plugin - * and notifying registered {@link IdentityListener}s when {@link Identity}s and - * {@link OwnIdentity}s are discovered or disappearing. + * and sending events to the {@link EventBus} when {@link Identity}s and {@link + * OwnIdentity}s are discovered or disappearing. * * @author David ‘Bombe’ Roden */ @@ -46,48 +57,35 @@ public class IdentityManager extends AbstractService { /** The logger. */ private static final Logger logger = Logging.getLogger(IdentityManager.class); - /** The event manager. */ - private final IdentityListenerManager identityListenerManager = new IdentityListenerManager(); + /** The event bus. */ + private final EventBus eventBus; /** The Web of Trust connector. */ private final WebOfTrustConnector webOfTrustConnector; /** The context to filter for. */ - private volatile String context; + private final String context; + + /** The currently known own identities. */ + /* synchronize access on syncObject. */ + private final Set currentOwnIdentities = Sets.newHashSet(); /** * Creates a new identity manager. * + * @param eventBus + * The event bus * @param webOfTrustConnector - * The Web of Trust connector + * The Web of Trust connector + * @param context + * The context to focus on (may be {@code null} to ignore contexts) */ - public IdentityManager(WebOfTrustConnector webOfTrustConnector) { + @Inject + public IdentityManager(EventBus eventBus, WebOfTrustConnector webOfTrustConnector, @Named("WebOfTrustContext") String context) { super("Sone Identity Manager", false); + this.eventBus = eventBus; this.webOfTrustConnector = webOfTrustConnector; - } - - // - // LISTENER MANAGEMENT - // - - /** - * Adds a listener for identity events. - * - * @param identityListener - * The listener to add - */ - public void addIdentityListener(IdentityListener identityListener) { - identityListenerManager.addListener(identityListener); - } - - /** - * Removes a listener for identity events. - * - * @param identityListener - * The listener to remove - */ - public void removeIdentityListener(IdentityListener identityListener) { - identityListenerManager.removeListener(identityListener); + this.context = context; } // @@ -95,21 +93,11 @@ public class IdentityManager extends AbstractService { // /** - * Sets the context to filter own identities and trusted identities for. - * - * @param context - * The context to filter for, or {@code null} to not filter - */ - public void setContext(String context) { - this.context = context; - } - - /** * Returns whether the Web of Trust plugin could be reached during the last * try. * - * @return {@code true} if the Web of Trust plugin is connected, - * {@code false} otherwise + * @return {@code true} if the Web of Trust plugin is connected, {@code false} + * otherwise */ public boolean isConnected() { try { @@ -122,209 +110,144 @@ public class IdentityManager extends AbstractService { } /** - * Returns the own identity with the given ID. - * - * @param id - * The ID of the own identity - * @return The own identity, or {@code null} if there is no such identity - */ - public OwnIdentity getOwnIdentity(String id) { - Set allOwnIdentities = getAllOwnIdentities(); - for (OwnIdentity ownIdentity : allOwnIdentities) { - if (ownIdentity.getId().equals(id)) { - return ownIdentity; - } - } - return null; - } - - /** * Returns all own identities. * * @return All own identities */ public Set getAllOwnIdentities() { - try { - return webOfTrustConnector.loadAllOwnIdentities(); - } catch (PluginException pe1) { - logger.log(Level.WARNING, "Could not load all own identities!", pe1); - return Collections.emptySet(); + synchronized (currentOwnIdentities) { + return new HashSet(currentOwnIdentities); } } // - // ACTIONS + // SERVICE METHODS // - /** - * Adds a context to the given own identity. - * - * @param ownIdentity - * The own identity - * @param context - * The context to add - */ - public void addContext(OwnIdentity ownIdentity, String context) { - if (ownIdentity.hasContext(context)) { - return; - } - try { - webOfTrustConnector.addContext(ownIdentity, context); - ownIdentity.addContext(context); - } catch (PluginException pe1) { - logger.log(Level.WARNING, "Could not add context " + context + " to OwnIdentity " + ownIdentity + ".", pe1); + @Override + protected void serviceRun() { + Multimap oldIdentities = create(); + + while (!shouldStop()) { + try { + Collection currentOwnIdentities = webOfTrustConnector.loadAllOwnIdentities(); + Multimap currentIdentities = loadTrustedIdentitiesForOwnIdentities(currentOwnIdentities); + + detectChangesInIdentities(currentOwnIdentities, currentIdentities, oldIdentities); + oldIdentities = currentIdentities; + + synchronized (currentOwnIdentities) { + this.currentOwnIdentities.clear(); + this.currentOwnIdentities.addAll(currentOwnIdentities); + } + } catch (WebOfTrustException wote1) { + logger.log(Level.WARNING, "WoT has disappeared!", wote1); + } + + /* wait a minute before checking again. */ + sleep(60 * 1000); } } - /** - * Removes a context from the given own identity. - * - * @param ownIdentity - * The own identity - * @param context - * The context to remove - */ - public void removeContext(OwnIdentity ownIdentity, String context) { - if (!ownIdentity.hasContext(context)) { - return; - } - try { - webOfTrustConnector.removeContext(ownIdentity, context); - ownIdentity.removeContext(context); - } catch (PluginException pe1) { - logger.log(Level.WARNING, "Could not remove context " + context + " from OwnIdentity " + ownIdentity + ".", pe1); - } + private void detectChangesInIdentities(Collection currentOwnIdentities, Multimap newIdentities, Multimap oldIdentities) { + IdentityChangeDetector identityChangeDetector = new IdentityChangeDetector(getAllOwnIdentities()); + identityChangeDetector.onNewIdentity(addNewOwnIdentityAndItsTrustedIdentities(newIdentities)); + identityChangeDetector.onRemovedIdentity(removeOwnIdentityAndItsTrustedIdentities(oldIdentities)); + identityChangeDetector.onUnchangedIdentity(detectChangesInTrustedIdentities(newIdentities, oldIdentities)); + identityChangeDetector.detectChanges(currentOwnIdentities); } - /** - * Sets the property with the given name to the given value. - * - * @param ownIdentity - * The own identity - * @param name - * The name of the property - * @param value - * The value of the property - */ - public void setProperty(OwnIdentity ownIdentity, String name, String value) { - try { - webOfTrustConnector.setProperty(ownIdentity, name, value); - ownIdentity.setProperty(name, value); - } catch (PluginException pe1) { - logger.log(Level.WARNING, "Could not set property “" + name + "” to “" + value + "” for OwnIdentity: " + ownIdentity, pe1); - } + private IdentityProcessor detectChangesInTrustedIdentities(Multimap newIdentities, Multimap oldIdentities) { + return new DefaultIdentityProcessor(oldIdentities, newIdentities); } - /** - * Removes the property with the given name. - * - * @param ownIdentity - * The own identity - * @param name - * The name of the property to remove - */ - public void removeProperty(OwnIdentity ownIdentity, String name) { - try { - webOfTrustConnector.removeProperty(ownIdentity, name); - ownIdentity.removeProperty(name); - } catch (PluginException pe1) { - logger.log(Level.WARNING, "Could not remove property “" + name + "” from OwnIdentity: " + ownIdentity, pe1); - } + private IdentityProcessor removeOwnIdentityAndItsTrustedIdentities(final Multimap oldIdentities) { + return new IdentityProcessor() { + @Override + public void processIdentity(Identity identity) { + eventBus.post(new OwnIdentityRemovedEvent((OwnIdentity) identity)); + for (Identity removedIdentity : oldIdentities.get((OwnIdentity) identity)) { + eventBus.post(new IdentityRemovedEvent((OwnIdentity) identity, removedIdentity)); + } + } + }; } - // - // SERVICE METHODS - // + private IdentityProcessor addNewOwnIdentityAndItsTrustedIdentities(final Multimap newIdentities) { + return new IdentityProcessor() { + @Override + public void processIdentity(Identity identity) { + eventBus.post(new OwnIdentityAddedEvent((OwnIdentity) identity)); + for (Identity newIdentity : newIdentities.get((OwnIdentity) identity)) { + eventBus.post(new IdentityAddedEvent((OwnIdentity) identity, newIdentity)); + } + } + }; + } - /** - * {@inheritDoc} - */ - @Override - protected void serviceRun() { - Map oldIdentities = Collections.emptyMap(); - Map oldOwnIdentities = Collections.emptyMap(); - while (!shouldStop()) { - Map currentIdentities = new HashMap(); - Map currentOwnIdentities = new HashMap(); + private Multimap loadTrustedIdentitiesForOwnIdentities(Collection ownIdentities) throws PluginException { + Multimap currentIdentities = create(); - /* get all identities with the wanted context from WoT. */ - Set ownIdentities; - try { - ownIdentities = Filters.filteredSet(webOfTrustConnector.loadAllOwnIdentities(), new Filter() { - - @Override - @SuppressWarnings("synthetic-access") - public boolean filterObject(OwnIdentity ownIdentity) { - return (context == null) || ownIdentity.hasContext(context); - } - - }); - for (OwnIdentity ownIdentity : ownIdentities) { - currentOwnIdentities.put(ownIdentity.getId(), ownIdentity); - for (Identity identity : webOfTrustConnector.loadTrustedIdentities(ownIdentity, context)) { - currentIdentities.put(identity.getId(), identity); - } - } + for (OwnIdentity ownIdentity : ownIdentities) { + if ((context != null) && !ownIdentity.hasContext(context)) { + continue; + } - /* find removed own identities: */ - for (OwnIdentity oldOwnIdentity : oldOwnIdentities.values()) { - if (!currentOwnIdentities.containsKey(oldOwnIdentity.getId())) { - identityListenerManager.fireOwnIdentityRemoved(oldOwnIdentity); - } - } + logger.finer(String.format("Getting trusted identities for %s...", ownIdentity.getId())); + Set trustedIdentities = webOfTrustConnector.loadTrustedIdentities(ownIdentity, context); + logger.finest(String.format("Got %d trusted identities.", trustedIdentities.size())); + currentIdentities.putAll(ownIdentity, trustedIdentities); + } - /* find added own identities. */ - for (OwnIdentity currentOwnIdentity : currentOwnIdentities.values()) { - if (!oldOwnIdentities.containsKey(currentOwnIdentity.getId())) { - identityListenerManager.fireOwnIdentityAdded(currentOwnIdentity); - } - } + return currentIdentities; + } - /* find removed identities. */ - for (Identity oldIdentity : oldIdentities.values()) { - if (!currentIdentities.containsKey(oldIdentity.getId())) { - identityListenerManager.fireIdentityRemoved(oldIdentity); - } - } + private class DefaultIdentityProcessor implements IdentityProcessor { - /* find new identities. */ - for (Identity currentIdentity : currentIdentities.values()) { - if (!oldIdentities.containsKey(currentIdentity.getId())) { - identityListenerManager.fireIdentityAdded(currentIdentity); - } - } + private final Multimap oldIdentities; + private final Multimap newIdentities; - /* check for changes in the properties. */ - for (Identity oldIdentity : oldIdentities.values()) { - if (!currentIdentities.containsKey(oldIdentity.getId())) { - continue; - } - Identity newIdentity = currentIdentities.get(oldIdentity.getId()); - Map oldProperties = oldIdentity.getProperties(); - Map newProperties = newIdentity.getProperties(); - if (oldProperties.size() != newProperties.size()) { - identityListenerManager.fireIdentityUpdated(newIdentity); - continue; - } - for (Entry oldProperty : oldProperties.entrySet()) { - if (!newProperties.containsKey(oldProperty.getKey()) || !newProperties.get(oldProperty.getKey()).equals(oldProperty.getValue())) { - identityListenerManager.fireIdentityUpdated(newIdentity); - break; - } - } - } + public DefaultIdentityProcessor(Multimap oldIdentities, Multimap newIdentities) { + this.oldIdentities = oldIdentities; + this.newIdentities = newIdentities; + } - /* remember the current set of identities. */ - oldIdentities = currentIdentities; - oldOwnIdentities = currentOwnIdentities; + @Override + public void processIdentity(Identity ownIdentity) { + IdentityChangeDetector identityChangeDetector = new IdentityChangeDetector(oldIdentities.get((OwnIdentity) ownIdentity)); + identityChangeDetector.onNewIdentity(notifyForAddedIdentities((OwnIdentity) ownIdentity)); + identityChangeDetector.onRemovedIdentity(notifyForRemovedIdentities((OwnIdentity) ownIdentity)); + identityChangeDetector.onChangedIdentity(notifyForChangedIdentities((OwnIdentity) ownIdentity)); + identityChangeDetector.detectChanges(newIdentities.get((OwnIdentity) ownIdentity)); + } - } catch (PluginException pe1) { - logger.log(Level.WARNING, "WoT has disappeared!", pe1); - } + private IdentityProcessor notifyForChangedIdentities(final OwnIdentity ownIdentity) { + return new IdentityProcessor() { + @Override + public void processIdentity(Identity identity) { + eventBus.post(new IdentityUpdatedEvent(ownIdentity, identity)); + } + }; + } - /* wait a minute before checking again. */ - sleep(60 * 1000); + private IdentityProcessor notifyForRemovedIdentities(final OwnIdentity ownIdentity) { + return new IdentityProcessor() { + @Override + public void processIdentity(Identity identity) { + eventBus.post(new IdentityRemovedEvent(ownIdentity, identity)); + } + }; + } + + private IdentityProcessor notifyForAddedIdentities(final OwnIdentity ownIdentity) { + return new IdentityProcessor() { + @Override + public void processIdentity(Identity identity) { + eventBus.post(new IdentityAddedEvent(ownIdentity, identity)); + } + }; } + } }