X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Fcore%2FCore.java;h=1bb638afca70eb44ef7260370a420f04de28fc95;hb=771e8efcd92c7325423441d57c5a6ed90a835e6f;hp=c39158208ba8ccdce636cca3265895d455f3fea0;hpb=2748d28c7b7b436a44438b78d98660f28ad7757b;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 c391582..1bb638a 100644 --- a/src/main/java/net/pterodactylus/sone/core/Core.java +++ b/src/main/java/net/pterodactylus/sone/core/Core.java @@ -19,6 +19,7 @@ package net.pterodactylus.sone.core; import java.net.MalformedURLException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -47,6 +48,7 @@ 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.database.Database; import net.pterodactylus.sone.fcp.FcpInterface; import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired; import net.pterodactylus.sone.freenet.wot.Identity; @@ -59,6 +61,7 @@ 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; @@ -95,6 +98,9 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis /** Whether we’re currently saving the configuration. */ private boolean storingConfiguration = false; + /** The database. */ + private Database database; + /** The identity manager. */ private final IdentityManager identityManager; @@ -108,7 +114,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis private final ImageInserter imageInserter; /** Sone downloader thread-pool. */ - private final ExecutorService soneDownloaders = Executors.newFixedThreadPool(10); + private final ExecutorService soneDownloaders = Executors.newFixedThreadPool(10, new NamedThreadFactory("Sone Downloader %2$d")); /** The update checker. */ private final UpdateChecker updateChecker; @@ -134,14 +140,6 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis /* synchronize access on this on localSones. */ private final Map soneRescuers = new HashMap(); - /** All local Sones. */ - /* synchronize access on this on itself. */ - private final Map localSones = new HashMap(); - - /** All remote Sones. */ - /* synchronize access on this on itself. */ - private final Map remoteSones = new HashMap(); - /** All known Sones. */ private final Set knownSones = new HashSet(); @@ -184,6 +182,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * * @param configuration * The configuration of the core + * @param database + * The database to use * @param freenetInterface * The freenet interface * @param identityManager @@ -191,9 +191,10 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @param webOfTrustUpdater * The WebOfTrust updater */ - public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater) { + public Core(Configuration configuration, Database database, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater) { super("Sone Core"); this.configuration = configuration; + this.database = database; this.freenetInterface = freenetInterface; this.identityManager = identityManager; this.soneDownloader = new SoneDownloader(this, freenetInterface); @@ -296,8 +297,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", isLocalSone(sone)).check(); - synchronized (localSones) { + Validation.begin().isNotNull("Sone", sone).check().is("Local Sone", sone.isLocal()).check(); + synchronized (soneRescuers) { SoneRescuer soneRescuer = soneRescuers.get(sone); if (soneRescuer == null) { soneRescuer = new SoneRescuer(this, soneDownloader, sone); @@ -326,11 +327,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * * @return All Sones */ - public Set getSones() { - Set allSones = new HashSet(); - allSones.addAll(getLocalSones()); - allSones.addAll(getRemoteSones()); - return allSones; + public Collection getSones() { + return database.getSones(); } /** @@ -361,10 +359,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ @Override public Sone getSone(String id, boolean create) { - if (isLocalSone(id)) { - return getLocalSone(id); - } - return getRemoteSone(id, create); + return database.getSone(id, create); } /** @@ -376,34 +371,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * otherwise */ public boolean hasSone(String id) { - return isLocalSone(id) || isRemoteSone(id); - } - - /** - * Returns whether the given Sone is a local Sone. - * - * @param sone - * The Sone to check for its locality - * @return {@code true} if the given Sone is local, {@code false} otherwise - */ - public boolean isLocalSone(Sone sone) { - synchronized (localSones) { - return localSones.containsKey(sone.getId()); - } - } - - /** - * Returns whether the given ID is the ID of a local Sone. - * - * @param id - * The Sone ID to check for its locality - * @return {@code true} if the given ID is a local Sone, {@code false} - * otherwise - */ - public boolean isLocalSone(String id) { - synchronized (localSones) { - return localSones.containsKey(id); - } + return database.getSone(id, false) != null; } /** @@ -411,10 +379,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * * @return All local Sones */ - public Set getLocalSones() { - synchronized (localSones) { - return new HashSet(localSones.values()); - } + public Collection getLocalSones() { + return database.getLocalSones(); } /** @@ -439,14 +405,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return The Sone with the given ID, or {@code null} */ public Sone getLocalSone(String id, boolean create) { - synchronized (localSones) { - Sone sone = localSones.get(id); - if ((sone == null) && create) { - sone = new Sone(id); - localSones.put(id, sone); - } - return sone; - } + return database.getLocalSone(id, create); } /** @@ -454,10 +413,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * * @return All remote Sones */ - public Set getRemoteSones() { - synchronized (remoteSones) { - return new HashSet(remoteSones.values()); - } + public Collection getRemoteSones() { + return database.getRemoteSones(); } /** @@ -471,42 +428,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return The Sone with the given ID */ public Sone getRemoteSone(String id, boolean create) { - synchronized (remoteSones) { - Sone sone = remoteSones.get(id); - if ((sone == null) && create && (id != null) && (id.length() == 43)) { - sone = new Sone(id); - remoteSones.put(id, sone); - } - return sone; - } - } - - /** - * Returns whether the given Sone is a remote Sone. - * - * @param sone - * The Sone to check - * @return {@code true} if the given Sone is a remote Sone, {@code false} - * otherwise - */ - public boolean isRemoteSone(Sone sone) { - synchronized (remoteSones) { - return remoteSones.containsKey(sone.getId()); - } - } - - /** - * Returns whether the Sone with the given ID is a remote Sone. - * - * @param id - * The ID of the Sone to check - * @return {@code true} if the Sone with the given ID is a remote Sone, - * {@code false} otherwise - */ - public boolean isRemoteSone(String id) { - synchronized (remoteSones) { - return remoteSones.containsKey(id); - } + return database.getRemoteSone(id, create); } /** @@ -553,17 +475,6 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } /** - * Returns the post with the given ID. - * - * @param postId - * The ID of the post to get - * @return The post with the given ID, or a new post with the given ID - */ - public Post getPost(String postId) { - return getPost(postId, true); - } - - /** * Returns the post with the given ID, optionally creating a new post. * * @param postId @@ -649,7 +560,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return All replies for the given post */ public List getReplies(Post post) { - Set sones = getSones(); + Collection sones = getSones(); List replies = new ArrayList(); for (Sone sone : sones) { for (PostReply reply : sone.getReplies()) { @@ -870,27 +781,25 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis logger.log(Level.WARNING, "Given OwnIdentity is null!"); return null; } - synchronized (localSones) { - final Sone sone; - try { - sone = getLocalSone(ownIdentity.getId()).setIdentity(ownIdentity).setInsertUri(new FreenetURI(ownIdentity.getInsertUri())).setRequestUri(new FreenetURI(ownIdentity.getRequestUri())); - } catch (MalformedURLException 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); - soneInserter.addSoneInsertListener(this); - soneInserters.put(sone, soneInserter); - sone.setStatus(SoneStatus.idle); - loadSone(sone); - soneInserter.start(); - return sone; + Sone sone; + try { + sone = getLocalSone(ownIdentity.getId()).setIdentity(ownIdentity).setInsertUri(new FreenetURI(ownIdentity.getInsertUri())).setRequestUri(new FreenetURI(ownIdentity.getRequestUri())); + } catch (MalformedURLException 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 */ + final SoneInserter soneInserter = new SoneInserter(this, freenetInterface, sone); + soneInserter.addSoneInsertListener(this); + soneInserters.put(sone, soneInserter); + sone.setStatus(SoneStatus.idle); + loadSone(sone); + soneInserter.start(); + database.saveSone(sone); + return sone; } /** @@ -930,37 +839,36 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis logger.log(Level.WARNING, "Given Identity is null!"); return null; } - synchronized (remoteSones) { - 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)); + 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)); + if (newSone) { + synchronized (knownSones) { + newSone = !knownSones.contains(sone.getId()); + } + sone.setKnown(!newSone); if (newSone) { - synchronized (knownSones) { - newSone = !knownSones.contains(sone.getId()); - } - sone.setKnown(!newSone); - if (newSone) { - coreListenerManager.fireNewSoneFound(sone); - for (Sone localSone : getLocalSones()) { - if (localSone.getOptions().getBooleanOption("AutoFollow").get()) { - followSone(localSone, sone); - } + coreListenerManager.fireNewSoneFound(sone); + for (Sone localSone : getLocalSones()) { + if (localSone.getOptions().getBooleanOption("AutoFollow").get()) { + followSone(localSone, sone); } } } - soneDownloader.addSone(sone); - soneDownloaders.execute(new Runnable() { + } + soneDownloader.addSone(sone); + soneDownloaders.execute(new Runnable() { - @Override - @SuppressWarnings("synthetic-access") - public void run() { - soneDownloader.fetchSone(sone, sone.getRequestUri()); - } + @Override + @SuppressWarnings("synthetic-access") + public void run() { + soneDownloader.fetchSone(sone, sone.getRequestUri()); + } - }); - return sone; - } + }); + database.saveSone(sone); + return sone; } /** @@ -1053,7 +961,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } /** - * Sets the trust value of the given origin Sone for the target Sone. + * Sets the trust value of the given origin Sone for + * the target Sone. * * @param origin * The origin Sone @@ -1160,8 +1069,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis if (!storedPosts.contains(post)) { if (post.getTime() < getSoneFollowingTime(sone)) { knownPosts.add(post.getId()); + post.setKnown(true); } else if (!knownPosts.contains(post.getId())) { - sone.setKnown(false); coreListenerManager.fireNewPostFound(post); } } @@ -1185,8 +1094,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis if (!storedReplies.contains(reply)) { if (reply.getTime() < getSoneFollowingTime(sone)) { knownReplies.add(reply.getId()); + reply.setKnown(true); } else if (!knownReplies.contains(reply.getId())) { - reply.setKnown(false); coreListenerManager.fireNewReplyFound(reply); } } @@ -1257,16 +1166,14 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis 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, String.format("Tried to delete non-local Sone: %s", sone)); - return; - } - localSones.remove(sone.getId()); - SoneInserter soneInserter = soneInserters.remove(sone); - soneInserter.removeSoneInsertListener(this); - soneInserter.stop(); + if (!sone.isLocal()) { + logger.log(Level.WARNING, String.format("Tried to delete non-local Sone: %s", sone)); + return; } + database.removeSone(sone.getId()); + SoneInserter soneInserter = soneInserters.remove(sone); + soneInserter.removeSoneInsertListener(this); + soneInserter.stop(); webOfTrustUpdater.removeContext((OwnIdentity) sone.getIdentity(), "Sone"); webOfTrustUpdater.removeProperty((OwnIdentity) sone.getIdentity(), "Sone.LatestEdition"); try { @@ -1302,7 +1209,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The Sone to load and update */ public void loadSone(Sone sone) { - if (!isLocalSone(sone)) { + if (!sone.isLocal()) { logger.log(Level.FINE, String.format("Tried to load non-local Sone: %s", sone)); return; } @@ -1359,7 +1266,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis logger.log(Level.WARNING, "Invalid post found, aborting load!"); return; } - Post post = getPost(postId).setSone(sone).setTime(postTime).setText(postText); + Post post = getPost(postId, true).setSone(sone).setTime(postTime).setText(postText); if ((postRecipientId != null) && (postRecipientId.length() == 43)) { post.setRecipient(getSone(postRecipientId)); } @@ -1381,7 +1288,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis logger.log(Level.WARNING, "Invalid reply found, aborting load!"); return; } - replies.add(getReply(replyId).setSone(sone).setPost(getPost(postId)).setTime(replyTime).setText(replyText)); + replies.add(getReply(replyId).setSone(sone).setPost(getPost(postId, true)).setTime(replyTime).setText(replyText)); } /* load post likes. */ @@ -1525,50 +1432,6 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * * @param sone * The Sone that creates the post - * @param text - * The text of the post - * @return The created post - */ - public Post createPost(Sone sone, String text) { - return createPost(sone, System.currentTimeMillis(), text); - } - - /** - * Creates a new post. - * - * @param sone - * The Sone that creates the post - * @param time - * The time of the post - * @param text - * The text of the post - * @return The created post - */ - public Post createPost(Sone sone, long time, String text) { - return createPost(sone, null, time, text); - } - - /** - * Creates a new post. - * - * @param sone - * The Sone that creates the post - * @param recipient - * The recipient Sone, or {@code null} if this post does not have - * a recipient - * @param text - * The text of the post - * @return The created post - */ - public Post createPost(Sone sone, Sone recipient, String text) { - return createPost(sone, recipient, System.currentTimeMillis(), text); - } - - /** - * Creates a new post. - * - * @param sone - * The Sone that creates the post * @param recipient * The recipient Sone, or {@code null} if this post does not have * a recipient @@ -1579,7 +1442,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return The created post */ public Post createPost(Sone sone, Sone recipient, long time, String text) { - if (!isLocalSone(sone)) { + Validation.begin().isNotNull("Text", text).check().isGreater("Text Length", text.length(), 0).check(); + if (!sone.isLocal()) { logger.log(Level.FINE, String.format("Tried to create post for non-local Sone: %s", sone)); return null; } @@ -1613,7 +1477,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The post to delete */ public void deletePost(Post post) { - if (!isLocalSone(post.getSone())) { + if (!post.getSone().isLocal()) { logger.log(Level.WARNING, String.format("Tried to delete post of non-local Sone: %s", post.getSone())); return; } @@ -1719,7 +1583,8 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * @return The created reply */ public PostReply createReply(Sone sone, Post post, long time, String text) { - if (!isLocalSone(sone)) { + Validation.begin().isNotNull("Text", text).check().isGreater("Text Length", text.trim().length(), 0).check(); + if (!sone.isLocal()) { logger.log(Level.FINE, String.format("Tried to create reply for non-local Sone: %s", sone)); return null; } @@ -1753,7 +1618,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ public void deleteReply(PostReply reply) { Sone sone = reply.getSone(); - if (!isLocalSone(sone)) { + if (!sone.isLocal()) { logger.log(Level.FINE, String.format("Tried to delete non-local reply: %s", reply)); return; } @@ -1828,7 +1693,7 @@ 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", isLocalSone(album.getSone())).check(); + Validation.begin().isNotNull("Album", album).check().is("Local Sone", album.getSone().isLocal()).check(); if (!album.isEmpty()) { return; } @@ -1855,7 +1720,7 @@ 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", isLocalSone(sone)).check().isEqual("Owner and Album Owner", sone, album.getSone()).check(); + 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(); Image image = new Image(temporaryImage.getId()).setSone(sone).setCreationTime(System.currentTimeMillis()); album.addImage(image); synchronized (images) { @@ -1874,7 +1739,7 @@ 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", isLocalSone(image.getSone())).check(); + Validation.begin().isNotNull("Image", image).check().is("Local Sone", image.getSone().isLocal()).check(); deleteTemporaryImage(image.getId()); image.getAlbum().removeImage(image); synchronized (images) { @@ -1977,12 +1842,10 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ @Override public void serviceStop() { - synchronized (localSones) { - for (Entry soneInserter : soneInserters.entrySet()) { - soneInserter.getValue().removeSoneInsertListener(this); - soneInserter.getValue().stop(); - saveSone(soneInserter.getKey()); - } + for (Entry soneInserter : soneInserters.entrySet()) { + soneInserter.getValue().removeSoneInsertListener(this); + soneInserter.getValue().stop(); + saveSone(soneInserter.getKey()); } saveConfiguration(); webOfTrustUpdater.stop(); @@ -2003,7 +1866,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis * The Sone to save */ private synchronized void saveSone(Sone sone) { - if (!isLocalSone(sone)) { + if (!sone.isLocal()) { logger.log(Level.FINE, String.format("Tried to save non-local Sone: %s", sone)); return; } @@ -2412,7 +2275,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis */ @Override public void identityUpdated(OwnIdentity ownIdentity, final Identity identity) { - new Thread(new Runnable() { + soneDownloaders.execute(new Runnable() { @Override @SuppressWarnings("synthetic-access") @@ -2423,7 +2286,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis soneDownloader.addSone(sone); soneDownloader.fetchSone(sone); } - }).start(); + }); } /** @@ -2466,9 +2329,7 @@ public class Core extends AbstractService implements IdentityListener, UpdateLis } } } - synchronized (remoteSones) { - remoteSones.remove(identity.getId()); - } + database.removeSone(identity.getId()); coreListenerManager.fireSoneRemoved(sone); }