From 97cc5d173db6b98489c469af2b9e621030a86c53 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Mon, 1 Nov 2010 21:30:55 +0100 Subject: [PATCH] Add identity manager. --- .../sone/freenet/wot/IdentityListener.java | 71 +++++ .../sone/freenet/wot/IdentityListenerManager.java | 107 +++++++ .../sone/freenet/wot/IdentityManager.java | 338 +++++++++++++++++++++ 3 files changed, 516 insertions(+) create mode 100644 src/main/java/net/pterodactylus/sone/freenet/wot/IdentityListener.java create mode 100644 src/main/java/net/pterodactylus/sone/freenet/wot/IdentityListenerManager.java create mode 100644 src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManager.java diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityListener.java b/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityListener.java new file mode 100644 index 0000000..64ea61f --- /dev/null +++ b/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityListener.java @@ -0,0 +1,71 @@ +/* + * Sone - IdentityListener.java - Copyright © 2010 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 . + */ + +package net.pterodactylus.sone.freenet.wot; + +import java.util.EventListener; + +/** + * Listener interface for {@link IdentityManager} events. + * + * @author David ‘Bombe’ Roden + */ +public interface IdentityListener extends EventListener { + + /** + * Notifies a listener that an {@link OwnIdentity} that was not known on the + * previous check is available. + * + * @param ownIdentity + * The new own identity + */ + public void ownIdentityAdded(OwnIdentity ownIdentity); + + /** + * Notifies a listener that an {@link OwnIdentity} that was available during + * the last check has gone away. + * + * @param ownIdentity + * The disappeared own identity + */ + public void ownIdentityRemoved(OwnIdentity ownIdentity); + + /** + * Notifies a listener that a new identity was discovered. + * + * @param identity + * The new identity + */ + public void identityAdded(Identity identity); + + /** + * Notifies a listener that some properties of the identity have changed. + * + * @param identity + * The updated identity + */ + public void identityUpdated(Identity identity); + + /** + * Notifies a listener that an identity has gone away. + * + * @param identity + * The disappeared identity + */ + public void identityRemoved(Identity identity); + +} diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityListenerManager.java b/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityListenerManager.java new file mode 100644 index 0000000..c08fd16 --- /dev/null +++ b/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityListenerManager.java @@ -0,0 +1,107 @@ +/* + * Sone - IdentityListenerManager.java - Copyright © 2010 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 . + */ + +package net.pterodactylus.sone.freenet.wot; + +import net.pterodactylus.util.event.AbstractListenerManager; + +/** + * Manager for {@link IdentityListener}s. + * + * @author David ‘Bombe’ Roden + */ +public class IdentityListenerManager extends AbstractListenerManager { + + /** + * Creates a new identity listener manager. + */ + public IdentityListenerManager() { + super(null); + } + + // + // ACTIONS + // + + /** + * Notifies all listeners that an {@link OwnIdentity} that was not known on + * the previous check is available. + * + * @see IdentityListener#ownIdentityAdded(OwnIdentity) + * @param ownIdentity + * The new own identity + */ + public void fireOwnIdentityAdded(OwnIdentity ownIdentity) { + for (IdentityListener identityListener : getListeners()) { + identityListener.ownIdentityAdded(ownIdentity); + } + } + + /** + * Notifies all listeners that an {@link OwnIdentity} that was available + * during the last check has gone away. + * + * @see IdentityListener#ownIdentityRemoved(OwnIdentity) + * @param ownIdentity + * The disappeared own identity + */ + public void fireOwnIdentityRemoved(OwnIdentity ownIdentity) { + for (IdentityListener identityListener : getListeners()) { + identityListener.ownIdentityRemoved(ownIdentity); + } + } + + /** + * Notifies all listeners that a new identity was discovered. + * + * @see IdentityListener#identityAdded(Identity) + * @param identity + * The new identity + */ + public void fireIdentityAdded(Identity identity) { + for (IdentityListener identityListener : getListeners()) { + identityListener.identityAdded(identity); + } + } + + /** + * Notifies all listeners that some properties of the identity have changed. + * + * @see IdentityListener#identityUpdated(Identity) + * @param identity + * The updated identity + */ + public void fireIdentityUpdated(Identity identity) { + for (IdentityListener identityListener : getListeners()) { + identityListener.identityUpdated(identity); + } + } + + /** + * Notifies all listeners that an identity has gone away. + * + * @see IdentityListener#identityRemoved(Identity) + * @param identity + * The disappeared identity + */ + public void fireIdentityRemoved(Identity identity) { + for (IdentityListener identityListener : getListeners()) { + identityListener.identityRemoved(identity); + } + } + +} diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManager.java b/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManager.java new file mode 100644 index 0000000..e416cd1 --- /dev/null +++ b/src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManager.java @@ -0,0 +1,338 @@ +/* + * Sone - IdentityManager.java - Copyright © 2010 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 . + */ + +package net.pterodactylus.sone.freenet.wot; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +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.util.logging.Logging; +import net.pterodactylus.util.service.AbstractService; + +/** + * 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. + * + * @author David ‘Bombe’ Roden + */ +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 Web of Trust connector. */ + private final WebOfTrustConnector webOfTrustConnector; + + /** The context to filter for. */ + private volatile String context; + + /** Whether the Web of Trust plugin is connected. */ + private volatile boolean wotPluginConnected = false; + + /** + * Creates a new identity manager. + * + * @param webOfTrustConnector + * The Web of Trust connector + */ + public IdentityManager(WebOfTrustConnector webOfTrustConnector) { + super("Sone Identity Manager", false); + 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); + } + + // + // ACCESSORS + // + + /** + * 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 + */ + public boolean isConnected() { + return wotPluginConnected; + } + + /** + * 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 { + Set allOwnIdentities = webOfTrustConnector.loadAllOwnIdentities(); + wotPluginConnected = true; + return allOwnIdentities; + } catch (PluginException pe1) { + logger.log(Level.WARNING, "Could not load all own identities!", pe1); + wotPluginConnected = false; + return Collections.emptySet(); + } + } + + // + // ACTIONS + // + + /** + * 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); + wotPluginConnected = true; + ownIdentity.addContext(context); + } catch (PluginException pe1) { + logger.log(Level.WARNING, "Could not add context " + context + " to OwnIdentity " + ownIdentity + ".", pe1); + wotPluginConnected = false; + } + } + + /** + * 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); + wotPluginConnected = true; + ownIdentity.removeContext(context); + } catch (PluginException pe1) { + logger.log(Level.WARNING, "Could not remove context " + context + " from OwnIdentity " + ownIdentity + ".", pe1); + wotPluginConnected = false; + } + } + + /** + * 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); + wotPluginConnected = true; + ownIdentity.setProperty(name, value); + } catch (PluginException pe1) { + logger.log(Level.WARNING, "Could not set property “" + name + "” to “" + value + "” for OwnIdentity: " + ownIdentity, pe1); + wotPluginConnected = false; + } + } + + /** + * 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); + wotPluginConnected = true; + ownIdentity.removeProperty(name); + } catch (PluginException pe1) { + logger.log(Level.WARNING, "Could not remove property “" + name + "” from OwnIdentity: " + ownIdentity, pe1); + wotPluginConnected = false; + } + } + + // + // SERVICE METHODS + // + + /** + * {@inheritDoc} + */ + @Override + protected void serviceRun() { + Map oldIdentities = Collections.emptyMap(); + Map oldOwnIdentities = Collections.emptyMap(); + while (!shouldStop()) { + Map currentIdentities = new HashMap(); + Map currentOwnIdentities = new HashMap(); + + /* 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); + } + } + + /* find removed own identities: */ + for (OwnIdentity oldOwnIdentity : oldOwnIdentities.values()) { + if (!currentOwnIdentities.containsKey(oldOwnIdentity.getId())) { + identityListenerManager.fireOwnIdentityRemoved(oldOwnIdentity); + } + } + + /* find added own identities. */ + for (OwnIdentity currentOwnIdentity : currentOwnIdentities.values()) { + if (!oldOwnIdentities.containsKey(currentOwnIdentity.getId())) { + identityListenerManager.fireOwnIdentityAdded(currentOwnIdentity); + } + } + + /* find removed identities. */ + for (Identity oldIdentity : oldIdentities.values()) { + if (!currentIdentities.containsKey(oldIdentity.getId())) { + identityListenerManager.fireIdentityRemoved(oldIdentity); + } + } + + /* find new identities. */ + for (Identity currentIdentity : currentIdentities.values()) { + if (!oldIdentities.containsKey(currentIdentity.getId())) { + identityListenerManager.fireIdentityAdded(currentIdentity); + } + } + + /* 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; + } + } + } + + /* remember the current set of identities. */ + oldIdentities = currentIdentities; + oldOwnIdentities = currentOwnIdentities; + + } catch (PluginException pe1) { + logger.log(Level.WARNING, "WoT has disappeared!", pe1); + } + + /* wait a minute before checking again. */ + sleep(60 * 1000); + } + } + +} -- 2.7.4