X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Fcore%2FCore.java;h=70758802bbf667f6ed933346822a056b1a616e38;hb=d5efb086bee8f103cbe90c7a953ffbb7ff27b689;hp=fcde6854053cfa14660f5664eb56379e505a24a5;hpb=a88e930a23b550dae75116d7759924d760941776;p=Sone.git diff --git a/src/main/java/net/pterodactylus/sone/core/Core.java b/src/main/java/net/pterodactylus/sone/core/Core.java index fcde685..7075880 100644 --- a/src/main/java/net/pterodactylus/sone/core/Core.java +++ b/src/main/java/net/pterodactylus/sone/core/Core.java @@ -1,5 +1,5 @@ /* - * Sone - Core.java - Copyright © 2010–2012 David Roden + * Sone - Core.java - Copyright © 2010–2013 David Roden * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +17,9 @@ package net.pterodactylus.sone.core; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; @@ -35,6 +38,18 @@ import java.util.logging.Logger; import net.pterodactylus.sone.core.Options.DefaultOption; import net.pterodactylus.sone.core.Options.Option; import net.pterodactylus.sone.core.Options.OptionWatcher; +import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent; +import net.pterodactylus.sone.core.event.MarkPostKnownEvent; +import net.pterodactylus.sone.core.event.MarkPostReplyKnownEvent; +import net.pterodactylus.sone.core.event.MarkSoneKnownEvent; +import net.pterodactylus.sone.core.event.NewPostFoundEvent; +import net.pterodactylus.sone.core.event.NewPostReplyFoundEvent; +import net.pterodactylus.sone.core.event.NewSoneFoundEvent; +import net.pterodactylus.sone.core.event.PostRemovedEvent; +import net.pterodactylus.sone.core.event.PostReplyRemovedEvent; +import net.pterodactylus.sone.core.event.SoneLockedEvent; +import net.pterodactylus.sone.core.event.SoneRemovedEvent; +import net.pterodactylus.sone.core.event.SoneUnlockedEvent; import net.pterodactylus.sone.data.Album; import net.pterodactylus.sone.data.Client; import net.pterodactylus.sone.data.Image; @@ -48,28 +63,35 @@ import net.pterodactylus.sone.data.Sone.ShowCustomAvatars; import net.pterodactylus.sone.data.Sone.SoneStatus; import net.pterodactylus.sone.data.TemporaryImage; import net.pterodactylus.sone.data.impl.PostImpl; +import net.pterodactylus.sone.data.impl.PostReplyImpl; import net.pterodactylus.sone.fcp.FcpInterface; import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired; import net.pterodactylus.sone.freenet.wot.Identity; -import net.pterodactylus.sone.freenet.wot.IdentityListener; import net.pterodactylus.sone.freenet.wot.IdentityManager; import net.pterodactylus.sone.freenet.wot.OwnIdentity; +import net.pterodactylus.sone.freenet.wot.event.IdentityAddedEvent; +import net.pterodactylus.sone.freenet.wot.event.IdentityRemovedEvent; +import net.pterodactylus.sone.freenet.wot.event.IdentityUpdatedEvent; +import net.pterodactylus.sone.freenet.wot.event.OwnIdentityAddedEvent; +import net.pterodactylus.sone.freenet.wot.event.OwnIdentityRemovedEvent; import net.pterodactylus.sone.main.SonePlugin; +import net.pterodactylus.sone.utils.IntegerRangePredicate; import net.pterodactylus.util.config.Configuration; import net.pterodactylus.util.config.ConfigurationException; import net.pterodactylus.util.logging.Logging; -import net.pterodactylus.util.number.Numbers; import net.pterodactylus.util.service.AbstractService; import net.pterodactylus.util.thread.NamedThreadFactory; import net.pterodactylus.util.thread.Ticker; -import net.pterodactylus.util.validation.EqualityValidator; -import net.pterodactylus.util.validation.IntegerRangeValidator; -import net.pterodactylus.util.validation.OrValidator; -import net.pterodactylus.util.validation.Validation; -import net.pterodactylus.util.version.Version; +import com.google.common.base.Optional; import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import com.google.common.collect.Collections2; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; +import com.google.common.primitives.Longs; +import com.google.inject.Inject; + import freenet.keys.FreenetURI; /** @@ -77,7 +99,7 @@ import freenet.keys.FreenetURI; * * @author David ‘Bombe’ Roden */ -public class Core extends AbstractService implements IdentityListener, UpdateListener, SoneProvider, PostProvider, SoneInsertListener, ImageInsertListener { +public class Core extends AbstractService implements SoneProvider, PostProvider { /** The logger. */ private static final Logger logger = Logging.getLogger(Core.class); @@ -91,8 +113,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis /** The preferences. */ private final Preferences preferences = new Preferences(options); - /** The core listener manager. */ - private final CoreListenerManager coreListenerManager = new CoreListenerManager(this); + /** The event bus. */ + private final EventBus eventBus; /** The configuration. */ private Configuration configuration; @@ -191,40 +213,20 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The identity manager * @param webOfTrustUpdater * The WebOfTrust updater + * @param eventBus + * The event bus */ - public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater) { + @Inject + public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus) { super("Sone Core"); this.configuration = configuration; this.freenetInterface = freenetInterface; this.identityManager = identityManager; this.soneDownloader = new SoneDownloader(this, freenetInterface); - this.imageInserter = new ImageInserter(this, freenetInterface); - this.updateChecker = new UpdateChecker(freenetInterface); + this.imageInserter = new ImageInserter(freenetInterface); + this.updateChecker = new UpdateChecker(eventBus, freenetInterface); this.webOfTrustUpdater = webOfTrustUpdater; - } - - // - // LISTENER MANAGEMENT - // - - /** - * Adds a new core listener. - * - * @param coreListener - * The listener to add - */ - public void addCoreListener(CoreListener coreListener) { - coreListenerManager.addListener(coreListener); - } - - /** - * Removes a core listener. - * - * @param coreListener - * The listener to remove - */ - public void removeCoreListener(CoreListener coreListener) { - coreListenerManager.removeListener(coreListener); + this.eventBus = eventBus; } // @@ -297,7 +299,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return The Sone rescuer for the given Sone */ public SoneRescuer getSoneRescuer(Sone sone) { - Validation.begin().isNotNull("Sone", sone).check().is("Local Sone", sone.isLocal()).check(); + checkNotNull(sone, "sone must not be null"); + checkArgument(sone.isLocal(), "sone must be local"); synchronized (sones) { SoneRescuer soneRescuer = soneRescuers.get(sone); if (soneRescuer == null) { @@ -360,7 +363,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis @Override public Sone getSone(String id, boolean create) { synchronized (sones) { - if (!sones.containsKey(id)) { + if (!sones.containsKey(id) && create) { Sone sone = new Sone(id, false); sones.put(id, sone); } @@ -416,7 +419,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis sone = new Sone(id, true); sones.put(id, sone); } - if (!sone.isLocal()) { + if ((sone != null) && !sone.isLocal()) { sone = new Sone(id, true); sones.put(id, sone); } @@ -501,7 +504,9 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return {@code true} if the target Sone is trusted by the origin Sone */ public boolean isSoneTrusted(Sone origin, Sone target) { - Validation.begin().isNotNull("Origin", origin).isNotNull("Target", target).check().isInstanceOf("Origin’s OwnIdentity", origin.getIdentity(), OwnIdentity.class).check(); + checkNotNull(origin, "origin must not be null"); + checkNotNull(target, "target must not be null"); + checkArgument(origin.getIdentity() instanceof OwnIdentity, "origin’s identity must be an OwnIdentity"); return trustedIdentities.containsKey(origin.getIdentity()) && trustedIdentities.get(origin.getIdentity()).contains(target.getIdentity()); } @@ -547,7 +552,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return All posts that have the given Sone as recipient */ public Set getDirectedPosts(Sone recipient) { - Validation.begin().isNotNull("Recipient", recipient).check(); + checkNotNull(recipient, "recipient must not be null"); Set directedPosts = new HashSet(); synchronized (posts) { for (Post post : posts.values()) { @@ -575,7 +580,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis synchronized (replies) { PostReply reply = replies.get(replyId); if (create && (reply == null)) { - reply = new PostReply(replyId); + reply = new PostReplyImpl(replyId); replies.put(replyId, reply); } return reply; @@ -779,7 +784,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis public void lockSone(Sone sone) { synchronized (lockedSones) { if (lockedSones.add(sone)) { - coreListenerManager.fireSoneLocked(sone); + eventBus.post(new SoneLockedEvent(sone)); } } } @@ -794,7 +799,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis public void unlockSone(Sone sone) { synchronized (lockedSones) { if (lockedSones.remove(sone)) { - coreListenerManager.fireSoneUnlocked(sone); + eventBus.post(new SoneUnlockedEvent(sone)); } } } @@ -819,13 +824,12 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis logger.log(Level.SEVERE, String.format("Could not convert the Identity’s URIs to Freenet URIs: %s, %s", ownIdentity.getInsertUri(), ownIdentity.getRequestUri()), mue1); return null; } - sone.setLatestEdition(Numbers.safeParseLong(ownIdentity.getProperty("Sone.LatestEdition"), (long) 0)); + sone.setLatestEdition(Optional.fromNullable(Longs.tryParse(ownIdentity.getProperty("Sone.LatestEdition"))).or(0L)); sone.setClient(new Client("Sone", SonePlugin.VERSION.toString())); sone.setKnown(true); /* TODO - load posts ’n stuff */ sones.put(ownIdentity.getId(), sone); - final SoneInserter soneInserter = new SoneInserter(this, freenetInterface, sone); - soneInserter.addSoneInsertListener(this); + final SoneInserter soneInserter = new SoneInserter(this, eventBus, freenetInterface, sone); soneInserters.put(sone, soneInserter); sone.setStatus(SoneStatus.idle); loadSone(sone); @@ -875,14 +879,14 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis final Sone sone = getRemoteSone(identity.getId(), true).setIdentity(identity); boolean newSone = sone.getRequestUri() == null; sone.setRequestUri(getSoneUri(identity.getRequestUri())); - sone.setLatestEdition(Numbers.safeParseLong(identity.getProperty("Sone.LatestEdition"), (long) 0)); + sone.setLatestEdition(Optional.fromNullable(Longs.tryParse(identity.getProperty("Sone.LatestEdition"))).or(0L)); if (newSone) { synchronized (knownSones) { newSone = !knownSones.contains(sone.getId()); } sone.setKnown(!newSone); if (newSone) { - coreListenerManager.fireNewSoneFound(sone); + eventBus.post(new NewSoneFoundEvent(sone)); for (Sone localSone : getLocalSones()) { if (localSone.getOptions().getBooleanOption("AutoFollow").get()) { followSone(localSone, sone); @@ -913,7 +917,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The ID of the Sone to follow */ public void followSone(Sone sone, String soneId) { - Validation.begin().isNotNull("Sone", sone).isNotNull("Sone ID", soneId).check(); + checkNotNull(sone, "sone must not be null"); + checkNotNull(soneId, "soneId must not be null"); Sone followedSone = getSone(soneId, true); if (followedSone == null) { logger.log(Level.INFO, String.format("Ignored Sone with invalid ID: %s", soneId)); @@ -934,7 +939,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The Sone that should be followed */ public void followSone(Sone sone, Sone followedSone) { - Validation.begin().isNotNull("Sone", sone).isNotNull("Followed Sone", followedSone).check(); + checkNotNull(sone, "sone must not be null"); + checkNotNull(followedSone, "followedSone must not be null"); sone.addFriend(followedSone.getId()); synchronized (soneFollowingTimes) { if (!soneFollowingTimes.containsKey(followedSone)) { @@ -964,7 +970,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The ID of the Sone being unfollowed */ public void unfollowSone(Sone sone, String soneId) { - Validation.begin().isNotNull("Sone", sone).isNotNull("Sone ID", soneId).check(); + checkNotNull(sone, "sone must not be null"); + checkNotNull(soneId, "soneId must not be null"); unfollowSone(sone, getSone(soneId, false)); } @@ -979,7 +986,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The Sone being unfollowed */ public void unfollowSone(Sone sone, Sone unfollowedSone) { - Validation.begin().isNotNull("Sone", sone).isNotNull("Unfollowed Sone", unfollowedSone).check(); + checkNotNull(sone, "sone must not be null"); + checkNotNull(unfollowedSone, "unfollowedSone must not be null"); sone.removeFriend(unfollowedSone.getId()); boolean unfollowedSoneStillFollowed = false; for (Sone localSone : getLocalSones()) { @@ -1004,7 +1012,10 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The trust value (from {@code -100} to {@code 100}) */ public void setTrust(Sone origin, Sone target, int trustValue) { - Validation.begin().isNotNull("Trust Origin", origin).check().isInstanceOf("Trust Origin", origin.getIdentity(), OwnIdentity.class).isNotNull("Trust Target", target).isLessOrEqual("Trust Value", trustValue, 100).isGreaterOrEqual("Trust Value", trustValue, -100).check(); + checkNotNull(origin, "origin must not be null"); + checkArgument(origin.getIdentity() instanceof OwnIdentity, "origin must be a local Sone"); + checkNotNull(target, "target must not be null"); + checkArgument((trustValue >= -100) && (trustValue <= 100), "trustValue must be within [-100, 100]"); webOfTrustUpdater.setTrust((OwnIdentity) origin.getIdentity(), target.getIdentity(), trustValue, preferences.getTrustComment()); } @@ -1017,7 +1028,9 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The trust target */ public void removeTrust(Sone origin, Sone target) { - Validation.begin().isNotNull("Trust Origin", origin).isNotNull("Trust Target", target).check().isInstanceOf("Trust Origin Identity", origin.getIdentity(), OwnIdentity.class).check(); + checkNotNull(origin, "origin must not be null"); + checkNotNull(target, "target must not be null"); + checkArgument(origin.getIdentity() instanceof OwnIdentity, "origin must be a local Sone"); webOfTrustUpdater.setTrust((OwnIdentity) origin.getIdentity(), target.getIdentity(), null, null); } @@ -1090,7 +1103,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis for (Post post : storedSone.getPosts()) { posts.remove(post.getId()); if (!sone.getPosts().contains(post)) { - coreListenerManager.firePostRemoved(post); + eventBus.post(new PostRemovedEvent(post)); } } } @@ -1103,7 +1116,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis knownPosts.add(post.getId()); post.setKnown(true); } else if (!knownPosts.contains(post.getId())) { - coreListenerManager.fireNewPostFound(post); + eventBus.post(new NewPostFoundEvent(post)); } } posts.put(post.getId(), post); @@ -1115,7 +1128,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis for (PostReply reply : storedSone.getReplies()) { replies.remove(reply.getId()); if (!sone.getReplies().contains(reply)) { - coreListenerManager.fireReplyRemoved(reply); + eventBus.post(new PostReplyRemovedEvent(reply)); } } } @@ -1128,7 +1141,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis knownReplies.add(reply.getId()); reply.setKnown(true); } else if (!knownReplies.contains(reply.getId())) { - coreListenerManager.fireNewReplyFound(reply); + eventBus.post(new NewPostReplyFoundEvent(reply)); } } replies.put(reply.getId(), reply); @@ -1205,7 +1218,6 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } sones.remove(sone.getId()); SoneInserter soneInserter = soneInserters.remove(sone); - soneInserter.removeSoneInsertListener(this); soneInserter.stop(); } webOfTrustUpdater.removeContext((OwnIdentity) sone.getIdentity(), "Sone"); @@ -1219,7 +1231,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis /** * Marks the given Sone as known. If the Sone was not {@link Post#isKnown() - * known} before, a {@link CoreListener#markSoneKnown(Sone)} event is fired. + * known} before, a {@link MarkSoneKnownEvent} is fired. * * @param sone * The Sone to mark as known @@ -1230,7 +1242,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis synchronized (knownSones) { knownSones.add(sone.getId()); } - coreListenerManager.fireMarkSoneKnown(sone); + eventBus.post(new MarkSoneKnownEvent(sone)); touchConfiguration(); } } @@ -1520,19 +1532,20 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return The created post */ public Post createPost(Sone sone, Sone recipient, long time, String text) { - Validation.begin().isNotNull("Text", text).check().isGreater("Text Length", text.length(), 0).check(); + checkNotNull(text, "text must not be null"); + checkArgument(text.trim().length() > 0, "text must not be empty"); if (!sone.isLocal()) { logger.log(Level.FINE, String.format("Tried to create post for non-local Sone: %s", sone)); return null; } - final Post post = new PostImpl(sone, time, text); + final Post post = new PostImpl(sone, time, text.trim()); if (recipient != null) { post.setRecipient(recipient); } synchronized (posts) { posts.put(post.getId(), post); } - coreListenerManager.fireNewPostFound(post); + eventBus.post(new NewPostFoundEvent(post)); sone.addPost(post); touchConfiguration(); localElementTicker.registerEvent(System.currentTimeMillis() + 10 * 1000, new Runnable() { @@ -1563,7 +1576,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis synchronized (posts) { posts.remove(post.getId()); } - coreListenerManager.firePostRemoved(post); + eventBus.post(new PostRemovedEvent(post)); markPostKnown(post); touchConfiguration(); } @@ -1578,7 +1591,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis public void markPostKnown(Post post) { post.setKnown(true); synchronized (knownPosts) { - coreListenerManager.fireMarkPostKnown(post); + eventBus.post(new MarkPostKnownEvent(post)); if (knownPosts.add(post.getId())) { touchConfiguration(); } @@ -1661,17 +1674,18 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return The created reply */ public PostReply createReply(Sone sone, Post post, long time, String text) { - Validation.begin().isNotNull("Text", text).check().isGreater("Text Length", text.trim().length(), 0).check(); + checkNotNull(text, "text must not be null"); + checkArgument(text.trim().length() > 0, "text must not be empty"); if (!sone.isLocal()) { logger.log(Level.FINE, String.format("Tried to create reply for non-local Sone: %s", sone)); return null; } - final PostReply reply = new PostReply(sone, post, System.currentTimeMillis(), text); + final PostReply reply = new PostReplyImpl(sone, post, System.currentTimeMillis(), text.trim()); synchronized (replies) { replies.put(reply.getId(), reply); } synchronized (knownReplies) { - coreListenerManager.fireNewReplyFound(reply); + eventBus.post(new NewPostReplyFoundEvent(reply)); } sone.addReply(reply); touchConfiguration(); @@ -1721,7 +1735,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis public void markReplyKnown(PostReply reply) { reply.setKnown(true); synchronized (knownReplies) { - coreListenerManager.fireMarkReplyKnown(reply); + eventBus.post(new MarkPostReplyKnownEvent(reply)); if (knownReplies.add(reply.getId())) { touchConfiguration(); } @@ -1771,7 +1785,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The album to remove */ public void deleteAlbum(Album album) { - Validation.begin().isNotNull("Album", album).check().is("Local Sone", album.getSone().isLocal()).check(); + checkNotNull(album, "album must not be null"); + checkArgument(album.getSone().isLocal(), "album’s Sone must be a local Sone"); if (!album.isEmpty()) { return; } @@ -1798,7 +1813,11 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return The newly created image */ public Image createImage(Sone sone, Album album, TemporaryImage temporaryImage) { - Validation.begin().isNotNull("Sone", sone).isNotNull("Album", album).isNotNull("Temporary Image", temporaryImage).check().is("Local Sone", sone.isLocal()).check().isEqual("Owner and Album Owner", sone, album.getSone()).check(); + checkNotNull(sone, "sone must not be null"); + checkNotNull(album, "album must not be null"); + checkNotNull(temporaryImage, "temporaryImage must not be null"); + checkArgument(sone.isLocal(), "sone must be a local Sone"); + checkArgument(sone.equals(album.getSone()), "album must belong to the given Sone"); Image image = new Image(temporaryImage.getId()).setSone(sone).setCreationTime(System.currentTimeMillis()); album.addImage(image); synchronized (images) { @@ -1817,7 +1836,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The image to delete */ public void deleteImage(Image image) { - Validation.begin().isNotNull("Image", image).check().is("Local Sone", image.getSone().isLocal()).check(); + checkNotNull(image, "image must not be null"); + checkArgument(image.getSone().isLocal(), "image must belong to a local Sone"); deleteTemporaryImage(image.getId()); image.getAlbum().removeImage(image); synchronized (images) { @@ -1851,7 +1871,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The temporary image to delete */ public void deleteTemporaryImage(TemporaryImage temporaryImage) { - Validation.begin().isNotNull("Temporary Image", temporaryImage).check(); + checkNotNull(temporaryImage, "temporaryImage must not be null"); deleteTemporaryImage(temporaryImage.getId()); } @@ -1862,7 +1882,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The ID of the temporary image to delete */ public void deleteTemporaryImage(String imageId) { - Validation.begin().isNotNull("Temporary Image ID", imageId).check(); + checkNotNull(imageId, "imageId must not be null"); synchronized (temporaryImages) { temporaryImages.remove(imageId); } @@ -1891,8 +1911,9 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis @Override public void serviceStart() { loadConfiguration(); - updateChecker.addUpdateListener(this); updateChecker.start(); + identityManager.start(); + webOfTrustUpdater.init(); webOfTrustUpdater.start(); } @@ -1922,7 +1943,6 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis public void serviceStop() { synchronized (sones) { for (Entry soneInserter : soneInserters.entrySet()) { - soneInserter.getValue().removeSoneInsertListener(this); soneInserter.getValue().stop(); saveSone(soneInserter.getKey()); } @@ -1930,8 +1950,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis saveConfiguration(); webOfTrustUpdater.stop(); updateChecker.stop(); - updateChecker.removeUpdateListener(this); soneDownloader.stop(); + identityManager.stop(); } // @@ -2168,7 +2188,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis @SuppressWarnings("unchecked") private void loadConfiguration() { /* create options. */ - options.addIntegerOption("InsertionDelay", new DefaultOption(60, new IntegerRangeValidator(0, Integer.MAX_VALUE), new OptionWatcher() { + options.addIntegerOption("InsertionDelay", new DefaultOption(60, new IntegerRangePredicate(0, Integer.MAX_VALUE), new OptionWatcher() { @Override public void optionChanged(Option option, Integer oldValue, Integer newValue) { @@ -2176,13 +2196,13 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } })); - options.addIntegerOption("PostsPerPage", new DefaultOption(10, new IntegerRangeValidator(1, Integer.MAX_VALUE))); - options.addIntegerOption("ImagesPerPage", new DefaultOption(9, new IntegerRangeValidator(1, Integer.MAX_VALUE))); - options.addIntegerOption("CharactersPerPost", new DefaultOption(400, new OrValidator(new IntegerRangeValidator(50, Integer.MAX_VALUE), new EqualityValidator(-1)))); - options.addIntegerOption("PostCutOffLength", new DefaultOption(200, new OrValidator(new IntegerRangeValidator(50, Integer.MAX_VALUE), new EqualityValidator(-1)))); + options.addIntegerOption("PostsPerPage", new DefaultOption(10, new IntegerRangePredicate(1, Integer.MAX_VALUE))); + options.addIntegerOption("ImagesPerPage", new DefaultOption(9, new IntegerRangePredicate(1, Integer.MAX_VALUE))); + options.addIntegerOption("CharactersPerPost", new DefaultOption(400, Predicates.or(new IntegerRangePredicate(50, Integer.MAX_VALUE), Predicates.equalTo(-1)))); + options.addIntegerOption("PostCutOffLength", new DefaultOption(200, Predicates.or(new IntegerRangePredicate(50, Integer.MAX_VALUE), Predicates.equalTo(-1)))); options.addBooleanOption("RequireFullAccess", new DefaultOption(false)); - options.addIntegerOption("PositiveTrust", new DefaultOption(75, new IntegerRangeValidator(0, 100))); - options.addIntegerOption("NegativeTrust", new DefaultOption(-25, new IntegerRangeValidator(-100, 100))); + options.addIntegerOption("PositiveTrust", new DefaultOption(75, new IntegerRangePredicate(0, 100))); + options.addIntegerOption("NegativeTrust", new DefaultOption(-25, new IntegerRangePredicate(-100, 100))); options.addStringOption("TrustComment", new DefaultOption("Set from Sone Web Interface")); options.addBooleanOption("ActivateFcpInterface", new DefaultOption(false, new OptionWatcher() { @@ -2315,15 +2335,15 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } } - // - // INTERFACE IdentityListener - // - /** - * {@inheritDoc} + * Notifies the core that a new {@link OwnIdentity} was added. + * + * @param ownIdentityAddedEvent + * The event */ - @Override - public void ownIdentityAdded(OwnIdentity ownIdentity) { + @Subscribe + public void ownIdentityAdded(OwnIdentityAddedEvent ownIdentityAddedEvent) { + OwnIdentity ownIdentity = ownIdentityAddedEvent.ownIdentity(); logger.log(Level.FINEST, String.format("Adding OwnIdentity: %s", ownIdentity)); if (ownIdentity.hasContext("Sone")) { trustedIdentities.put(ownIdentity, Collections.synchronizedSet(new HashSet())); @@ -2332,29 +2352,41 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } /** - * {@inheritDoc} + * Notifies the core that an {@link OwnIdentity} was removed. + * + * @param ownIdentityRemovedEvent + * The event */ - @Override - public void ownIdentityRemoved(OwnIdentity ownIdentity) { + @Subscribe + public void ownIdentityRemoved(OwnIdentityRemovedEvent ownIdentityRemovedEvent) { + OwnIdentity ownIdentity = ownIdentityRemovedEvent.ownIdentity(); logger.log(Level.FINEST, String.format("Removing OwnIdentity: %s", ownIdentity)); trustedIdentities.remove(ownIdentity); } /** - * {@inheritDoc} + * Notifies the core that a new {@link Identity} was added. + * + * @param identityAddedEvent + * The event */ - @Override - public void identityAdded(OwnIdentity ownIdentity, Identity identity) { + @Subscribe + public void identityAdded(IdentityAddedEvent identityAddedEvent) { + Identity identity = identityAddedEvent.identity(); logger.log(Level.FINEST, String.format("Adding Identity: %s", identity)); - trustedIdentities.get(ownIdentity).add(identity); + trustedIdentities.get(identityAddedEvent.ownIdentity()).add(identity); addRemoteSone(identity); } /** - * {@inheritDoc} + * Notifies the core that an {@link Identity} was updated. + * + * @param identityUpdatedEvent + * The event */ - @Override - public void identityUpdated(OwnIdentity ownIdentity, final Identity identity) { + @Subscribe + public void identityUpdated(IdentityUpdatedEvent identityUpdatedEvent) { + final Identity identity = identityUpdatedEvent.identity(); soneDownloaders.execute(new Runnable() { @Override @@ -2362,7 +2394,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis public void run() { Sone sone = getRemoteSone(identity.getId(), false); sone.setIdentity(identity); - sone.setLatestEdition(Numbers.safeParseLong(identity.getProperty("Sone.LatestEdition"), sone.getLatestEdition())); + sone.setLatestEdition(Optional.fromNullable(Longs.tryParse(identity.getProperty("Sone.LatestEdition"))).or(sone.getLatestEdition())); soneDownloader.addSone(sone); soneDownloader.fetchSone(sone); } @@ -2370,10 +2402,15 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } /** - * {@inheritDoc} + * Notifies the core that an {@link Identity} was removed. + * + * @param identityRemovedEvent + * The event */ - @Override - public void identityRemoved(OwnIdentity ownIdentity, Identity identity) { + @Subscribe + public void identityRemoved(IdentityRemovedEvent identityRemovedEvent) { + OwnIdentity ownIdentity = identityRemovedEvent.ownIdentity(); + Identity identity = identityRemovedEvent.identity(); trustedIdentities.get(ownIdentity).remove(identity); boolean foundIdentity = false; for (Entry> trustedIdentity : trustedIdentities.entrySet()) { @@ -2397,7 +2434,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis synchronized (knownPosts) { for (Post post : sone.getPosts()) { posts.remove(post.getId()); - coreListenerManager.firePostRemoved(post); + eventBus.post(new PostRemovedEvent(post)); } } } @@ -2405,451 +2442,28 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis synchronized (knownReplies) { for (PostReply reply : sone.getReplies()) { replies.remove(reply.getId()); - coreListenerManager.fireReplyRemoved(reply); + eventBus.post(new PostReplyRemovedEvent(reply)); } } } synchronized (sones) { sones.remove(identity.getId()); } - coreListenerManager.fireSoneRemoved(sone); - } - - // - // INTERFACE UpdateListener - // - - /** - * {@inheritDoc} - */ - @Override - public void updateFound(Version version, long releaseTime, long latestEdition) { - coreListenerManager.fireUpdateFound(version, releaseTime, latestEdition); - } - - // - // INTERFACE ImageInsertListener - // - - /** - * {@inheritDoc} - */ - @Override - public void insertStarted(Sone sone) { - coreListenerManager.fireSoneInserting(sone); - } - - /** - * {@inheritDoc} - */ - @Override - public void insertFinished(Sone sone, long insertDuration) { - coreListenerManager.fireSoneInserted(sone, insertDuration); + eventBus.post(new SoneRemovedEvent(sone)); } /** - * {@inheritDoc} - */ - @Override - public void insertAborted(Sone sone, Throwable cause) { - coreListenerManager.fireSoneInsertAborted(sone, cause); - } - - // - // SONEINSERTLISTENER METHODS - // - - /** - * {@inheritDoc} - */ - @Override - public void imageInsertStarted(Image image) { - logger.log(Level.WARNING, String.format("Image insert started for %s...", image)); - coreListenerManager.fireImageInsertStarted(image); - } - - /** - * {@inheritDoc} - */ - @Override - public void imageInsertAborted(Image image) { - logger.log(Level.WARNING, String.format("Image insert aborted for %s.", image)); - coreListenerManager.fireImageInsertAborted(image); - } - - /** - * {@inheritDoc} + * Deletes the temporary image. + * + * @param imageInsertFinishedEvent + * The event */ - @Override - public void imageInsertFinished(Image image, FreenetURI key) { - logger.log(Level.WARNING, String.format("Image insert finished for %s: %s", image, key)); - image.setKey(key.toString()); - deleteTemporaryImage(image.getId()); + @Subscribe + public void imageInsertFinished(ImageInsertFinishedEvent imageInsertFinishedEvent) { + logger.log(Level.WARNING, String.format("Image insert finished for %s: %s", imageInsertFinishedEvent.image(), imageInsertFinishedEvent.resultingUri())); + imageInsertFinishedEvent.image().setKey(imageInsertFinishedEvent.resultingUri().toString()); + deleteTemporaryImage(imageInsertFinishedEvent.image().getId()); touchConfiguration(); - coreListenerManager.fireImageInsertFinished(image); - } - - /** - * {@inheritDoc} - */ - @Override - public void imageInsertFailed(Image image, Throwable cause) { - logger.log(Level.WARNING, String.format("Image insert failed for %s." + image), cause); - coreListenerManager.fireImageInsertFailed(image, cause); - } - - /** - * Convenience interface for external classes that want to access the core’s - * configuration. - * - * @author David ‘Bombe’ Roden - */ - public static class Preferences { - - /** The wrapped options. */ - private final Options options; - - /** - * Creates a new preferences object wrapped around the given options. - * - * @param options - * The options to wrap - */ - public Preferences(Options options) { - this.options = options; - } - - /** - * Returns the insertion delay. - * - * @return The insertion delay - */ - public int getInsertionDelay() { - return options.getIntegerOption("InsertionDelay").get(); - } - - /** - * Validates the given insertion delay. - * - * @param insertionDelay - * The insertion delay to validate - * @return {@code true} if the given insertion delay was valid, - * {@code false} otherwise - */ - public boolean validateInsertionDelay(Integer insertionDelay) { - return options.getIntegerOption("InsertionDelay").validate(insertionDelay); - } - - /** - * Sets the insertion delay - * - * @param insertionDelay - * The new insertion delay, or {@code null} to restore it to - * the default value - * @return This preferences - */ - public Preferences setInsertionDelay(Integer insertionDelay) { - options.getIntegerOption("InsertionDelay").set(insertionDelay); - return this; - } - - /** - * Returns the number of posts to show per page. - * - * @return The number of posts to show per page - */ - public int getPostsPerPage() { - return options.getIntegerOption("PostsPerPage").get(); - } - - /** - * Validates the number of posts per page. - * - * @param postsPerPage - * The number of posts per page - * @return {@code true} if the number of posts per page was valid, - * {@code false} otherwise - */ - public boolean validatePostsPerPage(Integer postsPerPage) { - return options.getIntegerOption("PostsPerPage").validate(postsPerPage); - } - - /** - * Sets the number of posts to show per page. - * - * @param postsPerPage - * The number of posts to show per page - * @return This preferences object - */ - public Preferences setPostsPerPage(Integer postsPerPage) { - options.getIntegerOption("PostsPerPage").set(postsPerPage); - return this; - } - - /** - * Returns the number of images to show per page. - * - * @return The number of images to show per page - */ - public int getImagesPerPage() { - return options.getIntegerOption("ImagesPerPage").get(); - } - - /** - * Validates the number of images per page. - * - * @param imagesPerPage - * The number of images per page - * @return {@code true} if the number of images per page was valid, - * {@code false} otherwise - */ - public boolean validateImagesPerPage(Integer imagesPerPage) { - return options.getIntegerOption("ImagesPerPage").validate(imagesPerPage); - } - - /** - * Sets the number of images per page. - * - * @param imagesPerPage - * The number of images per page - * @return This preferences object - */ - public Preferences setImagesPerPage(Integer imagesPerPage) { - options.getIntegerOption("ImagesPerPage").set(imagesPerPage); - return this; - } - - /** - * Returns the number of characters per post, or -1 if the - * posts should not be cut off. - * - * @return The numbers of characters per post - */ - public int getCharactersPerPost() { - return options.getIntegerOption("CharactersPerPost").get(); - } - - /** - * Validates the number of characters per post. - * - * @param charactersPerPost - * The number of characters per post - * @return {@code true} if the number of characters per post was valid, - * {@code false} otherwise - */ - public boolean validateCharactersPerPost(Integer charactersPerPost) { - return options.getIntegerOption("CharactersPerPost").validate(charactersPerPost); - } - - /** - * Sets the number of characters per post. - * - * @param charactersPerPost - * The number of characters per post, or -1 to - * not cut off the posts - * @return This preferences objects - */ - public Preferences setCharactersPerPost(Integer charactersPerPost) { - options.getIntegerOption("CharactersPerPost").set(charactersPerPost); - return this; - } - - /** - * Returns the number of characters the shortened post should have. - * - * @return The number of characters of the snippet - */ - public int getPostCutOffLength() { - return options.getIntegerOption("PostCutOffLength").get(); - } - - /** - * Validates the number of characters after which to cut off the post. - * - * @param postCutOffLength - * The number of characters of the snippet - * @return {@code true} if the number of characters of the snippet is - * valid, {@code false} otherwise - */ - public boolean validatePostCutOffLength(Integer postCutOffLength) { - return options.getIntegerOption("PostCutOffLength").validate(postCutOffLength); - } - - /** - * Sets the number of characters the shortened post should have. - * - * @param postCutOffLength - * The number of characters of the snippet - * @return This preferences - */ - public Preferences setPostCutOffLength(Integer postCutOffLength) { - options.getIntegerOption("PostCutOffLength").set(postCutOffLength); - return this; - } - - /** - * Returns whether Sone requires full access to be even visible. - * - * @return {@code true} if Sone requires full access, {@code false} - * otherwise - */ - public boolean isRequireFullAccess() { - return options.getBooleanOption("RequireFullAccess").get(); - } - - /** - * Sets whether Sone requires full access to be even visible. - * - * @param requireFullAccess - * {@code true} if Sone requires full access, {@code false} - * otherwise - */ - public void setRequireFullAccess(Boolean requireFullAccess) { - options.getBooleanOption("RequireFullAccess").set(requireFullAccess); - } - - /** - * Returns the positive trust. - * - * @return The positive trust - */ - public int getPositiveTrust() { - return options.getIntegerOption("PositiveTrust").get(); - } - - /** - * Validates the positive trust. - * - * @param positiveTrust - * The positive trust to validate - * @return {@code true} if the positive trust was valid, {@code false} - * otherwise - */ - public boolean validatePositiveTrust(Integer positiveTrust) { - return options.getIntegerOption("PositiveTrust").validate(positiveTrust); - } - - /** - * Sets the positive trust. - * - * @param positiveTrust - * The new positive trust, or {@code null} to restore it to - * the default vlaue - * @return This preferences - */ - public Preferences setPositiveTrust(Integer positiveTrust) { - options.getIntegerOption("PositiveTrust").set(positiveTrust); - return this; - } - - /** - * Returns the negative trust. - * - * @return The negative trust - */ - public int getNegativeTrust() { - return options.getIntegerOption("NegativeTrust").get(); - } - - /** - * Validates the negative trust. - * - * @param negativeTrust - * The negative trust to validate - * @return {@code true} if the negative trust was valid, {@code false} - * otherwise - */ - public boolean validateNegativeTrust(Integer negativeTrust) { - return options.getIntegerOption("NegativeTrust").validate(negativeTrust); - } - - /** - * Sets the negative trust. - * - * @param negativeTrust - * The negative trust, or {@code null} to restore it to the - * default value - * @return The preferences - */ - public Preferences setNegativeTrust(Integer negativeTrust) { - options.getIntegerOption("NegativeTrust").set(negativeTrust); - return this; - } - - /** - * Returns the trust comment. This is the comment that is set in the web - * of trust when a trust value is assigned to an identity. - * - * @return The trust comment - */ - public String getTrustComment() { - return options.getStringOption("TrustComment").get(); - } - - /** - * Sets the trust comment. - * - * @param trustComment - * The trust comment, or {@code null} to restore it to the - * default value - * @return This preferences - */ - public Preferences setTrustComment(String trustComment) { - options.getStringOption("TrustComment").set(trustComment); - return this; - } - - /** - * Returns whether the {@link FcpInterface FCP interface} is currently - * active. - * - * @see FcpInterface#setActive(boolean) - * @return {@code true} if the FCP interface is currently active, - * {@code false} otherwise - */ - public boolean isFcpInterfaceActive() { - return options.getBooleanOption("ActivateFcpInterface").get(); - } - - /** - * Sets whether the {@link FcpInterface FCP interface} is currently - * active. - * - * @see FcpInterface#setActive(boolean) - * @param fcpInterfaceActive - * {@code true} to activate the FCP interface, {@code false} - * to deactivate the FCP interface - * @return This preferences object - */ - public Preferences setFcpInterfaceActive(boolean fcpInterfaceActive) { - options.getBooleanOption("ActivateFcpInterface").set(fcpInterfaceActive); - return this; - } - - /** - * Returns the action level for which full access to the FCP interface - * is required. - * - * @return The action level for which full access to the FCP interface - * is required - */ - public FullAccessRequired getFcpFullAccessRequired() { - return FullAccessRequired.values()[options.getIntegerOption("FcpFullAccessRequired").get()]; - } - - /** - * Sets the action level for which full access to the FCP interface is - * required - * - * @param fcpFullAccessRequired - * The action level - * @return This preferences - */ - public Preferences setFcpFullAccessRequired(FullAccessRequired fcpFullAccessRequired) { - options.getIntegerOption("FcpFullAccessRequired").set((fcpFullAccessRequired != null) ? fcpFullAccessRequired.ordinal() : null); - return this; - } - } }