X-Git-Url: https://git.pterodactylus.net/?p=Sone.git;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Fcore%2FCore.java;h=e3fdd1975a06022cfaba1a4556d0740f736bb046;hp=7a978420a45a219c46526afab4cd19b4fe6f89de;hb=864f0802a2ae1cfaf4f94b3c29292aec31be1081;hpb=7b1a3e4378a632ad4b9e32373921cfad4fd91e8d diff --git a/src/main/java/net/pterodactylus/sone/core/Core.java b/src/main/java/net/pterodactylus/sone/core/Core.java index 7a97842..e3fdd19 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 David Roden + * Sone - Core.java - Copyright © 2010–2012 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 @@ -24,8 +24,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; @@ -40,12 +40,13 @@ import net.pterodactylus.sone.data.Image; import net.pterodactylus.sone.data.Post; import net.pterodactylus.sone.data.PostReply; import net.pterodactylus.sone.data.Profile; +import net.pterodactylus.sone.data.Profile.Field; import net.pterodactylus.sone.data.Reply; import net.pterodactylus.sone.data.Sone; -import net.pterodactylus.sone.data.TemporaryImage; -import net.pterodactylus.sone.data.Profile.Field; 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.fcp.FcpInterface; import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired; import net.pterodactylus.sone.freenet.wot.Identity; @@ -53,7 +54,6 @@ 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.Trust; -import net.pterodactylus.sone.freenet.wot.WebOfTrustException; import net.pterodactylus.sone.main.SonePlugin; import net.pterodactylus.util.config.Configuration; import net.pterodactylus.util.config.ConfigurationException; @@ -111,6 +111,9 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis /** The update checker. */ private final UpdateChecker updateChecker; + /** The trust updater. */ + private final WebOfTrustUpdater webOfTrustUpdater; + /** The FCP interface. */ private volatile FcpInterface fcpInterface; @@ -131,56 +134,45 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis /** All local Sones. */ /* synchronize access on this on itself. */ - private Map localSones = new HashMap(); + private final Map localSones = new HashMap(); /** All remote Sones. */ /* synchronize access on this on itself. */ - private Map remoteSones = new HashMap(); - - /** All new Sones. */ - private Set newSones = new HashSet(); + private final Map remoteSones = new HashMap(); /** All known Sones. */ - /* synchronize access on {@link #newSones}. */ - private Set knownSones = new HashSet(); + private final Set knownSones = new HashSet(); /** All posts. */ - private Map posts = new HashMap(); - - /** All new posts. */ - private Set newPosts = new HashSet(); + private final Map posts = new HashMap(); /** All known posts. */ - /* synchronize access on {@link #newPosts}. */ - private Set knownPosts = new HashSet(); + private final Set knownPosts = new HashSet(); /** All replies. */ - private Map replies = new HashMap(); - - /** All new replies. */ - private Set newReplies = new HashSet(); + private final Map replies = new HashMap(); /** All known replies. */ - private Set knownReplies = new HashSet(); + private final Set knownReplies = new HashSet(); /** All bookmarked posts. */ /* synchronize access on itself. */ - private Set bookmarkedPosts = new HashSet(); + private final Set bookmarkedPosts = new HashSet(); /** Trusted identities, sorted by own identities. */ - private Map> trustedIdentities = Collections.synchronizedMap(new HashMap>()); + private final Map> trustedIdentities = Collections.synchronizedMap(new HashMap>()); /** All known albums. */ - private Map albums = new HashMap(); + private final Map albums = new HashMap(); /** All known images. */ - private Map images = new HashMap(); + private final Map images = new HashMap(); /** All temporary images. */ - private Map temporaryImages = new HashMap(); + private final Map temporaryImages = new HashMap(); /** Ticker for threads that mark own elements as known. */ - private Ticker localElementTicker = new Ticker(); + private final Ticker localElementTicker = new Ticker(); /** The time the configuration was last touched. */ private volatile long lastConfigurationUpdate; @@ -194,8 +186,10 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The freenet interface * @param identityManager * The identity manager + * @param webOfTrustUpdater + * The WebOfTrust updater */ - public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager) { + public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater) { super("Sone Core"); this.configuration = configuration; this.freenetInterface = freenetInterface; @@ -203,6 +197,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis this.soneDownloader = new SoneDownloader(this, freenetInterface); this.imageInserter = new ImageInserter(this, freenetInterface); this.updateChecker = new UpdateChecker(freenetInterface); + this.webOfTrustUpdater = webOfTrustUpdater; } // @@ -504,19 +499,6 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } /** - * Returns whether the Sone with the given ID is a new Sone. - * - * @param soneId - * The ID of the sone to check for - * @return {@code true} if the given Sone is new, false otherwise - */ - public boolean isNewSone(String soneId) { - synchronized (newSones) { - return !knownSones.contains(soneId) && newSones.contains(soneId); - } - } - - /** * Returns whether the given Sone has been modified. * * @param sone @@ -585,7 +567,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis synchronized (posts) { Post post = posts.get(postId); if ((post == null) && create) { - post = new Post(postId); + post = new PostImpl(postId); posts.put(postId, post); } return post; @@ -593,20 +575,6 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } /** - * Returns whether the given post ID is new. - * - * @param postId - * The post ID - * @return {@code true} if the post is considered to be new, {@code false} - * otherwise - */ - public boolean isNewPost(String postId) { - synchronized (newPosts) { - return !knownPosts.contains(postId) && newPosts.contains(postId); - } - } - - /** * Returns all posts that have the given Sone as recipient. * * @see Post#getRecipient() @@ -684,20 +652,6 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } /** - * Returns whether the reply with the given ID is new. - * - * @param replyId - * The ID of the reply to check - * @return {@code true} if the reply is considered to be new, {@code false} - * otherwise - */ - public boolean isNewReply(String replyId) { - synchronized (newReplies) { - return !knownReplies.contains(replyId) && newReplies.contains(replyId); - } - } - - /** * Returns all Sones that have liked the given post. * * @param post @@ -910,11 +864,12 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis try { sone = getLocalSone(ownIdentity.getId()).setIdentity(ownIdentity).setInsertUri(new FreenetURI(ownIdentity.getInsertUri())).setRequestUri(new FreenetURI(ownIdentity.getRequestUri())); } catch (MalformedURLException mue1) { - logger.log(Level.SEVERE, "Could not convert the Identity’s URIs to Freenet URIs: " + ownIdentity.getInsertUri() + ", " + ownIdentity.getRequestUri(), mue1); + 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.setClient(new Client("Sone", SonePlugin.VERSION.toString())); + sone.setKnown(true); /* TODO - load posts ’n stuff */ localSones.put(ownIdentity.getId(), sone); final SoneInserter soneInserter = new SoneInserter(this, freenetInterface, sone); @@ -935,10 +890,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return The created Sone */ public Sone createSone(OwnIdentity ownIdentity) { - try { - ownIdentity.addContext("Sone"); - } catch (WebOfTrustException wote1) { - logger.log(Level.SEVERE, "Could not add “Sone” context to own identity: " + ownIdentity, wote1); + if (!webOfTrustUpdater.addContextWait(ownIdentity, "Sone")) { + logger.log(Level.SEVERE, String.format("Could not add “Sone” context to own identity: %s", ownIdentity)); return null; } Sone sone = addLocalSone(ownIdentity); @@ -972,12 +925,10 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis sone.setRequestUri(getSoneUri(identity.getRequestUri())); sone.setLatestEdition(Numbers.safeParseLong(identity.getProperty("Sone.LatestEdition"), (long) 0)); if (newSone) { - synchronized (newSones) { + synchronized (knownSones) { newSone = !knownSones.contains(sone.getId()); - if (newSone) { - newSones.add(sone.getId()); - } } + sone.setKnown(!newSone); if (newSone) { coreListenerManager.fireNewSoneFound(sone); for (Sone localSone : getLocalSones()) { @@ -1103,9 +1054,10 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ public Trust getTrust(Sone origin, Sone target) { if (!isLocalSone(origin)) { - logger.log(Level.WARNING, "Tried to get trust from remote Sone: %s", origin); + logger.log(Level.WARNING, String.format("Tried to get trust from remote Sone: %s", origin)); return null; } + webOfTrustUpdater.getTrust((OwnIdentity) origin.getIdentity(), target.getIdentity()); return target.getIdentity().getTrust((OwnIdentity) origin.getIdentity()); } @@ -1121,11 +1073,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ 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(); - try { - ((OwnIdentity) origin.getIdentity()).setTrust(target.getIdentity(), trustValue, preferences.getTrustComment()); - } catch (WebOfTrustException wote1) { - logger.log(Level.WARNING, "Could not set trust for Sone: " + target, wote1); - } + webOfTrustUpdater.setTrust((OwnIdentity) origin.getIdentity(), target.getIdentity(), trustValue, preferences.getTrustComment()); } /** @@ -1138,11 +1086,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ 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(); - try { - ((OwnIdentity) origin.getIdentity()).removeTrust(target.getIdentity()); - } catch (WebOfTrustException wote1) { - logger.log(Level.WARNING, "Could not remove trust for Sone: " + target, wote1); - } + webOfTrustUpdater.setTrust((OwnIdentity) origin.getIdentity(), target.getIdentity(), null, null); } /** @@ -1206,7 +1150,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis if (hasSone(sone.getId())) { Sone storedSone = getSone(sone.getId()); if (!soneRescueMode && !(sone.getTime() > storedSone.getTime())) { - logger.log(Level.FINE, "Downloaded Sone %s is not newer than stored Sone %s.", new Object[] { sone, storedSone }); + logger.log(Level.FINE, String.format("Downloaded Sone %s is not newer than stored Sone %s.", sone, storedSone)); return; } synchronized (posts) { @@ -1219,14 +1163,14 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } } List storedPosts = storedSone.getPosts(); - synchronized (newPosts) { + synchronized (knownPosts) { for (Post post : sone.getPosts()) { - post.setSone(storedSone); + post.setSone(storedSone).setKnown(knownPosts.contains(post.getId())); if (!storedPosts.contains(post)) { if (post.getTime() < getSoneFollowingTime(sone)) { knownPosts.add(post.getId()); } else if (!knownPosts.contains(post.getId())) { - newPosts.add(post.getId()); + sone.setKnown(false); coreListenerManager.fireNewPostFound(post); } } @@ -1244,14 +1188,14 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } } Set storedReplies = storedSone.getReplies(); - synchronized (newReplies) { + synchronized (knownReplies) { for (PostReply reply : sone.getReplies()) { - reply.setSone(storedSone); + reply.setSone(storedSone).setKnown(knownReplies.contains(reply.getId())); if (!storedReplies.contains(reply)) { if (reply.getTime() < getSoneFollowingTime(sone)) { knownReplies.add(reply.getId()); } else if (!knownReplies.contains(reply.getId())) { - newReplies.add(reply.getId()); + reply.setKnown(false); coreListenerManager.fireNewReplyFound(reply); } } @@ -1319,12 +1263,12 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ public void deleteSone(Sone sone) { if (!(sone.getIdentity() instanceof OwnIdentity)) { - logger.log(Level.WARNING, "Tried to delete Sone of non-own identity: %s", sone); + logger.log(Level.WARNING, String.format("Tried to delete Sone of non-own identity: %s", sone)); return; } synchronized (localSones) { if (!localSones.containsKey(sone.getId())) { - logger.log(Level.WARNING, "Tried to delete non-local Sone: %s", sone); + logger.log(Level.WARNING, String.format("Tried to delete non-local Sone: %s", sone)); return; } localSones.remove(sone.getId()); @@ -1332,12 +1276,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis soneInserter.removeSoneInsertListener(this); soneInserter.stop(); } - try { - ((OwnIdentity) sone.getIdentity()).removeContext("Sone"); - ((OwnIdentity) sone.getIdentity()).removeProperty("Sone.LatestEdition"); - } catch (WebOfTrustException wote1) { - logger.log(Level.WARNING, "Could not remove context and properties from Sone: " + sone, wote1); - } + webOfTrustUpdater.removeContext((OwnIdentity) sone.getIdentity(), "Sone"); + webOfTrustUpdater.removeProperty((OwnIdentity) sone.getIdentity(), "Sone.LatestEdition"); try { configuration.getLongValue("Sone/" + sone.getId() + "/Time").setValue(null); } catch (ConfigurationException ce1) { @@ -1346,19 +1286,20 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } /** - * Marks the given Sone as known. If the Sone was {@link #isNewPost(String) - * new} before, a {@link CoreListener#markSoneKnown(Sone)} event is fired. + * Marks the given Sone as known. If the Sone was not {@link Post#isKnown() + * known} before, a {@link CoreListener#markSoneKnown(Sone)} event is fired. * * @param sone * The Sone to mark as known */ public void markSoneKnown(Sone sone) { - synchronized (newSones) { - if (newSones.remove(sone.getId())) { + if (!sone.isKnown()) { + sone.setKnown(true); + synchronized (knownSones) { knownSones.add(sone.getId()); - coreListenerManager.fireMarkSoneKnown(sone); - touchConfiguration(); } + coreListenerManager.fireMarkSoneKnown(sone); + touchConfiguration(); } } @@ -1371,7 +1312,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ public void loadSone(Sone sone) { if (!isLocalSone(sone)) { - logger.log(Level.FINE, "Tried to load non-local Sone: %s", sone); + logger.log(Level.FINE, String.format("Tried to load non-local Sone: %s", sone)); return; } @@ -1503,12 +1444,14 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis if (albumParentId != null) { Album parentAlbum = getAlbum(albumParentId, false); if (parentAlbum == null) { - logger.log(Level.WARNING, "Invalid parent album ID: " + albumParentId); + logger.log(Level.WARNING, String.format("Invalid parent album ID: %s", albumParentId)); return; } parentAlbum.addAlbum(album); } else { - topLevelAlbums.add(album); + if (!topLevelAlbums.contains(album)) { + topLevelAlbums.add(album); + } } } @@ -1569,17 +1512,17 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis sone.setAlbums(topLevelAlbums); soneInserters.get(sone).setLastInsertFingerprint(lastInsertFingerprint); } - synchronized (newSones) { + synchronized (knownSones) { for (String friend : friends) { knownSones.add(friend); } } - synchronized (newPosts) { + synchronized (knownPosts) { for (Post post : posts) { knownPosts.add(post.getId()); } } - synchronized (newReplies) { + synchronized (knownReplies) { for (PostReply reply : replies) { knownReplies.add(reply.getId()); } @@ -1646,20 +1589,17 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ public Post createPost(Sone sone, Sone recipient, long time, String text) { if (!isLocalSone(sone)) { - logger.log(Level.FINE, "Tried to create post for non-local Sone: %s", sone); + logger.log(Level.FINE, String.format("Tried to create post for non-local Sone: %s", sone)); return null; } - final Post post = new Post(sone, time, text); + final Post post = new PostImpl(sone, time, text); if (recipient != null) { post.setRecipient(recipient); } synchronized (posts) { posts.put(post.getId(), post); } - synchronized (newPosts) { - newPosts.add(post.getId()); - coreListenerManager.fireNewPostFound(post); - } + coreListenerManager.fireNewPostFound(post); sone.addPost(post); touchConfiguration(); localElementTicker.registerEvent(System.currentTimeMillis() + 10 * 1000, new Runnable() { @@ -1683,7 +1623,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ public void deletePost(Post post) { if (!isLocalSone(post.getSone())) { - logger.log(Level.WARNING, "Tried to delete post of non-local Sone: %s", post.getSone()); + logger.log(Level.WARNING, String.format("Tried to delete post of non-local Sone: %s", post.getSone())); return; } post.getSone().removePost(post); @@ -1691,28 +1631,28 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis posts.remove(post.getId()); } coreListenerManager.firePostRemoved(post); - synchronized (newPosts) { - markPostKnown(post); - knownPosts.remove(post.getId()); - } + markPostKnown(post); touchConfiguration(); } /** - * Marks the given post as known, if it is currently a new post (according - * to {@link #isNewPost(String)}). + * Marks the given post as known, if it is currently not a known post + * (according to {@link Post#isKnown()}). * * @param post * The post to mark as known */ public void markPostKnown(Post post) { - synchronized (newPosts) { - newPosts.remove(post.getId()); + post.setKnown(true); + synchronized (knownPosts) { + coreListenerManager.fireMarkPostKnown(post); if (knownPosts.add(post.getId())) { - coreListenerManager.fireMarkPostKnown(post); touchConfiguration(); } } + for (PostReply reply : getReplies(post)) { + markReplyKnown(reply); + } } /** @@ -1789,15 +1729,14 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ public PostReply createReply(Sone sone, Post post, long time, String text) { if (!isLocalSone(sone)) { - logger.log(Level.FINE, "Tried to create reply for non-local Sone: %s", sone); + 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); synchronized (replies) { replies.put(reply.getId(), reply); } - synchronized (newReplies) { - newReplies.add(reply.getId()); + synchronized (knownReplies) { coreListenerManager.fireNewReplyFound(reply); } sone.addReply(reply); @@ -1824,13 +1763,13 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis public void deleteReply(PostReply reply) { Sone sone = reply.getSone(); if (!isLocalSone(sone)) { - logger.log(Level.FINE, "Tried to delete non-local reply: %s", reply); + logger.log(Level.FINE, String.format("Tried to delete non-local reply: %s", reply)); return; } synchronized (replies) { replies.remove(reply.getId()); } - synchronized (newReplies) { + synchronized (knownReplies) { markReplyKnown(reply); knownReplies.remove(reply.getId()); } @@ -1839,17 +1778,17 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } /** - * Marks the given reply as known, if it is currently a new reply (according - * to {@link #isNewReply(String)}). + * Marks the given reply as known, if it is currently not a known reply + * (according to {@link Reply#isKnown()}). * * @param reply * The reply to mark as known */ public void markReplyKnown(PostReply reply) { - synchronized (newReplies) { - newReplies.remove(reply.getId()); + reply.setKnown(true); + synchronized (knownReplies) { + coreListenerManager.fireMarkReplyKnown(reply); if (knownReplies.add(reply.getId())) { - coreListenerManager.fireMarkReplyKnown(reply); touchConfiguration(); } } @@ -1910,7 +1849,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis synchronized (albums) { albums.remove(album.getId()); } - saveSone(album.getSone()); + touchConfiguration(); } /** @@ -1950,7 +1889,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis synchronized (images) { images.remove(image.getId()); } - saveSone(image.getSone()); + touchConfiguration(); } /** @@ -2020,6 +1959,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis loadConfiguration(); updateChecker.addUpdateListener(this); updateChecker.start(); + webOfTrustUpdater.start(); } /** @@ -2052,6 +1992,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis soneInserter.stop(); } } + webOfTrustUpdater.stop(); updateChecker.stop(); updateChecker.removeUpdateListener(this); soneDownloader.stop(); @@ -2070,15 +2011,15 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ private synchronized void saveSone(Sone sone) { if (!isLocalSone(sone)) { - logger.log(Level.FINE, "Tried to save non-local Sone: %s", sone); + logger.log(Level.FINE, String.format("Tried to save non-local Sone: %s", sone)); return; } if (!(sone.getIdentity() instanceof OwnIdentity)) { - logger.log(Level.WARNING, "Local Sone without OwnIdentity found, refusing to save: %s", sone); + logger.log(Level.WARNING, String.format("Local Sone without OwnIdentity found, refusing to save: %s", sone)); return; } - logger.log(Level.INFO, "Saving Sone: %s", sone); + logger.log(Level.INFO, String.format("Saving Sone: %s", sone)); try { /* save Sone into configuration. */ String sonePrefix = "Sone/" + sone.getId(); @@ -2191,13 +2132,11 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis configuration.save(); - ((OwnIdentity) sone.getIdentity()).setProperty("Sone.LatestEdition", String.valueOf(sone.getLatestEdition())); + webOfTrustUpdater.setProperty((OwnIdentity) sone.getIdentity(), "Sone.LatestEdition", String.valueOf(sone.getLatestEdition())); - logger.log(Level.INFO, "Sone %s saved.", sone); + logger.log(Level.INFO, String.format("Sone %s saved.", sone)); } catch (ConfigurationException ce1) { - logger.log(Level.WARNING, "Could not save Sone: " + sone, ce1); - } catch (WebOfTrustException wote1) { - logger.log(Level.WARNING, "Could not set WoT property for Sone: " + sone, wote1); + logger.log(Level.WARNING, String.format("Could not save Sone: %s", sone), ce1); } } @@ -2218,6 +2157,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis configuration.getIntValue("Option/ConfigurationVersion").setValue(0); configuration.getIntValue("Option/InsertionDelay").setValue(options.getIntegerOption("InsertionDelay").getReal()); configuration.getIntValue("Option/PostsPerPage").setValue(options.getIntegerOption("PostsPerPage").getReal()); + configuration.getIntValue("Option/ImagesPerPage").setValue(options.getIntegerOption("ImagesPerPage").getReal()); configuration.getIntValue("Option/CharactersPerPost").setValue(options.getIntegerOption("CharactersPerPost").getReal()); configuration.getIntValue("Option/PostCutOffLength").setValue(options.getIntegerOption("PostCutOffLength").getReal()); configuration.getBooleanValue("Option/RequireFullAccess").setValue(options.getBooleanOption("RequireFullAccess").getReal()); @@ -2226,13 +2166,10 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis configuration.getStringValue("Option/TrustComment").setValue(options.getStringOption("TrustComment").getReal()); configuration.getBooleanValue("Option/ActivateFcpInterface").setValue(options.getBooleanOption("ActivateFcpInterface").getReal()); configuration.getIntValue("Option/FcpFullAccessRequired").setValue(options.getIntegerOption("FcpFullAccessRequired").getReal()); - configuration.getBooleanValue("Option/SoneRescueMode").setValue(options.getBooleanOption("SoneRescueMode").getReal()); - configuration.getBooleanValue("Option/ClearOnNextRestart").setValue(options.getBooleanOption("ClearOnNextRestart").getReal()); - configuration.getBooleanValue("Option/ReallyClearOnNextRestart").setValue(options.getBooleanOption("ReallyClearOnNextRestart").getReal()); /* save known Sones. */ int soneCounter = 0; - synchronized (newSones) { + synchronized (knownSones) { for (String knownSoneId : knownSones) { configuration.getStringValue("KnownSone/" + soneCounter++ + "/ID").setValue(knownSoneId); } @@ -2252,7 +2189,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis /* save known posts. */ int postCounter = 0; - synchronized (newPosts) { + synchronized (knownPosts) { for (String knownPostId : knownPosts) { configuration.getStringValue("KnownPosts/" + postCounter++ + "/ID").setValue(knownPostId); } @@ -2261,7 +2198,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis /* save known replies. */ int replyCounter = 0; - synchronized (newReplies) { + synchronized (knownReplies) { for (String knownReplyId : knownReplies) { configuration.getStringValue("KnownReplies/" + replyCounter++ + "/ID").setValue(knownReplyId); } @@ -2304,6 +2241,7 @@ 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.addBooleanOption("RequireFullAccess", new DefaultOption(false)); @@ -2327,23 +2265,10 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } })); - options.addBooleanOption("SoneRescueMode", new DefaultOption(false)); - options.addBooleanOption("ClearOnNextRestart", new DefaultOption(false)); - options.addBooleanOption("ReallyClearOnNextRestart", new DefaultOption(false)); - - /* read options from configuration. */ - options.getBooleanOption("ClearOnNextRestart").set(configuration.getBooleanValue("Option/ClearOnNextRestart").getValue(null)); - options.getBooleanOption("ReallyClearOnNextRestart").set(configuration.getBooleanValue("Option/ReallyClearOnNextRestart").getValue(null)); - boolean clearConfiguration = options.getBooleanOption("ClearOnNextRestart").get() && options.getBooleanOption("ReallyClearOnNextRestart").get(); - options.getBooleanOption("ClearOnNextRestart").set(null); - options.getBooleanOption("ReallyClearOnNextRestart").set(null); - if (clearConfiguration) { - /* stop loading the configuration. */ - return; - } loadConfigurationValue("InsertionDelay"); loadConfigurationValue("PostsPerPage"); + loadConfigurationValue("ImagesPerPage"); loadConfigurationValue("CharactersPerPost"); loadConfigurationValue("PostCutOffLength"); options.getBooleanOption("RequireFullAccess").set(configuration.getBooleanValue("Option/RequireFullAccess").getValue(null)); @@ -2352,7 +2277,6 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis options.getStringOption("TrustComment").set(configuration.getStringValue("Option/TrustComment").getValue(null)); options.getBooleanOption("ActivateFcpInterface").set(configuration.getBooleanValue("Option/ActivateFcpInterface").getValue(null)); options.getIntegerOption("FcpFullAccessRequired").set(configuration.getIntValue("Option/FcpFullAccessRequired").getValue(null)); - options.getBooleanOption("SoneRescueMode").set(configuration.getBooleanValue("Option/SoneRescueMode").getValue(null)); /* load known Sones. */ int soneCounter = 0; @@ -2361,7 +2285,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis if (knownSoneId == null) { break; } - synchronized (newSones) { + synchronized (knownSones) { knownSones.add(knownSoneId); } } @@ -2392,7 +2316,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis if (knownPostId == null) { break; } - synchronized (newPosts) { + synchronized (knownPosts) { knownPosts.add(knownPostId); } } @@ -2404,7 +2328,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis if (knownReplyId == null) { break; } - synchronized (newReplies) { + synchronized (knownReplies) { knownReplies.add(knownReplyId); } } @@ -2434,7 +2358,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis try { options.getIntegerOption(optionName).set(configuration.getIntValue("Option/" + optionName).getValue(null)); } catch (IllegalArgumentException iae1) { - logger.log(Level.WARNING, "Invalid value for " + optionName + " in configuration, using default."); + logger.log(Level.WARNING, String.format("Invalid value for %s in configuration, using default.", optionName)); } } @@ -2450,7 +2374,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis FreenetURI uri = new FreenetURI(uriString).setDocName("Sone").setMetaString(new String[0]); return uri; } catch (MalformedURLException mue1) { - logger.log(Level.WARNING, "Could not create Sone URI from URI: " + uriString, mue1); + logger.log(Level.WARNING, String.format("Could not create Sone URI from URI: %s", uriString), mue1); return null; } } @@ -2464,7 +2388,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ @Override public void ownIdentityAdded(OwnIdentity ownIdentity) { - logger.log(Level.FINEST, "Adding OwnIdentity: " + ownIdentity); + logger.log(Level.FINEST, String.format("Adding OwnIdentity: %s", ownIdentity)); if (ownIdentity.hasContext("Sone")) { trustedIdentities.put(ownIdentity, Collections.synchronizedSet(new HashSet())); addLocalSone(ownIdentity); @@ -2476,7 +2400,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ @Override public void ownIdentityRemoved(OwnIdentity ownIdentity) { - logger.log(Level.FINEST, "Removing OwnIdentity: " + ownIdentity); + logger.log(Level.FINEST, String.format("Removing OwnIdentity: %s", ownIdentity)); trustedIdentities.remove(ownIdentity); } @@ -2485,7 +2409,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ @Override public void identityAdded(OwnIdentity ownIdentity, Identity identity) { - logger.log(Level.FINEST, "Adding Identity: " + identity); + logger.log(Level.FINEST, String.format("Adding Identity: %s", identity)); trustedIdentities.get(ownIdentity).add(identity); addRemoteSone(identity); } @@ -2534,19 +2458,17 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis return; } synchronized (posts) { - synchronized (newPosts) { + synchronized (knownPosts) { for (Post post : sone.getPosts()) { posts.remove(post.getId()); - newPosts.remove(post.getId()); coreListenerManager.firePostRemoved(post); } } } synchronized (replies) { - synchronized (newReplies) { + synchronized (knownReplies) { for (PostReply reply : sone.getReplies()) { replies.remove(reply.getId()); - newReplies.remove(reply.getId()); coreListenerManager.fireReplyRemoved(reply); } } @@ -2554,10 +2476,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis synchronized (remoteSones) { remoteSones.remove(identity.getId()); } - synchronized (newSones) { - newSones.remove(identity.getId()); - coreListenerManager.fireSoneRemoved(sone); - } + coreListenerManager.fireSoneRemoved(sone); } // @@ -2609,7 +2528,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ @Override public void imageInsertStarted(Image image) { - logger.log(Level.WARNING, "Image insert started for " + image); + logger.log(Level.WARNING, String.format("Image insert started for %s...", image)); coreListenerManager.fireImageInsertStarted(image); } @@ -2618,7 +2537,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ @Override public void imageInsertAborted(Image image) { - logger.log(Level.WARNING, "Image insert aborted for " + image); + logger.log(Level.WARNING, String.format("Image insert aborted for %s.", image)); coreListenerManager.fireImageInsertAborted(image); } @@ -2627,10 +2546,10 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ @Override public void imageInsertFinished(Image image, FreenetURI key) { - logger.log(Level.WARNING, "Image insert finished for " + image + ": " + key); + logger.log(Level.WARNING, String.format("Image insert finished for %s: %s", image, key)); image.setKey(key.toString()); deleteTemporaryImage(image.getId()); - saveSone(image.getSone()); + touchConfiguration(); coreListenerManager.fireImageInsertFinished(image); } @@ -2639,7 +2558,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ @Override public void imageInsertFailed(Image image, Throwable cause) { - logger.log(Level.WARNING, "Image insert failed for " + image, cause); + logger.log(Level.WARNING, String.format("Image insert failed for %s." + image), cause); coreListenerManager.fireImageInsertFailed(image, cause); } @@ -2678,8 +2597,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * * @param insertionDelay * The insertion delay to validate - * @return {@code true} if the given insertion delay was valid, {@code - * false} otherwise + * @return {@code true} if the given insertion delay was valid, + * {@code false} otherwise */ public boolean validateInsertionDelay(Integer insertionDelay) { return options.getIntegerOption("InsertionDelay").validate(insertionDelay); @@ -2732,6 +2651,39 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } /** + * 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. * @@ -2962,58 +2914,6 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis return this; } - /** - * Returns whether Sone should clear its settings on the next restart. - * In order to be effective, {@link #isReallyClearOnNextRestart()} needs - * to return {@code true} as well! - * - * @return {@code true} if Sone should clear its settings on the next - * restart, {@code false} otherwise - */ - public boolean isClearOnNextRestart() { - return options.getBooleanOption("ClearOnNextRestart").get(); - } - - /** - * Sets whether Sone will clear its settings on the next restart. - * - * @param clearOnNextRestart - * {@code true} if Sone should clear its settings on the next - * restart, {@code false} otherwise - * @return This preferences - */ - public Preferences setClearOnNextRestart(Boolean clearOnNextRestart) { - options.getBooleanOption("ClearOnNextRestart").set(clearOnNextRestart); - return this; - } - - /** - * Returns whether Sone should really clear its settings on next - * restart. This is a confirmation option that needs to be set in - * addition to {@link #isClearOnNextRestart()} in order to clear Sone’s - * settings on the next restart. - * - * @return {@code true} if Sone should really clear its settings on the - * next restart, {@code false} otherwise - */ - public boolean isReallyClearOnNextRestart() { - return options.getBooleanOption("ReallyClearOnNextRestart").get(); - } - - /** - * Sets whether Sone should really clear its settings on the next - * restart. - * - * @param reallyClearOnNextRestart - * {@code true} if Sone should really clear its settings on - * the next restart, {@code false} otherwise - * @return This preferences - */ - public Preferences setReallyClearOnNextRestart(Boolean reallyClearOnNextRestart) { - options.getBooleanOption("ReallyClearOnNextRestart").set(reallyClearOnNextRestart); - return this; - } - } }