2 * Sone - WebOfTrustUpdater.java - Copyright © 2012 David Roden
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package net.pterodactylus.sone.core;
20 import java.util.concurrent.BlockingQueue;
21 import java.util.concurrent.LinkedBlockingQueue;
22 import java.util.logging.Level;
23 import java.util.logging.Logger;
25 import net.pterodactylus.sone.freenet.plugin.PluginException;
26 import net.pterodactylus.sone.freenet.wot.DefaultIdentity;
27 import net.pterodactylus.sone.freenet.wot.Identity;
28 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
29 import net.pterodactylus.sone.freenet.wot.Trust;
30 import net.pterodactylus.sone.freenet.wot.WebOfTrustConnector;
31 import net.pterodactylus.sone.freenet.wot.WebOfTrustException;
32 import net.pterodactylus.util.logging.Logging;
33 import net.pterodactylus.util.service.AbstractService;
34 import net.pterodactylus.util.validation.Validation;
37 * Updates WebOfTrust identity data in a background thread because communicating
38 * with the WebOfTrust plugin can potentially last quite long.
40 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
42 public class WebOfTrustUpdater extends AbstractService {
45 private static final Logger logger = Logging.getLogger(WebOfTrustUpdater.class);
48 @SuppressWarnings("synthetic-access")
49 private final WebOfTrustUpdateJob stopJob = new WebOfTrustUpdateJob();
51 /** The web of trust connector. */
52 private final WebOfTrustConnector webOfTrustConnector;
54 /** The queue for jobs. */
55 private final BlockingQueue<WebOfTrustUpdateJob> updateJobs = new LinkedBlockingQueue<WebOfTrustUpdateJob>();
58 * Creates a new trust updater.
60 * @param webOfTrustConnector
61 * The web of trust connector
63 public WebOfTrustUpdater(WebOfTrustConnector webOfTrustConnector) {
64 super("Trust Updater");
65 this.webOfTrustConnector = webOfTrustConnector;
73 * Retrieves the trust relation between the truster and the trustee. This
74 * method will return immediately and perform a trust update in the
78 * The identity giving the trust
80 * The identity receiving the trust
82 public void getTrust(OwnIdentity truster, Identity trustee) {
83 GetTrustJob getTrustJob = new GetTrustJob(truster, trustee);
84 if (!updateJobs.contains(getTrustJob)) {
85 logger.log(Level.FINER, "Adding Trust Update Job: " + getTrustJob);
87 updateJobs.put(getTrustJob);
88 } catch (InterruptedException ie1) {
89 /* the queue is unbounded so it should never block. */
95 * Updates the trust relation between the truster and the trustee. This
96 * method will return immediately and perform a trust update in the
100 * The identity giving the trust
102 * The identity receiving the trust
104 * The new level of trust (from -100 to 100, may be {@code null}
105 * to remove the trust completely)
107 * The comment of the trust relation
109 public void setTrust(OwnIdentity truster, Identity trustee, Integer score, String comment) {
110 SetTrustJob setTrustJob = new SetTrustJob(truster, trustee, score, comment);
111 if (updateJobs.contains(setTrustJob)) {
112 updateJobs.remove(setTrustJob);
114 logger.log(Level.FINER, "Adding Trust Update Job: " + setTrustJob);
116 updateJobs.put(setTrustJob);
117 } catch (InterruptedException e) {
118 /* the queue is unbounded so it should never block. */
123 * Adds the given context to the given own identity.
126 * The own identity to add the context to
130 public void addContext(OwnIdentity ownIdentity, String context) {
131 addContextWait(ownIdentity, context, false);
135 * Adds the given context to the given own identity, waiting for completion
139 * The own identity to add the context to
142 * @return {@code true} if the context was added successfully, {@code false}
145 public boolean addContextWait(OwnIdentity ownIdentity, String context) {
146 return addContextWait(ownIdentity, context, true);
150 * Adds the given context to the given own identity, waiting for completion
154 * The own identity to add the context to
158 * {@code true} to wait for the end of the operation,
159 * {@code false} to return immediately
160 * @return {@code true} if the context was added successfully, {@code false}
161 * if the context was not added successfully, or if the job should
162 * not wait for completion
164 private boolean addContextWait(OwnIdentity ownIdentity, String context, boolean wait) {
165 AddContextJob addContextJob = new AddContextJob(ownIdentity, context);
166 if (!updateJobs.contains(addContextJob)) {
167 logger.log(Level.FINER, "Adding Context Job: " + addContextJob);
169 updateJobs.put(addContextJob);
170 } catch (InterruptedException ie1) {
171 /* the queue is unbounded so it should never block. */
174 return addContextJob.waitForCompletion();
177 for (WebOfTrustUpdateJob updateJob : updateJobs) {
178 if (updateJob.equals(addContextJob)) {
179 return updateJob.waitForCompletion();
194 protected void serviceRun() {
195 while (!shouldStop()) {
197 WebOfTrustUpdateJob updateJob = updateJobs.take();
198 if (shouldStop() || (updateJob == stopJob)) {
201 logger.log(Level.FINE, "Running Trust Update Job: " + updateJob);
202 long startTime = System.currentTimeMillis();
204 long endTime = System.currentTimeMillis();
205 logger.log(Level.FINE, "Trust Update Job finished, took " + (endTime - startTime) + " ms.");
206 } catch (InterruptedException ie1) {
207 /* happens, ignore, loop. */
216 protected void serviceStop() {
218 updateJobs.put(stopJob);
219 } catch (InterruptedException ie1) {
220 /* the queue is unbounded so it should never block. */
225 * Base class for WebOfTrust update jobs.
227 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
229 private class WebOfTrustUpdateJob {
231 /** Object for synchronization. */
232 @SuppressWarnings("hiding")
233 private final Object syncObject = new Object();
235 /** Whether the job has finished. */
236 private boolean finished;
238 /** Whether the job was successful. */
239 private boolean success;
246 * Performs the actual update operation.
248 * The implementation of this class does nothing.
255 * Waits for completion of this job or stopping of the WebOfTrust
258 * @return {@code true} if this job finished successfully, {@code false}
261 * @see WebOfTrustUpdater#stop()
263 @SuppressWarnings("synthetic-access")
264 public boolean waitForCompletion() {
265 synchronized (syncObject) {
266 while (!finished && !shouldStop()) {
269 } catch (InterruptedException ie1) {
270 /* we’re looping, ignore. */
282 * Signals that this job has finished.
285 * {@code true} if this job finished successfully,
286 * {@code false} otherwise
288 protected void finish(boolean success) {
289 synchronized (syncObject) {
291 this.success = success;
292 syncObject.notifyAll();
299 * Base class for WebOfTrust trust update jobs.
301 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
303 private class WebOfTrustTrustUpdateJob extends WebOfTrustUpdateJob {
305 /** The identity giving the trust. */
306 protected final OwnIdentity truster;
308 /** The identity receiving the trust. */
309 protected final Identity trustee;
312 * Creates a new trust update job.
315 * The identity giving the trust
317 * The identity receiving the trust
319 @SuppressWarnings("synthetic-access")
320 public WebOfTrustTrustUpdateJob(OwnIdentity truster, Identity trustee) {
321 this.truster = truster;
322 this.trustee = trustee;
333 public boolean equals(Object object) {
334 if ((object == null) || !object.getClass().equals(getClass())) {
337 WebOfTrustTrustUpdateJob updateJob = (WebOfTrustTrustUpdateJob) object;
338 return ((truster == null) ? (updateJob.truster == null) : updateJob.truster.equals(truster)) && ((trustee == null) ? (updateJob.trustee == null) : updateJob.trustee.equals(trustee));
345 public int hashCode() {
346 return getClass().hashCode() ^ ((truster == null) ? 0 : truster.hashCode()) ^ ((trustee == null) ? 0 : trustee.hashCode());
353 public String toString() {
354 return String.format("%s[truster=%s,trustee=%s]", getClass().getSimpleName(), (truster == null) ? null : truster.getId(), (trustee == null) ? null : trustee.getId());
360 * Update job that sets the trust relation between two identities.
362 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
364 private class SetTrustJob extends WebOfTrustTrustUpdateJob {
366 /** The score of the relation. */
367 private final Integer score;
369 /** The comment of the relation. */
370 private final String comment;
373 * Creates a new set trust job.
376 * The identity giving the trust
378 * The identity receiving the trust
380 * The score of the trust (from -100 to 100, may be
381 * {@code null} to remote the trust relation completely)
383 * The comment of the trust relation
385 public SetTrustJob(OwnIdentity truster, Identity trustee, Integer score, String comment) {
386 super(truster, trustee);
388 this.comment = comment;
395 @SuppressWarnings("synthetic-access")
399 if (trustee instanceof DefaultIdentity) {
400 ((DefaultIdentity) trustee).setTrust(truster, new Trust(score, null, 0));
402 webOfTrustConnector.setTrust(truster, trustee, score, comment);
404 if (trustee instanceof DefaultIdentity) {
405 ((DefaultIdentity) trustee).setTrust(truster, null);
407 webOfTrustConnector.removeTrust(truster, trustee);
410 } catch (WebOfTrustException wote1) {
411 logger.log(Level.WARNING, "Could not set Trust value for " + truster + " -> " + trustee + " to " + score + " (" + comment + ")!", wote1);
419 * Update job that retrieves the trust relation between two identities.
421 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
423 private class GetTrustJob extends WebOfTrustTrustUpdateJob {
426 * Creates a new trust update job.
429 * The identity giving the trust
431 * The identity receiving the trust
433 public GetTrustJob(OwnIdentity truster, Identity trustee) {
434 super(truster, trustee);
441 @SuppressWarnings("synthetic-access")
444 Trust trust = webOfTrustConnector.getTrust(truster, trustee);
445 if (trustee instanceof DefaultIdentity) {
446 ((DefaultIdentity) trustee).setTrust(truster, trust);
449 } catch (PluginException pe1) {
450 logger.log(Level.WARNING, "Could not get Trust value for " + truster + " -> " + trustee + "!", pe1);
458 * Base class for context updates of an {@link OwnIdentity}.
460 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
462 private class WebOfTrustContextUpdateJob extends WebOfTrustUpdateJob {
464 /** The own identity whose contexts to manage. */
465 protected final OwnIdentity ownIdentity;
467 /** The context to update. */
468 protected final String context;
471 * Creates a new context update job.
474 * The own identity to update
476 * The context to update
478 @SuppressWarnings("synthetic-access")
479 public WebOfTrustContextUpdateJob(OwnIdentity ownIdentity, String context) {
480 Validation.begin().isNotNull("OwnIdentity", ownIdentity).isNotNull("Context", context).check();
481 this.ownIdentity = ownIdentity;
482 this.context = context;
493 public boolean equals(Object object) {
494 if ((object == null) || !object.getClass().equals(getClass())) {
497 WebOfTrustContextUpdateJob updateJob = (WebOfTrustContextUpdateJob) object;
498 return updateJob.ownIdentity.equals(ownIdentity) && updateJob.context.equals(context);
505 public int hashCode() {
506 return getClass().hashCode() ^ ownIdentity.hashCode() ^ context.hashCode();
513 public String toString() {
514 return String.format("%s[ownIdentity=%s,context=%s]", getClass().getSimpleName(), ownIdentity, context);
520 * Job that adds a context to an {@link OwnIdentity}.
522 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
524 private class AddContextJob extends WebOfTrustContextUpdateJob {
527 * Creates a new add-context job.
530 * The own identity whose contexts to manage
534 public AddContextJob(OwnIdentity ownIdentity, String context) {
535 super(ownIdentity, context);
542 @SuppressWarnings("synthetic-access")
545 webOfTrustConnector.addContext(ownIdentity, context);
546 ownIdentity.addContext(context);
548 } catch (PluginException pe1) {
549 logger.log(Level.WARNING, String.format("Could not add Context “%2$s” to Own Identity %1$s!", ownIdentity, context), pe1);