Merge branch 'next' into wot-integration
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 30 Oct 2010 16:40:41 +0000 (18:40 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 30 Oct 2010 16:40:41 +0000 (18:40 +0200)
31 files changed:
src/main/java/net/pterodactylus/sone/core/Core.java
src/main/java/net/pterodactylus/sone/core/SoneInserter.java
src/main/java/net/pterodactylus/sone/data/Sone.java
src/main/java/net/pterodactylus/sone/freenet/wot/ConnectorListener.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/freenet/wot/ConnectorListenerManager.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/freenet/wot/Identity.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/freenet/wot/OwnIdentity.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/freenet/wot/PluginConnector.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/freenet/wot/PluginException.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/freenet/wot/WebOfTrustConnector.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/main/SonePlugin.java
src/main/java/net/pterodactylus/sone/template/IdentityAccessor.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/template/SoneAccessor.java
src/main/java/net/pterodactylus/sone/web/BlacklistPage.java [deleted file]
src/main/java/net/pterodactylus/sone/web/BlacklistSonePage.java [deleted file]
src/main/java/net/pterodactylus/sone/web/BlockSonePage.java [deleted file]
src/main/java/net/pterodactylus/sone/web/UnblacklistSonePage.java [deleted file]
src/main/java/net/pterodactylus/sone/web/UnblockSonePage.java [deleted file]
src/main/java/net/pterodactylus/sone/web/WebInterface.java
src/main/java/net/pterodactylus/sone/web/ajax/BlacklistSoneAjaxPage.java [deleted file]
src/main/java/net/pterodactylus/sone/web/ajax/BlockSoneAjaxPage.java [deleted file]
src/main/java/net/pterodactylus/sone/web/ajax/UnblacklistSoneAjaxPage.java [deleted file]
src/main/java/net/pterodactylus/sone/web/ajax/UnblockSoneAjaxPage.java [deleted file]
src/main/resources/i18n/sone.en.properties
src/main/resources/templates/blacklist.html [deleted file]
src/main/resources/templates/blacklistSone.html [deleted file]
src/main/resources/templates/blockSone.html [deleted file]
src/main/resources/templates/include/viewSone.html
src/main/resources/templates/insert/sone.xml
src/main/resources/templates/unblacklistSone.html [deleted file]
src/main/resources/templates/unblockSone.html [deleted file]

index 173f1d4..1a1c6df 100644 (file)
@@ -40,6 +40,7 @@ import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.Profile;
 import net.pterodactylus.sone.data.Reply;
 import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.freenet.wot.WebOfTrustConnector;
 import net.pterodactylus.util.config.Configuration;
 import net.pterodactylus.util.config.ConfigurationException;
 import net.pterodactylus.util.filter.Filter;
@@ -98,12 +99,12 @@ public class Core extends AbstractService {
        /** Interface to freenet. */
        private FreenetInterface freenetInterface;
 
+       /** The WoT connector. */
+       private WebOfTrustConnector webOfTrustConnector;
+
        /** The Sone downloader. */
        private SoneDownloader soneDownloader;
 
-       /** The Sone blacklist. */
-       private final Set<Sone> blacklistedSones = Collections.synchronizedSet(new HashSet<Sone>());
-
        /** The local Sones. */
        private final Set<Sone> localSones = Collections.synchronizedSet(new HashSet<Sone>());
 
@@ -171,22 +172,33 @@ public class Core extends AbstractService {
        }
 
        /**
+        * Returns the Web of Trust connector.
+        *
+        * @return The Web of Trust connector
+        */
+       public WebOfTrustConnector getWebOfTrustConnector() {
+               return webOfTrustConnector;
+       }
+
+       /**
+        * Sets the Web of Trust connector.
+        *
+        * @param webOfTrustConnector
+        *            The Web of Trust connector
+        * @return This core (for method chaining)
+        */
+       public Core setWebOfTrustConnector(WebOfTrustConnector webOfTrustConnector) {
+               this.webOfTrustConnector = webOfTrustConnector;
+               return this;
+       }
+
+       /**
         * Returns the local Sones.
         *
         * @return The local Sones
         */
        public Set<Sone> getSones() {
-               return Filters.filteredSet(localSones, new Filter<Sone>() {
-
-                       /**
-                        * {@inheritDoc}
-                        */
-                       @Override
-                       @SuppressWarnings("synthetic-access")
-                       public boolean filterObject(Sone sone) {
-                               return !blacklistedSones.contains(sone);
-                       }
-               });
+               return Collections.unmodifiableSet(localSones);
        }
 
        /**
@@ -212,17 +224,7 @@ public class Core extends AbstractService {
         * @return All known sones
         */
        public Collection<Sone> getKnownSones() {
-               return Filters.filteredCollection(soneCache.values(), new Filter<Sone>() {
-
-                       /**
-                        * {@inheritDoc}
-                        */
-                       @Override
-                       @SuppressWarnings("synthetic-access")
-                       public boolean filterObject(Sone sone) {
-                               return !blacklistedSones.contains(sone);
-                       }
-               });
+               return Collections.unmodifiableCollection(soneCache.values());
        }
 
        /**
@@ -231,34 +233,7 @@ public class Core extends AbstractService {
         * @return All remote Sones
         */
        public Collection<Sone> getRemoteSones() {
-               return Filters.filteredCollection(getKnownSones(), new Filter<Sone>() {
-
-                       @Override
-                       @SuppressWarnings("synthetic-access")
-                       public boolean filterObject(Sone sone) {
-                               return !blacklistedSones.contains(sone) && !localSones.contains(sone);
-                       }
-               });
-       }
-
-       /**
-        * Returns all blacklisted Sones.
-        *
-        * @return All blacklisted Sones
-        */
-       public Collection<Sone> getBlacklistedSones() {
-               return Collections.unmodifiableCollection(blacklistedSones);
-       }
-
-       /**
-        * Checks whether the given Sone is blacklisted.
-        *
-        * @param sone
-        *            The Sone to check
-        * @return {@code true} if this Sone is blacklisted, {@code false} otherwise
-        */
-       public boolean isBlacklistedSone(Sone sone) {
-               return blacklistedSones.contains(sone);
+               return Collections.unmodifiableCollection(getKnownSones());
        }
 
        /**
@@ -382,38 +357,6 @@ public class Core extends AbstractService {
        }
 
        /**
-        * Blackslists the given Sone.
-        *
-        * @param sone
-        *            The Sone to blacklist
-        */
-       public void blacklistSone(Sone sone) {
-               if (blacklistedSones.add(sone)) {
-                       soneDownloader.removeSone(sone);
-                       if (localSones.remove(sone)) {
-                               SoneInserter soneInserter = soneInserters.remove(sone);
-                               soneInserter.stop();
-                       }
-               }
-       }
-
-       /**
-        * Unblacklists the given Sone.
-        *
-        * @param sone
-        *            The Sone to unblacklist
-        */
-       public void unblacklistSone(Sone sone) {
-               if (blacklistedSones.remove(sone)) {
-                       if (sone.getInsertUri() != null) {
-                               addLocalSone(sone);
-                       } else {
-                               addSone(sone);
-                       }
-               }
-       }
-
-       /**
         * Creates a new Sone at a random location.
         *
         * @param name
@@ -846,17 +789,6 @@ public class Core extends AbstractService {
                                        sone.addFriend(friendSone);
                                }
 
-                               /* load blocked Sone IDs. */
-                               int blockedSoneCounter = 0;
-                               while (true) {
-                                       String blockedSonePrefix = sonePrefix + "/BlockedSone." + blockedSoneCounter++;
-                                       String blockedSoneId = configuration.getStringValue(blockedSonePrefix + "/ID").getValue(null);
-                                       if (blockedSoneId == null) {
-                                               break;
-                                       }
-                                       sone.addBlockedSoneId(blockedSoneId);
-                               }
-
                                /* load liked post IDs. */
                                int likedPostIdCounter = 0;
                                while (true) {
@@ -887,41 +819,6 @@ public class Core extends AbstractService {
                } while (true);
                logger.log(Level.INFO, "Loaded %d Sones.", getSones().size());
 
-               /* load all known Sones. */
-               int knownSonesCounter = 0;
-               while (true) {
-                       String knownSonePrefix = "KnownSone." + knownSonesCounter++;
-                       String knownSoneId = configuration.getStringValue(knownSonePrefix + "/ID").getValue(null);
-                       if (knownSoneId == null) {
-                               break;
-                       }
-                       String knownSoneName = configuration.getStringValue(knownSonePrefix + "/Name").getValue(null);
-                       String knownSoneKey = configuration.getStringValue(knownSonePrefix + "/Key").getValue(null);
-                       try {
-                               getSone(knownSoneId).setName(knownSoneName).setRequestUri(new FreenetURI(knownSoneKey));
-                       } catch (MalformedURLException mue1) {
-                               logger.log(Level.WARNING, "Could not create Sone from requestUri (“" + knownSoneKey + "”)!", mue1);
-                       }
-               }
-
-               /* load all blacklisted Sones. */
-               int blacklistedSonesCounter = 0;
-               while (true) {
-                       String blacklistedSonePrefix = "BlacklistedSone." + blacklistedSonesCounter++;
-                       String blacklistedSoneId = configuration.getStringValue(blacklistedSonePrefix + "/ID").getValue(null);
-                       if (blacklistedSoneId == null) {
-                               break;
-                       }
-                       String blacklistedSoneName = configuration.getStringValue(blacklistedSonePrefix + "/Name").getValue(null);
-                       String blacklistedSoneKey = configuration.getStringValue(blacklistedSonePrefix + "/Key").getValue(null);
-                       String blacklistedSoneInsertKey = configuration.getStringValue(blacklistedSonePrefix + "/InsertKey").getValue(null);
-                       try {
-                               blacklistSone(getSone(blacklistedSoneId).setName(blacklistedSoneName).setRequestUri(new FreenetURI(blacklistedSoneKey)).setInsertUri((blacklistedSoneInsertKey != null) ? new FreenetURI(blacklistedSoneInsertKey) : null));
-                       } catch (MalformedURLException mue1) {
-                               logger.log(Level.WARNING, "Could not create blacklisted Sone from requestUri (“" + blacklistedSoneKey + "”)!", mue1);
-                       }
-               }
-
                /* load all remote Sones. */
                for (Sone remoteSone : getRemoteSones()) {
                        loadSone(remoteSone);
@@ -991,14 +888,6 @@ public class Core extends AbstractService {
                                /* write null ID as terminator. */
                                configuration.getStringValue(sonePrefix + "/Friend." + friendId + "/ID").setValue(null);
 
-                               /* write all blocked Sones. */
-                               int blockedSoneCounter = 0;
-                               for (String blockedSoneId : sone.getBlockedSoneIds()) {
-                                       String blockedSonePrefix = sonePrefix + "/BlockedSone." + blockedSoneCounter++;
-                                       configuration.getStringValue(blockedSonePrefix + "/ID").setValue(blockedSoneId);
-                               }
-                               configuration.getStringValue(sonePrefix + "/BlockedSone." + blockedSoneCounter + "/ID").setValue(null);
-
                                /* write all liked posts. */
                                int likedPostIdCounter = 0;
                                for (String soneLikedPostId : sone.getLikedPostIds()) {
@@ -1019,29 +908,6 @@ public class Core extends AbstractService {
                        /* write null ID as terminator. */
                        configuration.getStringValue("Sone/Sone." + soneId + "/ID").setValue(null);
 
-                       /* write all known Sones. */
-                       int knownSonesCounter = 0;
-                       for (Sone knownSone : getRemoteSones()) {
-                               String knownSonePrefix = "KnownSone." + knownSonesCounter++;
-                               configuration.getStringValue(knownSonePrefix + "/ID").setValue(knownSone.getId());
-                               configuration.getStringValue(knownSonePrefix + "/Name").setValue(knownSone.getName());
-                               configuration.getStringValue(knownSonePrefix + "/Key").setValue(knownSone.getRequestUri().toString());
-                               /* TODO - store all known stuff? */
-                       }
-                       configuration.getStringValue("KnownSone." + knownSonesCounter + "/ID").setValue(null);
-
-                       /* write all blacklisted Sones. */
-                       int blacklistedSonesCounter = 0;
-                       for (Sone blacklistedSone : getBlacklistedSones()) {
-                               String blacklistedSonePrefix = "BlacklistedSone." + blacklistedSonesCounter++;
-                               configuration.getStringValue(blacklistedSonePrefix + "/ID").setValue(blacklistedSone.getId());
-                               configuration.getStringValue(blacklistedSonePrefix + "/Name").setValue(blacklistedSone.getName());
-                               configuration.getStringValue(blacklistedSonePrefix + "/Key").setValue(blacklistedSone.getRequestUri().toString());
-                               configuration.getStringValue(blacklistedSonePrefix + "/InsertKey").setValue((blacklistedSone.getInsertUri() != null) ? blacklistedSone.getInsertUri().toString() : null);
-                               /* TODO - store all known stuff? */
-                       }
-                       configuration.getStringValue("BlacklistedSone." + blacklistedSonesCounter + "/ID").setValue(null);
-
                } catch (ConfigurationException ce1) {
                        logger.log(Level.WARNING, "Could not store configuration!", ce1);
                }
index 05e3600..1136973 100644 (file)
@@ -25,7 +25,6 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
-import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -201,7 +200,6 @@ public class SoneInserter extends AbstractService {
                        soneProperties.put("profile", sone.getProfile());
                        soneProperties.put("posts", new ArrayList<Post>(sone.getPosts()));
                        soneProperties.put("replies", new HashSet<Reply>(sone.getReplies()));
-                       soneProperties.put("blockedSoneIds", new HashSet<String>(sone.getBlockedSoneIds()));
                        soneProperties.put("likedPostIds", new HashSet<String>(sone.getLikedPostIds()));
                        soneProperties.put("likeReplyIds", new HashSet<String>(sone.getLikedReplyIds()));
                }
@@ -267,8 +265,6 @@ public class SoneInserter extends AbstractService {
                        } finally {
                                Closer.close(templateInputStreamReader);
                        }
-                       @SuppressWarnings("unchecked")
-                       final Set<String> blockedSoneIds = (Set<String>) soneProperties.get("blockedSoneIds");
                        Collection<Sone> knownSones = Filters.filteredCollection(core.getKnownSones(), new Filter<Sone>() {
 
                                /**
@@ -276,7 +272,7 @@ public class SoneInserter extends AbstractService {
                                 */
                                @Override
                                public boolean filterObject(Sone object) {
-                                       return !blockedSoneIds.contains(object.getId()) && !object.getId().equals(soneProperties.get("id"));
+                                       return !object.getId().equals(soneProperties.get("id"));
                                }
                        });
 
index 5613828..5c0e486 100644 (file)
@@ -72,9 +72,6 @@ public class Sone {
        /** All replies. */
        private final Set<Reply> replies = Collections.synchronizedSet(new HashSet<Reply>());
 
-       /** The IDs of all blocked Sones. */
-       private final Set<String> blockedSoneIds = Collections.synchronizedSet(new HashSet<String>());
-
        /** The IDs of all liked posts. */
        private final Set<String> likedPostIds = Collections.synchronizedSet(new HashSet<String>());
 
@@ -419,52 +416,6 @@ public class Sone {
        }
 
        /**
-        * Returns the IDs of all blocked Sones. These Sones will not propagated
-        * using the “known Sones” mechanism.
-        *
-        * @return The IDs of all blocked Sones
-        */
-       public Set<String> getBlockedSoneIds() {
-               return Collections.unmodifiableSet(blockedSoneIds);
-       }
-
-       /**
-        * Returns whether the given Sone ID is blocked.
-        *
-        * @param soneId
-        *            The Sone ID to check
-        * @return {@code true} if the given Sone ID is blocked, {@code false}
-        *         otherwise
-        */
-       public boolean isSoneBlocked(String soneId) {
-               return blockedSoneIds.contains(soneId);
-       }
-
-       /**
-        * Adds the given ID to the list of blocked IDs.
-        *
-        * @param soneId
-        *            The Sone ID to block
-        */
-       public synchronized void addBlockedSoneId(String soneId) {
-               if (blockedSoneIds.add(soneId)) {
-                       modificationCounter++;
-               }
-       }
-
-       /**
-        * Removes the given ID from the list of blocked IDs.
-        *
-        * @param soneId
-        *            The Sone ID to unblock
-        */
-       public synchronized void removeBlockedSoneId(String soneId) {
-               if (blockedSoneIds.remove(soneId)) {
-                       modificationCounter++;
-               }
-       }
-
-       /**
         * Returns the IDs of all liked posts.
         *
         * @return All liked posts’ IDs
diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/ConnectorListener.java b/src/main/java/net/pterodactylus/sone/freenet/wot/ConnectorListener.java
new file mode 100644 (file)
index 0000000..cf1d1e3
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Sone - ConnectorListener.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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.freenet.wot;
+
+import java.util.EventListener;
+
+import freenet.support.SimpleFieldSet;
+import freenet.support.api.Bucket;
+
+/**
+ * Interface for objects that want to be notified if a {@link PluginConnector}
+ * receives a reply from a plugin. As a connection listener is always
+ * {@link PluginConnector#addConnectorListener(String, String, ConnectorListener)
+ * added} for a specific plugin, it will always be notified for replies from the
+ * correct plugin (unless you register the same listener for multiple
+ * plugins—which you subsequently should not do).
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface ConnectorListener extends EventListener {
+
+       /**
+        * A reply was received from the plugin this connection listener was added
+        * for.
+        *
+        * @param pluginConnector
+        *            The plugin connector that received the reply
+        * @param fields
+        *            The fields of the reply
+        * @param data
+        *            The data of the reply (may be null)
+        */
+       public void receivedReply(PluginConnector pluginConnector, SimpleFieldSet fields, Bucket data);
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/ConnectorListenerManager.java b/src/main/java/net/pterodactylus/sone/freenet/wot/ConnectorListenerManager.java
new file mode 100644 (file)
index 0000000..3962eef
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Sone - ConnectorListenerManager.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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.freenet.wot;
+
+import net.pterodactylus.util.event.AbstractListenerManager;
+import freenet.support.SimpleFieldSet;
+import freenet.support.api.Bucket;
+
+/**
+ * Manages {@link ConnectorListener}s and fire events.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ConnectorListenerManager extends AbstractListenerManager<PluginConnector, ConnectorListener> {
+
+       /**
+        * Creates a new manager for {@link ConnectorListener}s.
+        *
+        * @param pluginConnector
+        *            The plugin connector that is the source for all events
+        */
+       public ConnectorListenerManager(PluginConnector pluginConnector) {
+               super(pluginConnector);
+       }
+
+       //
+       // ACTIONS
+       //
+
+       /**
+        * Notifies all registered listeners that a reply from the plugin was
+        * received.
+        *
+        * @param fields
+        *            The fields of the reply
+        * @param data
+        *            The data of the reply (may be null)
+        */
+       public void fireReceivedReply(SimpleFieldSet fields, Bucket data) {
+               for (ConnectorListener connectorListener : getListeners()) {
+                       connectorListener.receivedReply(getSource(), fields, data);
+               }
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/Identity.java b/src/main/java/net/pterodactylus/sone/freenet/wot/Identity.java
new file mode 100644 (file)
index 0000000..d4288ea
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Sone - Identity.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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.freenet.wot;
+
+import java.util.Set;
+
+/**
+ * A Web of Trust identity.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class Identity {
+
+       /** The Web of Trust connector. */
+       protected final WebOfTrustConnector webOfTrustConnector;
+
+       /** The ID of the identity. */
+       private final String id;
+
+       /** The nickname of the identity. */
+       private final String nickname;
+
+       /** The request URI of the identity. */
+       private final String requestUri;
+
+       /**
+        * Creates a new identity.
+        *
+        * @param webOfTrustConnector
+        *            The Web of Trust connector
+        * @param id
+        *            The ID of the identity
+        * @param nickname
+        *            The nickname of the identity
+        * @param requestUri
+        *            The request URI of the identity
+        */
+       public Identity(WebOfTrustConnector webOfTrustConnector, String id, String nickname, String requestUri) {
+               this.webOfTrustConnector = webOfTrustConnector;
+               this.id = id;
+               this.nickname = nickname;
+               this.requestUri = requestUri;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the ID of the identity.
+        *
+        * @return The ID of the identity
+        */
+       public String getId() {
+               return id;
+       }
+
+       /**
+        * Returns the nickname of the identity.
+        *
+        * @return The nickname of the identity
+        */
+       public String getNickname() {
+               return nickname;
+       }
+
+       /**
+        * Returns the request URI of the identity.
+        *
+        * @return The request URI of the identity
+        */
+       public String getRequestUri() {
+               return requestUri;
+       }
+
+       /**
+        * Returns the contexts of the identity. If the contexts have not been
+        * loaded yet, they will be loaded. If loading the contexts fails, an empty
+        * set is returned.
+        *
+        * @return The contexts of the identity
+        * @throws PluginException
+        *             if an error occured communicating with the Web of Trust
+        *             plugin
+        */
+       public Set<String> getContexts() throws PluginException {
+               return webOfTrustConnector.loadIdentityContexts(this);
+       }
+
+       /**
+        * Returns whether the identity contains the given context.
+        *
+        * @param context
+        *            The context to check for
+        * @return {@code true} if this identity has the given context,
+        *         {@code false} otherwise
+        * @throws PluginException
+        *             if an error occured communicating with the Web of Trust
+        *             plugin
+        */
+       public boolean hasContext(String context) throws PluginException {
+               return getContexts().contains(context);
+       }
+
+       /**
+        * Returns the value of the property with the given name.
+        *
+        * @param name
+        *            The name of the property
+        * @return The value of the property, or {@code null} if there is no such
+        *         property
+        * @throws PluginException
+        *             if an error occured communicating with the Web of Trust
+        *             plugin
+        */
+       public String getProperty(String name) throws PluginException {
+               return webOfTrustConnector.getProperty(this, name);
+       }
+
+       //
+       // OBJECT METHODS
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public int hashCode() {
+               return id.hashCode();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public boolean equals(Object object) {
+               if (!(object instanceof Identity)) {
+                       return false;
+               }
+               Identity identity = (Identity) object;
+               return identity.id.equals(id);
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/OwnIdentity.java b/src/main/java/net/pterodactylus/sone/freenet/wot/OwnIdentity.java
new file mode 100644 (file)
index 0000000..3716229
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Sone - OwnIdentity.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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.freenet.wot;
+
+/**
+ * An own identity is an identity that the owner of the node has full control
+ * over.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class OwnIdentity extends Identity {
+
+       /** The insert URI of the identity. */
+       private final String insertUri;
+
+       /**
+        * Creates a new own identity.
+        *
+        * @param webOfTrustConnector
+        *            The Web of Trust connector
+        * @param id
+        *            The ID of the identity
+        * @param nickname
+        *            The nickname of the identity
+        * @param requestUri
+        *            The request URI of the identity
+        * @param insertUri
+        *            The insert URI of the identity
+        */
+       public OwnIdentity(WebOfTrustConnector webOfTrustConnector, String id, String nickname, String requestUri, String insertUri) {
+               super(webOfTrustConnector, id, nickname, requestUri);
+               this.insertUri = insertUri;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the insert URI of the identity.
+        *
+        * @return The insert URI of the identity
+        */
+       public String getInsertUri() {
+               return insertUri;
+       }
+
+       /**
+        * Adds the given context to this identity.
+        *
+        * @param context
+        *            The context to add
+        * @throws PluginException
+        *             if an error occured communicating with the Web of Trust
+        *             plugin
+        */
+       public void addContext(String context) throws PluginException {
+               webOfTrustConnector.addContext(this, context);
+       }
+
+       /**
+        * Removes the given context from this identity.
+        *
+        * @param context
+        *            The context to remove
+        * @throws PluginException
+        *             if an error occured communicating with the Web of Trust
+        *             plugin
+        */
+       public void removeContext(String context) throws PluginException {
+               webOfTrustConnector.removeContext(this, context);
+       }
+
+       /**
+        * Sets the property with the given name to the given value.
+        *
+        * @param name
+        *            The name of the property to set
+        * @param value
+        *            The new value of the property
+        * @throws PluginException
+        *             if an error occured communicating with the Web of Trust
+        *             plugin
+        */
+       public void setProperty(String name, String value) throws PluginException {
+               webOfTrustConnector.setProperty(this, name, value);
+       }
+
+       /**
+        * Removes the property with the given name.
+        *
+        * @param name
+        *            The name of the property to remove
+        * @throws PluginException
+        *             if an error occured communicating with the Web of Trust
+        *             plugin
+        */
+       public void removeProperty(String name) throws PluginException {
+               webOfTrustConnector.removeProperty(this, name);
+       }
+
+       //
+       // OBJECT METHODS
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public String toString() {
+               return getClass().getSimpleName() + "[id=" + getId() + ",nickname=" + getNickname() + ",requestUri=" + getRequestUri() + ",insertUri=" + insertUri + "]";
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/PluginConnector.java b/src/main/java/net/pterodactylus/sone/freenet/wot/PluginConnector.java
new file mode 100644 (file)
index 0000000..561f092
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Sone - PluginConnector.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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.freenet.wot;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.pterodactylus.util.collection.Pair;
+import freenet.pluginmanager.FredPluginTalker;
+import freenet.pluginmanager.PluginNotFoundException;
+import freenet.pluginmanager.PluginRespirator;
+import freenet.pluginmanager.PluginTalker;
+import freenet.support.SimpleFieldSet;
+import freenet.support.api.Bucket;
+
+/**
+ * Interface for talking to other plugins. Other plugins are identified by their
+ * name and a unique connection identifier.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class PluginConnector implements FredPluginTalker {
+
+       /** The plugin respirator. */
+       private final PluginRespirator pluginRespirator;
+
+       /** Connector listener managers for all plugin connections. */
+       private final Map<Pair<String, String>, ConnectorListenerManager> connectorListenerManagers = Collections.synchronizedMap(new HashMap<Pair<String, String>, ConnectorListenerManager>());
+
+       /**
+        * Creates a new plugin connector.
+        *
+        * @param pluginRespirator
+        *            The plugin respirator
+        */
+       public PluginConnector(PluginRespirator pluginRespirator) {
+               this.pluginRespirator = pluginRespirator;
+       }
+
+       //
+       // LISTENER MANAGEMENT
+       //
+
+       /**
+        * Adds a connection listener for the given plugin connection.
+        *
+        * @param pluginName
+        *            The name of the plugin
+        * @param identifier
+        *            The identifier of the connection
+        * @param connectorListener
+        *            The listener to add
+        */
+       public void addConnectorListener(String pluginName, String identifier, ConnectorListener connectorListener) {
+               getConnectorListenerManager(pluginName, identifier).addListener(connectorListener);
+       }
+
+       /**
+        * Removes a connection listener for the given plugin connection.
+        *
+        * @param pluginName
+        *            The name of the plugin
+        * @param identifier
+        *            The identifier of the connection
+        * @param connectorListener
+        *            The listener to remove
+        */
+       public void removeConnectorListener(String pluginName, String identifier, ConnectorListener connectorListener) {
+               getConnectorListenerManager(pluginName, identifier).removeListener(connectorListener);
+       }
+
+       //
+       // ACTIONS
+       //
+
+       /**
+        * Sends a request to the given plugin.
+        *
+        * @param pluginName
+        *            The name of the plugin
+        * @param identifier
+        *            The identifier of the connection
+        * @param fields
+        *            The fields of the message
+        * @throws PluginException
+        *             if the plugin can not be found
+        */
+       public void sendRequest(String pluginName, String identifier, SimpleFieldSet fields) throws PluginException {
+               sendRequest(pluginName, identifier, fields, null);
+       }
+
+       /**
+        * Sends a request to the given plugin.
+        *
+        * @param pluginName
+        *            The name of the plugin
+        * @param identifier
+        *            The identifier of the connection
+        * @param fields
+        *            The fields of the message
+        * @param data
+        *            The payload of the message (may be null)
+        * @throws PluginException
+        *             if the plugin can not be found
+        */
+       public void sendRequest(String pluginName, String identifier, SimpleFieldSet fields, Bucket data) throws PluginException {
+               getPluginTalker(pluginName, identifier).send(fields, data);
+       }
+
+       //
+       // PRIVATE METHODS
+       //
+
+       /**
+        * Returns the connection listener manager for the given plugin connection,
+        * creating a new one if none does exist yet.
+        *
+        * @param pluginName
+        *            The name of the plugin
+        * @param identifier
+        *            The identifier of the connection
+        * @return The connection listener manager
+        */
+       private ConnectorListenerManager getConnectorListenerManager(String pluginName, String identifier) {
+               return getConnectorListenerManager(pluginName, identifier, true);
+       }
+
+       /**
+        * Returns the connection listener manager for the given plugin connection,
+        * optionally creating a new one if none does exist yet.
+        *
+        * @param pluginName
+        *            The name of the plugin
+        * @param identifier
+        *            The identifier of the connection
+        * @param create
+        *            {@code true} to create a new manager if there is none,
+        *            {@code false} to return {@code null} in that case
+        * @return The connection listener manager, or {@code null} if none existed
+        *         and {@code create} is {@code false}
+        */
+       private ConnectorListenerManager getConnectorListenerManager(String pluginName, String identifier, boolean create) {
+               ConnectorListenerManager connectorListenerManager = connectorListenerManagers.get(new Pair<String, String>(pluginName, identifier));
+               if (create && (connectorListenerManager == null)) {
+                       connectorListenerManager = new ConnectorListenerManager(this);
+                       connectorListenerManagers.put(new Pair<String, String>(pluginName, identifier), connectorListenerManager);
+               }
+               return connectorListenerManager;
+       }
+
+       /**
+        * Returns the plugin talker for the given plugin connection.
+        *
+        * @param pluginName
+        *            The name of the plugin
+        * @param identifier
+        *            The identifier of the connection
+        * @return The plugin talker
+        * @throws PluginException
+        *             if the plugin can not be found
+        */
+       private PluginTalker getPluginTalker(String pluginName, String identifier) throws PluginException {
+               try {
+                       return pluginRespirator.getPluginTalker(this, pluginName, identifier);
+               } catch (PluginNotFoundException pnfe1) {
+                       throw new PluginException(pnfe1);
+               }
+       }
+
+       //
+       // INTERFACE FredPluginTalker
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public void onReply(String pluginName, String identifier, SimpleFieldSet params, Bucket data) {
+               ConnectorListenerManager connectorListenerManager = getConnectorListenerManager(pluginName, identifier, false);
+               if (connectorListenerManager == null) {
+                       /* we don’t care about events for this plugin. */
+                       return;
+               }
+               connectorListenerManager.fireReceivedReply(params, data);
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/PluginException.java b/src/main/java/net/pterodactylus/sone/freenet/wot/PluginException.java
new file mode 100644 (file)
index 0000000..36cf49a
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Sone - PluginException.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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.freenet.wot;
+
+/**
+ * Exception that signals an error when communicating with a plugin.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class PluginException extends Exception {
+
+       /**
+        * Creates a new plugin exception.
+        */
+       public PluginException() {
+               super();
+       }
+
+       /**
+        * Creates a new plugin exception.
+        *
+        * @param message
+        *            The message of the exception
+        */
+       public PluginException(String message) {
+               super(message);
+       }
+
+       /**
+        * Creates a new plugin exception.
+        *
+        * @param cause
+        *            The cause of the exception
+        */
+       public PluginException(Throwable cause) {
+               super(cause);
+       }
+
+       /**
+        * Creates a new plugin exception.
+        *
+        * @param message
+        *            The message of the exception
+        * @param cause
+        *            The cause of the exception
+        */
+       public PluginException(String message, Throwable cause) {
+               super(message, cause);
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/freenet/wot/WebOfTrustConnector.java b/src/main/java/net/pterodactylus/sone/freenet/wot/WebOfTrustConnector.java
new file mode 100644 (file)
index 0000000..fd42ce6
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * Sone - WebOfTrustConnector.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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.freenet.wot;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.pterodactylus.util.logging.Logging;
+import freenet.support.SimpleFieldSet;
+import freenet.support.api.Bucket;
+
+/**
+ * Connector for the Web of Trust plugin.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class WebOfTrustConnector implements ConnectorListener {
+
+       /** The logger. */
+       private static final Logger logger = Logging.getLogger(WebOfTrustConnector.class);
+
+       /** The name of the WoT plugin. */
+       private static final String WOT_PLUGIN_NAME = "plugins.WoT.WoT";
+
+       /** A random connection identifier. */
+       private static final String PLUGIN_CONNECTION_IDENTIFIER = "Sone-WoT-Connector-" + Math.abs(Math.random());
+
+       /** The current replies that we wait for. */
+       private final Map<String, Reply> replies = Collections.synchronizedMap(new HashMap<String, Reply>());
+
+       /** The plugin connector. */
+       private final PluginConnector pluginConnector;
+
+       /**
+        * Creates a new Web of Trust connector that uses the given plugin
+        * connector.
+        *
+        * @param pluginConnector
+        *            The plugin connector
+        */
+       public WebOfTrustConnector(PluginConnector pluginConnector) {
+               this.pluginConnector = pluginConnector;
+               pluginConnector.addConnectorListener(WOT_PLUGIN_NAME, PLUGIN_CONNECTION_IDENTIFIER, this);
+       }
+
+       //
+       // ACTIONS
+       //
+
+       /**
+        * Loads all own identities from the Web of Trust plugin.
+        *
+        * @return All own identity
+        * @throws PluginException
+        *             if the own identities can not be loaded
+        */
+       public Set<OwnIdentity> loadAllOwnIdentities() throws PluginException {
+               Reply reply = performRequest(SimpleFieldSetConstructor.create().put("Message", "GetOwnIdentities").get(), "OwnIdentities");
+               SimpleFieldSet fields = reply.getFields();
+               int ownIdentityCounter = -1;
+               Set<OwnIdentity> ownIdentities = new HashSet<OwnIdentity>();
+               while (true) {
+                       String id = fields.get("Identity" + ++ownIdentityCounter);
+                       if (id == null) {
+                               break;
+                       }
+                       String requestUri = fields.get("RequestURI" + ownIdentityCounter);
+                       String insertUri = fields.get("InsertURI" + ownIdentityCounter);
+                       String nickname = fields.get("Nickname" + ownIdentityCounter);
+                       OwnIdentity ownIdentity = new OwnIdentity(this, id, nickname, requestUri, insertUri);
+                       ownIdentities.add(ownIdentity);
+               }
+               return ownIdentities;
+       }
+
+       /**
+        * Loads the contexts of the given identity.
+        *
+        * @param identity
+        *            The identity to load the contexts for
+        * @return The contexts of the identity
+        * @throws PluginException
+        *             if an error occured talking to the Web of Trust plugin
+        */
+       public Set<String> loadIdentityContexts(Identity identity) throws PluginException {
+               Reply reply = performRequest(SimpleFieldSetConstructor.create().put("Message", "GetIdentity").put("TreeOwner", identity.getId()).put("Identity", identity.getId()).get(), "Identity");
+               SimpleFieldSet fields = reply.getFields();
+               int contextCounter = -1;
+               Set<String> contexts = new HashSet<String>();
+               while (true) {
+                       String context = fields.get("Context" + ++contextCounter);
+                       if (context == null) {
+                               break;
+                       }
+                       contexts.add(context);
+               }
+               return contexts;
+       }
+
+       /**
+        * Loads all identities that the given identities trusts with a score of
+        * more than 0.
+        *
+        * @param ownIdentity
+        *            The own identity
+        * @return All trusted identities
+        * @throws PluginException
+        *             if an error occured talking to the Web of Trust plugin
+        */
+       public Set<Identity> loadTrustedIdentities(OwnIdentity ownIdentity) throws PluginException {
+               return loadTrustedIdentities(ownIdentity, null);
+       }
+
+       /**
+        * Loads all identities that the given identities trusts with a score of
+        * more than 0 and the (optional) given context.
+        *
+        * @param ownIdentity
+        *            The own identity
+        * @param context
+        *            The context to filter, or {@code null}
+        * @return All trusted identities
+        * @throws PluginException
+        *             if an error occured talking to the Web of Trust plugin
+        */
+       public Set<Identity> loadTrustedIdentities(OwnIdentity ownIdentity, String context) throws PluginException {
+               Reply reply = performRequest(SimpleFieldSetConstructor.create().put("Message", "GetIdentitiesByScore").put("TreeOwner", ownIdentity.getId()).put("Selection", "+").put("Context", (context == null) ? "" : context).get(), "Identities");
+               SimpleFieldSet fields = reply.getFields();
+               Set<Identity> identities = new HashSet<Identity>();
+               int identityCounter = -1;
+               while (true) {
+                       String id = fields.get("Identity" + ++identityCounter);
+                       if (id == null) {
+                               break;
+                       }
+                       String nickname = fields.get("Nickname" + identityCounter);
+                       String requestUri = fields.get("RequestURI" + identityCounter);
+                       identities.add(new Identity(this, id, nickname, requestUri));
+               }
+               return identities;
+       }
+
+       /**
+        * Adds the given context to the given identity.
+        *
+        * @param ownIdentity
+        *            The identity to add the context to
+        * @param context
+        *            The context to add
+        * @throws PluginException
+        *             if an error occured talking to the Web of Trust plugin
+        */
+       public void addContext(OwnIdentity ownIdentity, String context) throws PluginException {
+               performRequest(SimpleFieldSetConstructor.create().put("Message", "AddContext").put("Identity", ownIdentity.getId()).put("Context", context).get(), "ContextAdded");
+       }
+
+       /**
+        * Removes the given context from the given identity.
+        *
+        * @param ownIdentity
+        *            The identity to remove the context from
+        * @param context
+        *            The context to remove
+        * @throws PluginException
+        *             if an error occured talking to the Web of Trust plugin
+        */
+       public void removeContext(OwnIdentity ownIdentity, String context) throws PluginException {
+               performRequest(SimpleFieldSetConstructor.create().put("Message", "RemoveContext").put("Identity", ownIdentity.getId()).put("Context", context).get(), "ContextRemoved");
+       }
+
+       /**
+        * Returns the value of the property with the given name.
+        *
+        * @param identity
+        *            The identity whose properties to check
+        * @param name
+        *            The name of the property to return
+        * @return The value of the property, or {@code null} if there is no value
+        * @throws PluginException
+        *             if an error occured talking to the Web of Trust plugin
+        */
+       public String getProperty(Identity identity, String name) throws PluginException {
+               Reply reply = performRequest(SimpleFieldSetConstructor.create().put("Message", "GetProperty").put("Identity", identity.getId()).put("Property", name).get(), "PropertyValue", "Error");
+               return reply.getFields().get("Property");
+       }
+
+       /**
+        * Sets the property with the given name to the given value.
+        *
+        * @param ownIdentity
+        *            The identity to set the property on
+        * @param name
+        *            The name of the property to set
+        * @param value
+        *            The value to set
+        * @throws PluginException
+        *             if an error occured talking to the Web of Trust plugin
+        */
+       public void setProperty(OwnIdentity ownIdentity, String name, String value) throws PluginException {
+               performRequest(SimpleFieldSetConstructor.create().put("Message", "SetProperty").put("Identity", ownIdentity.getId()).put("Property", name).put("Value", value).get(), "PropertyAdded");
+       }
+
+       /**
+        * Removes the property with the given name.
+        *
+        * @param ownIdentity
+        *            The identity to remove the property from
+        * @param name
+        *            The name of the property to remove
+        * @throws PluginException
+        *             if an error occured talking to the Web of Trust plugin
+        */
+       public void removeProperty(OwnIdentity ownIdentity, String name) throws PluginException {
+               performRequest(SimpleFieldSetConstructor.create().put("Message", "RemoveProperty").put("Identity", ownIdentity.getId()).put("Property", name).get(), "PropertyRemoved");
+       }
+
+       //
+       // PRIVATE ACTIONS
+       //
+
+       /**
+        * Sends a request containing the given fields and waits for the target
+        * message.
+        *
+        * @param fields
+        *            The fields of the message
+        * @param targetMessages
+        *            The messages of the reply to wait for
+        * @return The reply message
+        * @throws PluginException
+        *             if the request could not be sent
+        */
+       private Reply performRequest(SimpleFieldSet fields, String... targetMessages) throws PluginException {
+               return performRequest(fields, null, targetMessages);
+       }
+
+       /**
+        * Sends a request containing the given fields and waits for the target
+        * message.
+        *
+        * @param fields
+        *            The fields of the message
+        * @param data
+        *            The payload of the message
+        * @param targetMessages
+        *            The messages of the reply to wait for
+        * @return The reply message
+        * @throws PluginException
+        *             if the request could not be sent
+        */
+       private Reply performRequest(SimpleFieldSet fields, Bucket data, String... targetMessages) throws PluginException {
+               @SuppressWarnings("synthetic-access")
+               Reply reply = new Reply();
+               for (String targetMessage : targetMessages) {
+                       replies.put(targetMessage, reply);
+               }
+               synchronized (reply) {
+                       pluginConnector.sendRequest(WOT_PLUGIN_NAME, PLUGIN_CONNECTION_IDENTIFIER, fields, data);
+                       try {
+                               reply.wait(60000);
+                       } catch (InterruptedException ie1) {
+                               logger.log(Level.WARNING, "Got interrupted while waiting for reply on GetOwnIdentities.", ie1);
+                       }
+               }
+               for (String targetMessage : targetMessages) {
+                       replies.remove(targetMessage);
+               }
+               return reply;
+       }
+
+       //
+       // INTERFACE ConnectorListener
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public void receivedReply(PluginConnector pluginConnector, SimpleFieldSet fields, Bucket data) {
+               String messageName = fields.get("Message");
+               Reply reply = replies.remove(messageName);
+               if (reply == null) {
+                       logger.log(Level.FINE, "Not waiting for a “%s” message.", messageName);
+                       return;
+               }
+               synchronized (reply) {
+                       reply.setFields(fields);
+                       reply.setData(data);
+                       reply.notify();
+               }
+       }
+
+       /**
+        * Container for the data of the reply from a plugin.
+        *
+        * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+        */
+       private static class Reply {
+
+               /** The fields of the reply. */
+               private SimpleFieldSet fields;
+
+               /** The payload of the reply. */
+               private Bucket data;
+
+               /**
+                * Returns the fields of the reply.
+                *
+                * @return The fields of the reply
+                */
+               public SimpleFieldSet getFields() {
+                       return fields;
+               }
+
+               /**
+                * Sets the fields of the reply.
+                *
+                * @param fields
+                *            The fields of the reply
+                */
+               public void setFields(SimpleFieldSet fields) {
+                       this.fields = fields;
+               }
+
+               /**
+                * Returns the payload of the reply.
+                *
+                * @return The payload of the reply (may be {@code null})
+                */
+               @SuppressWarnings("unused")
+               public Bucket getData() {
+                       return data;
+               }
+
+               /**
+                * Sets the payload of the reply.
+                *
+                * @param data
+                *            The payload of the reply (may be {@code null})
+                */
+               public void setData(Bucket data) {
+                       this.data = data;
+               }
+
+       }
+
+       /**
+        * Helper method to create {@link SimpleFieldSet}s with terser code.
+        *
+        * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+        */
+       private static class SimpleFieldSetConstructor {
+
+               /** The field set being created. */
+               private SimpleFieldSet simpleFieldSet;
+
+               /**
+                * Creates a new simple field set constructor.
+                *
+                * @param shortLived
+                *            {@code true} if the resulting simple field set should be
+                *            short-lived, {@code false} otherwise
+                */
+               private SimpleFieldSetConstructor(boolean shortLived) {
+                       simpleFieldSet = new SimpleFieldSet(shortLived);
+               }
+
+               //
+               // ACCESSORS
+               //
+
+               /**
+                * Returns the created simple field set.
+                *
+                * @return The created simple field set
+                */
+               public SimpleFieldSet get() {
+                       return simpleFieldSet;
+               }
+
+               /**
+                * Sets the field with the given name to the given value.
+                *
+                * @param name
+                *            The name of the fleld
+                * @param value
+                *            The value of the field
+                * @return This constructor (for method chaining)
+                */
+               public SimpleFieldSetConstructor put(String name, String value) {
+                       simpleFieldSet.putOverwrite(name, value);
+                       return this;
+               }
+
+               //
+               // ACTIONS
+               //
+
+               /**
+                * Creates a new simple field set constructor.
+                *
+                * @return The created simple field set constructor
+                */
+               public static SimpleFieldSetConstructor create() {
+                       return create(true);
+               }
+
+               /**
+                * Creates a new simple field set constructor.
+                *
+                * @param shortLived
+                *            {@code true} if the resulting simple field set should be
+                *            short-lived, {@code false} otherwise
+                * @return The created simple field set constructor
+                */
+               public static SimpleFieldSetConstructor create(boolean shortLived) {
+                       SimpleFieldSetConstructor simpleFieldSetConstructor = new SimpleFieldSetConstructor(shortLived);
+                       return simpleFieldSetConstructor;
+               }
+
+       }
+
+}
index 531bc90..e156967 100644 (file)
@@ -26,6 +26,8 @@ import java.util.logging.Logger;
 import net.pterodactylus.sone.core.Core;
 import net.pterodactylus.sone.core.FreenetInterface;
 import net.pterodactylus.sone.freenet.PluginStoreConfigurationBackend;
+import net.pterodactylus.sone.freenet.wot.PluginConnector;
+import net.pterodactylus.sone.freenet.wot.WebOfTrustConnector;
 import net.pterodactylus.sone.web.WebInterface;
 import net.pterodactylus.util.config.Configuration;
 import net.pterodactylus.util.config.ConfigurationException;
@@ -158,6 +160,10 @@ public class SonePlugin implements FredPlugin, FredPluginL10n, FredPluginBaseL10
                /* create freenet interface. */
                FreenetInterface freenetInterface = new FreenetInterface(pluginRespirator.getNode(), pluginRespirator.getHLSimpleClient());
 
+               /* create web of trust connector. */
+               PluginConnector pluginConnector = new PluginConnector(pluginRespirator);
+               WebOfTrustConnector webOfTrustConnector = new WebOfTrustConnector(pluginConnector);
+
                /* create the web interface. */
                webInterface = new WebInterface(this);
 
@@ -165,6 +171,7 @@ public class SonePlugin implements FredPlugin, FredPluginL10n, FredPluginBaseL10
                core = new Core();
                core.configuration(configuration);
                core.freenetInterface(freenetInterface);
+               core.setWebOfTrustConnector(webOfTrustConnector);
 
                /* start core! */
                boolean startupFailed = true;
diff --git a/src/main/java/net/pterodactylus/sone/template/IdentityAccessor.java b/src/main/java/net/pterodactylus/sone/template/IdentityAccessor.java
new file mode 100644 (file)
index 0000000..4ea956d
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Sone - IdentityAccessor.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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.template;
+
+import java.util.Collections;
+import java.util.Set;
+
+import net.pterodactylus.sone.core.Core;
+import net.pterodactylus.sone.freenet.wot.Identity;
+import net.pterodactylus.sone.freenet.wot.OwnIdentity;
+import net.pterodactylus.sone.freenet.wot.PluginException;
+import net.pterodactylus.util.template.Accessor;
+import net.pterodactylus.util.template.DataProvider;
+import net.pterodactylus.util.template.ReflectionAccessor;
+
+/**
+ * {@link Accessor} implementation that adds a “uniqueNickname” member to an
+ * {@link Identity}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class IdentityAccessor extends ReflectionAccessor {
+
+       /** The core. */
+       private final Core core;
+
+       /**
+        * Creates a new identity accessor.
+        *
+        * @param core
+        *            The core
+        */
+       public IdentityAccessor(Core core) {
+               this.core = core;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public Object get(DataProvider dataProvider, Object object, String member) {
+               Identity identity = (Identity) object;
+               if ("uniqueNickname".equals(member)) {
+                       int minLength = -1;
+                       boolean found = false;
+                       Set<OwnIdentity> ownIdentities = null;
+                       try {
+                               ownIdentities = core.getWebOfTrustConnector().loadAllOwnIdentities();
+                       } catch (PluginException e) {
+                               ownIdentities = Collections.emptySet();
+                       }
+                       do {
+                               boolean unique = true;
+                               String abbreviatedWantedNickname = getAbbreviatedNickname(identity, ++minLength);
+                               for (Identity ownIdentity : ownIdentities) {
+                                       if (ownIdentity.equals(identity)) {
+                                               continue;
+                                       }
+                                       String abbreviatedNickname = getAbbreviatedNickname(ownIdentity, minLength);
+                                       if (abbreviatedNickname.equals(abbreviatedWantedNickname)) {
+                                               unique = false;
+                                               break;
+                                       }
+                               }
+                               found = unique;
+                       } while (!found && (minLength < 43));
+                       return getAbbreviatedNickname(identity, minLength);
+               }
+               return super.get(dataProvider, object, member);
+       }
+
+       //
+       // PRIVATE METHODS
+       //
+
+       /**
+        * Returns the nickname of the given identity, optionally appending the
+        * first characters of the ID to it.
+        *
+        * @param identity
+        *            The identity
+        * @param length
+        *            The number of characters from the beginning of the ID to
+        *            append to the nickname
+        * @return The nickname with optional ID appendage
+        */
+       private String getAbbreviatedNickname(Identity identity, int length) {
+               return identity.getNickname() + ((length > 0) ? "@" + identity.getId().substring(0, length) : "");
+       }
+
+}
index bb03306..5b787a9 100644 (file)
@@ -73,11 +73,6 @@ public class SoneAccessor extends ReflectionAccessor {
                } else if (member.equals("current")) {
                        Sone currentSone = (Sone) dataProvider.getData("currentSone");
                        return (currentSone != null) && currentSone.equals(sone);
-               } else if (member.equals("blocked")) {
-                       Sone currentSone = (Sone) dataProvider.getData("currentSone");
-                       return (currentSone != null) && currentSone.isSoneBlocked(sone.getId());
-               } else if (member.equals("blacklisted")) {
-                       return core.isBlacklistedSone(sone);
                } else if (member.equals("modified")) {
                        return sone.getModificationCounter() > 0;
                } else if (member.equals("status")) {
diff --git a/src/main/java/net/pterodactylus/sone/web/BlacklistPage.java b/src/main/java/net/pterodactylus/sone/web/BlacklistPage.java
deleted file mode 100644 (file)
index d8818bd..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Sone - BlacklistPage.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 <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.web;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import net.pterodactylus.sone.data.Sone;
-import net.pterodactylus.sone.template.SoneAccessor;
-import net.pterodactylus.util.template.Template;
-
-/**
- * This page lets the user manage Sone’s global blacklist.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class BlacklistPage extends SoneTemplatePage {
-
-       /**
-        * Creates a new blacklist management page.
-        *
-        * @param template
-        *            The template to render
-        * @param webInterface
-        *            The Sone web interface
-        */
-       public BlacklistPage(Template template, WebInterface webInterface) {
-               super("blacklist.html", template, "Page.Blacklist.Title", webInterface, false);
-       }
-
-       //
-       // TEMPLATEPAGE METHODS
-       //
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       protected void processTemplate(Request request, Template template) throws RedirectException {
-               super.processTemplate(request, template);
-               List<Sone> blacklistedSones = new ArrayList<Sone>(webInterface.core().getBlacklistedSones());
-               Collections.sort(blacklistedSones, new Comparator<Sone>() {
-
-                       @Override
-                       public int compare(Sone leftSone, Sone rightSone) {
-                               return SoneAccessor.getNiceName(leftSone).compareToIgnoreCase(SoneAccessor.getNiceName(rightSone));
-                       }
-
-               });
-               template.set("blacklistedSones", blacklistedSones);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/web/BlacklistSonePage.java b/src/main/java/net/pterodactylus/sone/web/BlacklistSonePage.java
deleted file mode 100644 (file)
index b16f4a0..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Sone - BlacklistSonePage.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 <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.web;
-
-import net.pterodactylus.sone.data.Sone;
-import net.pterodactylus.sone.web.page.Page.Request.Method;
-import net.pterodactylus.util.template.Template;
-
-/**
- * This page lets the user blacklist a {@link Sone}.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class BlacklistSonePage extends SoneTemplatePage {
-
-       /**
-        * Creates a new “blacklist Sone” page.
-        *
-        * @param template
-        *            The template to render
-        * @param webInterface
-        *            The Sone web interface
-        */
-       public BlacklistSonePage(Template template, WebInterface webInterface) {
-               super("blacklistSone.html", template, "Page.BlacklistSone.Title", webInterface, false);
-       }
-
-       //
-       // TEMPLATEPAGE METHODS
-       //
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       protected void processTemplate(Request request, Template template) throws RedirectException {
-               super.processTemplate(request, template);
-               if (request.getMethod() == Method.POST) {
-                       String soneId = request.getHttpRequest().getPartAsStringFailsafe("sone", 36);
-                       String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 64);
-                       Sone sone = webInterface.core().getSone(soneId);
-                       webInterface.core().blacklistSone(sone);
-                       throw new RedirectException(returnPage);
-               }
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/web/BlockSonePage.java b/src/main/java/net/pterodactylus/sone/web/BlockSonePage.java
deleted file mode 100644 (file)
index 328d6f0..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Sone - BlockSonePage.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 <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.web;
-
-import net.pterodactylus.sone.web.page.Page.Request.Method;
-import net.pterodactylus.util.template.Template;
-
-/**
- * This page lets the user block a Sone for propagation.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class BlockSonePage extends SoneTemplatePage {
-
-       /**
-        * Creates a new “block Sone” page.
-        *
-        * @param template
-        *            The template to render
-        * @param webInterface
-        *            The Sone web interface
-        */
-       public BlockSonePage(Template template, WebInterface webInterface) {
-               super("blockSone.html", template, "Page.BlockSone.Title", webInterface, true);
-       }
-
-       //
-       // TEMPLATEPAGE METHODS
-       //
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       protected void processTemplate(Request request, Template template) throws RedirectException {
-               super.processTemplate(request, template);
-               if (request.getMethod() == Method.POST) {
-                       String soneId = request.getHttpRequest().getPartAsStringFailsafe("sone", 36);
-                       String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 64);
-                       getCurrentSone(request.getToadletContext()).addBlockedSoneId(soneId);
-                       throw new RedirectException(returnPage);
-               }
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/web/UnblacklistSonePage.java b/src/main/java/net/pterodactylus/sone/web/UnblacklistSonePage.java
deleted file mode 100644 (file)
index e6be115..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Sone - UnblacklistSonePage.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 <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.web;
-
-import net.pterodactylus.sone.data.Sone;
-import net.pterodactylus.sone.web.page.Page.Request.Method;
-import net.pterodactylus.util.template.Template;
-
-/**
- * This page lets the user unblacklist a {@link Sone}.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class UnblacklistSonePage extends SoneTemplatePage {
-
-       /**
-        * Creates a new “unblacklist Sone” page.
-        *
-        * @param template
-        *            The template to render
-        * @param webInterface
-        *            The Sone web interface
-        */
-       public UnblacklistSonePage(Template template, WebInterface webInterface) {
-               super("unblacklistSone.html", template, "Page.UnblacklistSone.Title", webInterface, false);
-       }
-
-       //
-       // TEMPLATEPAGE METHODS
-       //
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       protected void processTemplate(Request request, Template template) throws RedirectException {
-               super.processTemplate(request, template);
-               if (request.getMethod() == Method.POST) {
-                       String soneId = request.getHttpRequest().getPartAsStringFailsafe("sone", 36);
-                       String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 64);
-                       Sone sone = webInterface.core().getSone(soneId);
-                       webInterface.core().unblacklistSone(sone);
-                       throw new RedirectException(returnPage);
-               }
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/web/UnblockSonePage.java b/src/main/java/net/pterodactylus/sone/web/UnblockSonePage.java
deleted file mode 100644 (file)
index cc88cce..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Sone - BlockSonePage.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 <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.web;
-
-import net.pterodactylus.sone.web.page.Page.Request.Method;
-import net.pterodactylus.util.template.Template;
-
-/**
- * This page lets the user unblock a Sone for propagation.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class UnblockSonePage extends SoneTemplatePage {
-
-       /**
-        * Creates a new “unblock Sone” page.
-        *
-        * @param template
-        *            The template to render
-        * @param webInterface
-        *            The Sone web interface
-        */
-       public UnblockSonePage(Template template, WebInterface webInterface) {
-               super("unblockSone.html", template, "Page.UnblockSone.Title", webInterface, true);
-       }
-
-       //
-       // TEMPLATEPAGE METHODS
-       //
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       protected void processTemplate(Request request, Template template) throws RedirectException {
-               super.processTemplate(request, template);
-               if (request.getMethod() == Method.POST) {
-                       String soneId = request.getHttpRequest().getPartAsStringFailsafe("sone", 36);
-                       String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 64);
-                       if (request.getMethod() == Method.POST) {
-                               getCurrentSone(request.getToadletContext()).removeBlockedSoneId(soneId);
-                       }
-                       throw new RedirectException(returnPage);
-               }
-       }
-
-}
index fd4365e..0d3c9b7 100644 (file)
@@ -40,8 +40,6 @@ import net.pterodactylus.sone.template.ReplyAccessor;
 import net.pterodactylus.sone.template.RequestChangeFilter;
 import net.pterodactylus.sone.template.SoneAccessor;
 import net.pterodactylus.sone.template.SubstringFilter;
-import net.pterodactylus.sone.web.ajax.BlacklistSoneAjaxPage;
-import net.pterodactylus.sone.web.ajax.BlockSoneAjaxPage;
 import net.pterodactylus.sone.web.ajax.DeletePostAjaxPage;
 import net.pterodactylus.sone.web.ajax.DeleteReplyAjaxPage;
 import net.pterodactylus.sone.web.ajax.FollowSoneAjaxPage;
@@ -49,8 +47,6 @@ import net.pterodactylus.sone.web.ajax.GetLikesAjaxPage;
 import net.pterodactylus.sone.web.ajax.GetSoneStatusPage;
 import net.pterodactylus.sone.web.ajax.GetTranslationPage;
 import net.pterodactylus.sone.web.ajax.LikeAjaxPage;
-import net.pterodactylus.sone.web.ajax.UnblacklistSoneAjaxPage;
-import net.pterodactylus.sone.web.ajax.UnblockSoneAjaxPage;
 import net.pterodactylus.sone.web.ajax.UnfollowSoneAjaxPage;
 import net.pterodactylus.sone.web.ajax.UnlikeAjaxPage;
 import net.pterodactylus.sone.web.page.PageToadlet;
@@ -205,8 +201,6 @@ public class WebInterface extends AbstractService {
                Template editProfileTemplate = templateFactory.createTemplate(createReader("/templates/editProfile.html"));
                Template backupProfileTemplate = templateFactory.createTemplate(createReader("/templates/backup.xml"));
                Template viewSoneTemplate = templateFactory.createTemplate(createReader("/templates/viewSone.html"));
-               Template blockSoneTemplate = templateFactory.createTemplate(createReader("/templates/blockSone.html"));
-               Template unblockSoneTemplate = templateFactory.createTemplate(createReader("/templates/unblockSone.html"));
                Template viewPostTemplate = templateFactory.createTemplate(createReader("/templates/viewPost.html"));
                Template likePostTemplate = templateFactory.createTemplate(createReader("/templates/like.html"));
                Template unlikePostTemplate = templateFactory.createTemplate(createReader("/templates/unlike.html"));
@@ -218,9 +212,6 @@ public class WebInterface extends AbstractService {
                Template noPermissionTemplate = templateFactory.createTemplate(createReader("/templates/noPermission.html"));
                Template logoutTemplate = templateFactory.createTemplate(createReader("/templates/logout.html"));
                Template optionsTemplate = templateFactory.createTemplate(createReader("/templates/options.html"));
-               Template blacklistTemplate = templateFactory.createTemplate(createReader("/templates/blacklist.html"));
-               Template blacklistSoneTemplate = templateFactory.createTemplate(createReader("/templates/blacklistSone.html"));
-               Template unblacklistSoneTemplate = templateFactory.createTemplate(createReader("/templates/unblacklistSone.html"));
                Template aboutTemplate = templateFactory.createTemplate(createReader("/templates/about.html"));
                Template helpTemplate = templateFactory.createTemplate(createReader("/templates/help.html"));
 
@@ -236,8 +227,6 @@ public class WebInterface extends AbstractService {
                pageToadlets.add(pageToadletFactory.createPageToadlet(new CreatePostPage(createPostTemplate, this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new CreateReplyPage(createReplyTemplate, this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new ViewSonePage(viewSoneTemplate, this)));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new BlockSonePage(blockSoneTemplate, this)));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new UnblockSonePage(unblockSoneTemplate, this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new ViewPostPage(viewPostTemplate, this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new LikePage(likePostTemplate, this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new UnlikePage(unlikePostTemplate, this)));
@@ -249,9 +238,6 @@ public class WebInterface extends AbstractService {
                pageToadlets.add(pageToadletFactory.createPageToadlet(new LoginPage(loginTemplate, this), "Login"));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new LogoutPage(logoutTemplate, this), "Logout"));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new OptionsPage(optionsTemplate, this), "Options"));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new BlacklistPage(blacklistTemplate, this), "Blacklist"));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new BlacklistSonePage(blacklistSoneTemplate, this)));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new UnblacklistSonePage(unblacklistSoneTemplate, this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new AboutPage(aboutTemplate, this, SonePlugin.VERSION), "About"));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new SoneTemplatePage("help.html", helpTemplate, "Page.Help.Title", this), "Help"));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new SoneTemplatePage("noPermission.html", noPermissionTemplate, "Page.NoPermission.Title", this)));
@@ -264,10 +250,6 @@ public class WebInterface extends AbstractService {
                pageToadlets.add(pageToadletFactory.createPageToadlet(new DeleteReplyAjaxPage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new FollowSoneAjaxPage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new UnfollowSoneAjaxPage(this)));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new BlockSoneAjaxPage(this)));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new UnblockSoneAjaxPage(this)));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new BlacklistSoneAjaxPage(this)));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new UnblacklistSoneAjaxPage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new LikeAjaxPage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new UnlikeAjaxPage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new GetLikesAjaxPage(this)));
diff --git a/src/main/java/net/pterodactylus/sone/web/ajax/BlacklistSoneAjaxPage.java b/src/main/java/net/pterodactylus/sone/web/ajax/BlacklistSoneAjaxPage.java
deleted file mode 100644 (file)
index 83a38e4..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Sone - BlacklistSoneAjaxPage.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 <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.web.ajax;
-
-import net.pterodactylus.sone.data.Sone;
-import net.pterodactylus.sone.web.WebInterface;
-import net.pterodactylus.util.json.JsonObject;
-
-/**
- * AJAX page that blacklists a Sone.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class BlacklistSoneAjaxPage extends JsonPage {
-
-       /**
-        * Creates a new “blacklist Sone” AJAX page.
-        *
-        * @param webInterface
-        *            The Sone web interface
-        */
-       public BlacklistSoneAjaxPage(WebInterface webInterface) {
-               super("ajax/blacklistSone.ajax", webInterface);
-       }
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       protected JsonObject createJsonObject(Request request) {
-               String soneId = request.getHttpRequest().getParam("sone");
-               if (soneId == null) {
-                       return new JsonObject().put("success", false).put("error", "invalid-sone-id");
-               }
-               Sone sone = webInterface.core().getSone(soneId);
-               webInterface.core().blacklistSone(sone);
-               return new JsonObject().put("success", true);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/web/ajax/BlockSoneAjaxPage.java b/src/main/java/net/pterodactylus/sone/web/ajax/BlockSoneAjaxPage.java
deleted file mode 100644 (file)
index e4ffe2b..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Sone - BlockSoneAjaxPage.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 <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.web.ajax;
-
-import net.pterodactylus.sone.data.Sone;
-import net.pterodactylus.sone.web.WebInterface;
-import net.pterodactylus.util.json.JsonObject;
-
-/**
- * AJAX page that lets the user block another Sone.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class BlockSoneAjaxPage extends JsonPage {
-
-       /**
-        * Creates a new “block Sone” AJAX page.
-        *
-        * @param webInterface
-        *            The Sone web interface
-        */
-       public BlockSoneAjaxPage(WebInterface webInterface) {
-               super("ajax/blockSone.ajax", webInterface);
-       }
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       protected JsonObject createJsonObject(Request request) {
-               String soneId = request.getHttpRequest().getParam("sone");
-               if (soneId == null) {
-                       return new JsonObject().put("success", false).put("error", "invalid-sone-id");
-               }
-               Sone currentSone = getCurrentSone(request.getToadletContext());
-               if (currentSone == null) {
-                       return new JsonObject().put("success", false).put("error", "auth-required");
-               }
-               currentSone.addBlockedSoneId(soneId);
-               return new JsonObject().put("success", true);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/web/ajax/UnblacklistSoneAjaxPage.java b/src/main/java/net/pterodactylus/sone/web/ajax/UnblacklistSoneAjaxPage.java
deleted file mode 100644 (file)
index 751efb6..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Sone - UnblacklistSoneAjaxPage.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 <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.web.ajax;
-
-import net.pterodactylus.sone.data.Sone;
-import net.pterodactylus.sone.web.WebInterface;
-import net.pterodactylus.util.json.JsonObject;
-
-/**
- * AJAX page that unblacklists a Sone.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class UnblacklistSoneAjaxPage extends JsonPage {
-
-       /**
-        * Creates a new “unblacklist Sone” AJAX page.
-        *
-        * @param webInterface
-        *            The Sone web interface
-        */
-       public UnblacklistSoneAjaxPage(WebInterface webInterface) {
-               super("ajax/unblacklistSone.ajax", webInterface);
-       }
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       protected JsonObject createJsonObject(Request request) {
-               String soneId = request.getHttpRequest().getParam("sone");
-               if (soneId == null) {
-                       return new JsonObject().put("success", false).put("error", "invalid-sone-id");
-               }
-               Sone sone = webInterface.core().getSone(soneId);
-               webInterface.core().unblacklistSone(sone);
-               return new JsonObject().put("success", true);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/web/ajax/UnblockSoneAjaxPage.java b/src/main/java/net/pterodactylus/sone/web/ajax/UnblockSoneAjaxPage.java
deleted file mode 100644 (file)
index 9012aee..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Sone - UnblockSoneAjaxPage.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 <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.web.ajax;
-
-import net.pterodactylus.sone.data.Sone;
-import net.pterodactylus.sone.web.WebInterface;
-import net.pterodactylus.util.json.JsonObject;
-
-/**
- * AJAX page that lets the user unblock another Sone.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class UnblockSoneAjaxPage extends JsonPage {
-
-       /**
-        * Creates a new “unblock Sone” AJAX page.
-        *
-        * @param webInterface
-        *            The Sone web interface
-        */
-       public UnblockSoneAjaxPage(WebInterface webInterface) {
-               super("ajax/unblockSone.ajax", webInterface);
-       }
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       protected JsonObject createJsonObject(Request request) {
-               String soneId = request.getHttpRequest().getParam("sone");
-               if (soneId == null) {
-                       return new JsonObject().put("success", false).put("error", "invalid-sone-id");
-               }
-               Sone currentSone = getCurrentSone(request.getToadletContext());
-               if (currentSone == null) {
-                       return new JsonObject().put("success", false).put("error", "auth-required");
-               }
-               currentSone.removeBlockedSoneId(soneId);
-               return new JsonObject().put("success", true);
-       }
-
-}
index 9f63a64..53e69e2 100644 (file)
@@ -18,8 +18,6 @@ Navigation.Menu.Item.Logout.Name=Logout
 Navigation.Menu.Item.Logout.Tooltip=Logs you out of the current Sone
 Navigation.Menu.Item.Options.Name=Options
 Navigation.Menu.Item.Options.Tooltip=Options for the Sone plugin
-Navigation.Menu.Item.Blacklist.Name=Blacklist
-Navigation.Menu.Item.Blacklist.Tooltip=Manages the global blacklist
 Navigation.Menu.Item.About.Name=About
 Navigation.Menu.Item.About.Tooltip=Information about Sone
 Navigation.Menu.Item.Help.Name=Help
@@ -44,15 +42,6 @@ Page.Options.Option.ClearOnNextRestart.Description=Resets the configuration of t
 Page.Options.Option.ReallyClearOnNextRestart.Description=This option needs to be set to “yes” if you really, {strong}really{/strong} want to clear the plugin configuration on the next restart.
 Page.Options.Button.Save=Save
 
-Page.Blacklist.Title=Blacklist - Sone
-Page.Blacklist.Page.Title=Blacklist
-Page.Blacklist.Text.Description=The Sone on the blacklist are prevented from being distributed with your next Sone updates, and there will be no updates fetched for these Sones.
-Page.Blacklist.Text.Empty=There are currently no Sones in the blacklist.
-
-Page.BlacklistSone.Title=Blacklist Sone - Sone
-
-Page.UnblacklistSone.Title=Unblacklist Sone - Sone
-
 Page.Login.Title=Login - Sone
 Page.Login.Page.Title=Login
 Page.Login.Label.SelectSone=Select Sone:
@@ -156,10 +145,6 @@ Page.ViewSone.FollowSone.Text=Follow this Sone
 Page.ViewSone.Following.Title=This Sone follows
 Page.ViewSone.Following.FollowingNone.Text=Apparently, this Sone does not yet follow any other Sone.
 
-Page.BlockSone.Title=Block Sone - Sone
-
-Page.UnblockSone.Title=Block Sone - Sone
-
 Page.ViewPost.Title=View Post - Sone
 Page.ViewPost.Page.Title=View Post by {sone}
 Page.ViewPost.Button.PostReply=Post Reply!
@@ -193,10 +178,6 @@ Page.Tail.Text.KeyOfSone=Key of this Sone (give this to other people):
 View.Sone.Label.LastUpdate=Last update:
 View.Sone.Button.UnfollowSone=unfollow
 View.Sone.Button.FollowSone=follow
-View.Sone.Button.UnblockSone=unblock
-View.Sone.Button.BlockSone=block
-View.Sone.Button.BlacklistSone=blacklist
-View.Sone.Button.UnblacklistSone=unblacklist
 View.Sone.Status.Modified=This Sone was modified and waits to be inserted.
 View.Sone.Status.Unknown=This Sone has not yet been retrieved.
 View.Sone.Status.Idle=This Sone is idle, i.e. not being inserted or downloaded.
diff --git a/src/main/resources/templates/blacklist.html b/src/main/resources/templates/blacklist.html
deleted file mode 100644 (file)
index 4968cae..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<%include include/head.html>
-
-       <h1><%= Page.Blacklist.Page.Title|l10n|html></h1>
-
-       <p><%= Page.Blacklist.Text.Description|l10n|html></p>
-
-       <div id="blacklist">
-               <%getpage>
-               <%paginate list=blacklistedSones pagesize=25>
-               <%= page|store key=pageParameter>
-               <%include include/pagination.html>
-               <%foreach pagination.items sone>
-                       <%include include/viewSone.html>
-               <%foreachelse>
-                       <p><%= Page.Blacklist.Text.Empty|l10n|html></p>
-               <%/foreach>
-               <%include include/pagination.html>
-       </div>
-
-<%include include/tail.html>
diff --git a/src/main/resources/templates/blacklistSone.html b/src/main/resources/templates/blacklistSone.html
deleted file mode 100644 (file)
index 196af72..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<%include include/head.html>
-
-<%include include/tail.html>
diff --git a/src/main/resources/templates/blockSone.html b/src/main/resources/templates/blockSone.html
deleted file mode 100644 (file)
index 196af72..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<%include include/head.html>
-
-<%include include/tail.html>
index 39d42da..d4e5b67 100644 (file)
        <div class="short-request-uri"><% sone.requestUri|substring start=4 length=43|html></div>
        <div class="hidden"><% sone.blacklisted></div>
        <%if ! sone.current>
-               <%if ! sone.blacklisted>
-                       <form class="blacklist" action="blacklistSone.html" method="post">
+               <%ifnull ! currentSone>
+                       <form class="unfollow<%if ! sone.friend> hidden<%/if>" action="unfollowSone.html" method="post">
                                <input type="hidden" name="formPassword" value="<% formPassword|html>" />
                                <input type="hidden" name="sone" value="<% sone.id|html>" />
                                <input type="hidden" name="returnPage" value="<% request.uri|html>" />
-                               <button type="submit"><%= View.Sone.Button.BlacklistSone|l10n|html></button>
+                               <button type="submit"><%= View.Sone.Button.UnfollowSone|l10n|html></button>
                        </form>
-                       <%ifnull ! currentSone>
-                               <form class="unfollow<%if ! sone.friend> hidden<%/if>" action="unfollowSone.html" method="post">
-                                       <input type="hidden" name="formPassword" value="<% formPassword|html>" />
-                                       <input type="hidden" name="sone" value="<% sone.id|html>" />
-                                       <input type="hidden" name="returnPage" value="<% request.uri|html>" />
-                                       <button type="submit"><%= View.Sone.Button.UnfollowSone|l10n|html></button>
-                               </form>
-                               <form class="follow<%if sone.friend> hidden<%/if>" action="followSone.html" method="post">
-                                       <input type="hidden" name="formPassword" value="<% formPassword|html>" />
-                                       <input type="hidden" name="sone" value="<% sone.id|html>" />
-                                       <input type="hidden" name="returnPage" value="<% request.uri|html>" />
-                                       <button type="submit"><%= View.Sone.Button.FollowSone|l10n|html></button>
-                               </form>
-                               <form class="unblock<%if ! sone.blocked> hidden<%/if>" action="unblockSone.html" method="post">
-                                       <input type="hidden" name="formPassword" value="<% formPassword|html>" />
-                                       <input type="hidden" name="sone" value="<% sone.id|html>" />
-                                       <input type="hidden" name="returnPage" value="<% request.uri|html>" />
-                                       <button type="submit"><%= View.Sone.Button.UnblockSone|l10n|html></button>
-                               </form>
-                               <form class="block<%if sone.blocked> hidden<%/if>" action="blockSone.html" method="post">
-                                       <input type="hidden" name="formPassword" value="<% formPassword|html>" />
-                                       <input type="hidden" name="sone" value="<% sone.id|html>" />
-                                       <input type="hidden" name="returnPage" value="<% request.uri|html>" />
-                                       <button type="submit"><%= View.Sone.Button.BlockSone|l10n|html></button>
-                               </form>
-                       <%/if>
-               <%else>
-                       <form class="unblacklist" action="unblacklistSone.html" method="post">
+                       <form class="follow<%if sone.friend> hidden<%/if>" action="followSone.html" method="post">
                                <input type="hidden" name="formPassword" value="<% formPassword|html>" />
                                <input type="hidden" name="sone" value="<% sone.id|html>" />
                                <input type="hidden" name="returnPage" value="<% request.uri|html>" />
-                               <button type="submit"><%= View.Sone.Button.UnblacklistSone|l10n|html></button>
+                               <button type="submit"><%= View.Sone.Button.FollowSone|l10n|html></button>
                        </form>
                <%/if>
        <%/if>
index 782eccd..c80dbe7 100644 (file)
                <%/foreach>
        </reply-likes>
 
-       <known-sones>
-               <%foreach knownSones sone>
-               <known-sone>
-                       <sone-id><% sone.id|xml></sone-id>
-                       <sone-key><% sone.requestUri|xml></sone-key>
-                       <sone-name><% sone.name|xml></sone-name>
-               </known-sone>
-               <%/foreach>
-       </known-sones>
-
 </sone>
diff --git a/src/main/resources/templates/unblacklistSone.html b/src/main/resources/templates/unblacklistSone.html
deleted file mode 100644 (file)
index 196af72..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<%include include/head.html>
-
-<%include include/tail.html>
diff --git a/src/main/resources/templates/unblockSone.html b/src/main/resources/templates/unblockSone.html
deleted file mode 100644 (file)
index 196af72..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<%include include/head.html>
-
-<%include include/tail.html>