Use the identity loader for loading identities.
[Sone.git] / src / main / java / net / pterodactylus / sone / freenet / wot / IdentityManager.java
1 /*
2  * Sone - IdentityManager.java - Copyright © 2010–2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.freenet.wot;
19
20 import static com.google.common.base.Optional.fromNullable;
21 import static com.google.common.collect.HashMultimap.create;
22
23 import java.util.HashSet;
24 import java.util.Set;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27
28 import net.pterodactylus.sone.freenet.plugin.PluginException;
29 import net.pterodactylus.sone.freenet.wot.IdentityChangeDetector.IdentityProcessor;
30 import net.pterodactylus.sone.freenet.wot.event.IdentityAddedEvent;
31 import net.pterodactylus.sone.freenet.wot.event.IdentityRemovedEvent;
32 import net.pterodactylus.sone.freenet.wot.event.IdentityUpdatedEvent;
33 import net.pterodactylus.sone.freenet.wot.event.OwnIdentityAddedEvent;
34 import net.pterodactylus.sone.freenet.wot.event.OwnIdentityRemovedEvent;
35 import net.pterodactylus.util.logging.Logging;
36 import net.pterodactylus.util.service.AbstractService;
37
38 import com.google.common.collect.Multimap;
39 import com.google.common.collect.Sets;
40 import com.google.common.eventbus.EventBus;
41 import com.google.inject.Inject;
42 import com.google.inject.name.Named;
43
44 /**
45  * The identity manager takes care of loading and storing identities, their
46  * contexts, and properties. It does so in a way that does not expose errors via
47  * exceptions but it only logs them and tries to return sensible defaults.
48  * <p/>
49  * It is also responsible for polling identities from the Web of Trust plugin
50  * and sending events to the {@link EventBus} when {@link Identity}s and {@link
51  * OwnIdentity}s are discovered or disappearing.
52  *
53  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
54  */
55 public class IdentityManager extends AbstractService {
56
57         /** The logger. */
58         private static final Logger logger = Logging.getLogger(IdentityManager.class);
59
60         /** The event bus. */
61         private final EventBus eventBus;
62
63         private final IdentityLoader identityLoader;
64
65         /** The Web of Trust connector. */
66         private final WebOfTrustConnector webOfTrustConnector;
67
68         /** The currently known own identities. */
69         /* synchronize access on syncObject. */
70         private final Set<OwnIdentity> currentOwnIdentities = Sets.newHashSet();
71
72         /**
73          * Creates a new identity manager.
74          *
75          * @param eventBus
76          *              The event bus
77          * @param webOfTrustConnector
78          *              The Web of Trust connector
79          * @param context
80          *              The context to focus on (may be {@code null} to ignore contexts)
81          */
82         @Inject
83         public IdentityManager(EventBus eventBus, WebOfTrustConnector webOfTrustConnector, @Named("WebOfTrustContext") String context) {
84                 super("Sone Identity Manager", false);
85                 this.eventBus = eventBus;
86                 this.webOfTrustConnector = webOfTrustConnector;
87                 this.identityLoader = new IdentityLoader(webOfTrustConnector, fromNullable(context));
88         }
89
90         //
91         // ACCESSORS
92         //
93
94         /**
95          * Returns whether the Web of Trust plugin could be reached during the last
96          * try.
97          *
98          * @return {@code true} if the Web of Trust plugin is connected, {@code false}
99          *         otherwise
100          */
101         public boolean isConnected() {
102                 try {
103                         webOfTrustConnector.ping();
104                         return true;
105                 } catch (PluginException pe1) {
106                         /* not connected, ignore. */
107                         return false;
108                 }
109         }
110
111         /**
112          * Returns all own identities.
113          *
114          * @return All own identities
115          */
116         public Set<OwnIdentity> getAllOwnIdentities() {
117                 synchronized (currentOwnIdentities) {
118                         return new HashSet<OwnIdentity>(currentOwnIdentities);
119                 }
120         }
121
122         //
123         // SERVICE METHODS
124         //
125
126         @Override
127         protected void serviceRun() {
128                 Multimap<OwnIdentity, Identity> oldIdentities = create();
129
130                 while (!shouldStop()) {
131                         try {
132                                 Multimap<OwnIdentity, Identity> currentIdentities = identityLoader.loadIdentities();
133
134                                 detectChangesInIdentities(currentIdentities, oldIdentities);
135                                 oldIdentities = currentIdentities;
136
137                                 synchronized (currentOwnIdentities) {
138                                         currentOwnIdentities.clear();
139                                         currentOwnIdentities.addAll(currentIdentities.keySet());
140                                 }
141                         } catch (WebOfTrustException wote1) {
142                                 logger.log(Level.WARNING, "WoT has disappeared!", wote1);
143                         }
144
145                         /* wait a minute before checking again. */
146                         sleep(60 * 1000);
147                 }
148         }
149
150         private void detectChangesInIdentities(Multimap<OwnIdentity, Identity> newIdentities, Multimap<OwnIdentity, Identity> oldIdentities) {
151                 IdentityChangeDetector identityChangeDetector = new IdentityChangeDetector(getAllOwnIdentities());
152                 identityChangeDetector.onNewIdentity(addNewOwnIdentityAndItsTrustedIdentities(newIdentities));
153                 identityChangeDetector.onRemovedIdentity(removeOwnIdentityAndItsTrustedIdentities(oldIdentities));
154                 identityChangeDetector.onUnchangedIdentity(detectChangesInTrustedIdentities(newIdentities, oldIdentities));
155                 identityChangeDetector.detectChanges(newIdentities.keySet());
156         }
157
158         private IdentityProcessor detectChangesInTrustedIdentities(Multimap<OwnIdentity, Identity> newIdentities, Multimap<OwnIdentity, Identity> oldIdentities) {
159                 return new DefaultIdentityProcessor(oldIdentities, newIdentities);
160         }
161
162         private IdentityProcessor removeOwnIdentityAndItsTrustedIdentities(final Multimap<OwnIdentity, Identity> oldIdentities) {
163                 return new IdentityProcessor() {
164                         @Override
165                         public void processIdentity(Identity identity) {
166                                 eventBus.post(new OwnIdentityRemovedEvent((OwnIdentity) identity));
167                                 for (Identity removedIdentity : oldIdentities.get((OwnIdentity) identity)) {
168                                         eventBus.post(new IdentityRemovedEvent((OwnIdentity) identity, removedIdentity));
169                                 }
170                         }
171                 };
172         }
173
174         private IdentityProcessor addNewOwnIdentityAndItsTrustedIdentities(final Multimap<OwnIdentity, Identity> newIdentities) {
175                 return new IdentityProcessor() {
176                         @Override
177                         public void processIdentity(Identity identity) {
178                                 eventBus.post(new OwnIdentityAddedEvent((OwnIdentity) identity));
179                                 for (Identity newIdentity : newIdentities.get((OwnIdentity) identity)) {
180                                         eventBus.post(new IdentityAddedEvent((OwnIdentity) identity, newIdentity));
181                                 }
182                         }
183                 };
184         }
185
186         private class DefaultIdentityProcessor implements IdentityProcessor {
187
188                 private final Multimap<OwnIdentity, Identity> oldIdentities;
189                 private final Multimap<OwnIdentity, Identity> newIdentities;
190
191                 public DefaultIdentityProcessor(Multimap<OwnIdentity, Identity> oldIdentities, Multimap<OwnIdentity, Identity> newIdentities) {
192                         this.oldIdentities = oldIdentities;
193                         this.newIdentities = newIdentities;
194                 }
195
196                 @Override
197                 public void processIdentity(Identity ownIdentity) {
198                         IdentityChangeDetector identityChangeDetector = new IdentityChangeDetector(oldIdentities.get((OwnIdentity) ownIdentity));
199                         identityChangeDetector.onNewIdentity(notifyForAddedIdentities((OwnIdentity) ownIdentity));
200                         identityChangeDetector.onRemovedIdentity(notifyForRemovedIdentities((OwnIdentity) ownIdentity));
201                         identityChangeDetector.onChangedIdentity(notifyForChangedIdentities((OwnIdentity) ownIdentity));
202                         identityChangeDetector.detectChanges(newIdentities.get((OwnIdentity) ownIdentity));
203                 }
204
205                 private IdentityProcessor notifyForChangedIdentities(final OwnIdentity ownIdentity) {
206                         return new IdentityProcessor() {
207                                 @Override
208                                 public void processIdentity(Identity identity) {
209                                         eventBus.post(new IdentityUpdatedEvent(ownIdentity, identity));
210                                 }
211                         };
212                 }
213
214                 private IdentityProcessor notifyForRemovedIdentities(final OwnIdentity ownIdentity) {
215                         return new IdentityProcessor() {
216                                 @Override
217                                 public void processIdentity(Identity identity) {
218                                         eventBus.post(new IdentityRemovedEvent(ownIdentity, identity));
219                                 }
220                         };
221                 }
222
223                 private IdentityProcessor notifyForAddedIdentities(final OwnIdentity ownIdentity) {
224                         return new IdentityProcessor() {
225                                 @Override
226                                 public void processIdentity(Identity identity) {
227                                         eventBus.post(new IdentityAddedEvent(ownIdentity, identity));
228                                 }
229                         };
230                 }
231
232         }
233
234 }