diff --git a/briar-android/src/org/briarproject/android/AndroidComponent.java b/briar-android/src/org/briarproject/android/AndroidComponent.java index 3e59233be3dc1542bfa2b4867cb90197cc5c6e39..accd45a4cdedfc1b33c49780842fab34b3880741 100644 --- a/briar-android/src/org/briarproject/android/AndroidComponent.java +++ b/briar-android/src/org/briarproject/android/AndroidComponent.java @@ -5,8 +5,6 @@ import org.briarproject.CoreModule; import org.briarproject.android.api.AndroidExecutor; import org.briarproject.android.api.AndroidNotificationManager; import org.briarproject.android.api.ReferenceManager; -import org.briarproject.android.blogs.BlogPersistentData; -import org.briarproject.android.forum.ForumPersistentData; import org.briarproject.android.report.BriarReportSender; import org.briarproject.api.blogs.BlogManager; import org.briarproject.api.blogs.BlogPostFactory; @@ -34,7 +32,6 @@ import org.briarproject.api.messaging.MessagingManager; import org.briarproject.api.messaging.PrivateMessageFactory; import org.briarproject.api.plugins.ConnectionRegistry; import org.briarproject.api.plugins.PluginManager; -import org.briarproject.api.properties.TransportPropertyManager; import org.briarproject.api.settings.SettingsManager; import org.briarproject.plugins.AndroidPluginsModule; import org.briarproject.system.AndroidSystemModule; @@ -91,8 +88,6 @@ public interface AndroidComponent extends CoreEagerSingletons { PrivateMessageFactory privateMessageFactory(); - TransportPropertyManager transportPropertyManager(); - ForumManager forumManager(); ForumSharingManager forumSharingManager(); @@ -117,10 +112,6 @@ public interface AndroidComponent extends CoreEagerSingletons { AndroidExecutor androidExecutor(); - ForumPersistentData forumPersistentData(); - - BlogPersistentData blogPersistentData(); - @IoExecutor Executor ioExecutor(); diff --git a/briar-android/src/org/briarproject/android/AppModule.java b/briar-android/src/org/briarproject/android/AppModule.java index 825e639c6c69ab442b1d85d388b2769e68920733..8f80ce0395841c0d5d1a5e81eb2d0c7f14a77831 100644 --- a/briar-android/src/org/briarproject/android/AppModule.java +++ b/briar-android/src/org/briarproject/android/AppModule.java @@ -4,8 +4,6 @@ import android.app.Application; import org.briarproject.android.api.AndroidNotificationManager; import org.briarproject.android.api.ReferenceManager; -import org.briarproject.android.blogs.BlogPersistentData; -import org.briarproject.android.forum.ForumPersistentData; import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.PublicKey; import org.briarproject.api.crypto.SecretKey; @@ -65,13 +63,13 @@ public class AppModule { } @Provides - public UiCallback provideUICallback() { + UiCallback provideUICallback() { return uiCallback; } @Provides @Singleton - public DatabaseConfig provideDatabaseConfig(Application app) { + DatabaseConfig provideDatabaseConfig(Application app) { final File dir = app.getApplicationContext().getDir("db", MODE_PRIVATE); return new DatabaseConfig() { @@ -103,7 +101,7 @@ public class AppModule { @Provides @Singleton - public DevConfig provideDevConfig(final CryptoComponent crypto) { + DevConfig provideDevConfig(final CryptoComponent crypto) { return new DevConfig() { @Override @@ -138,16 +136,4 @@ public class AppModule { eventBus.addListener(notificationManager); return notificationManager; } - - @Provides - @Singleton - ForumPersistentData provideForumPersistence() { - return new ForumPersistentData(); - } - - @Provides - @Singleton - BlogPersistentData provideBlogPersistence() { - return new BlogPersistentData(); - } } diff --git a/briar-android/src/org/briarproject/android/blogs/BlogActivity.java b/briar-android/src/org/briarproject/android/blogs/BlogActivity.java index 35321f390a96ee09c356de2b294552cc812d9696..7519b46ab2c9d6b304085003d91a93d01cf4ebaf 100644 --- a/briar-android/src/org/briarproject/android/blogs/BlogActivity.java +++ b/briar-android/src/org/briarproject/android/blogs/BlogActivity.java @@ -21,7 +21,6 @@ import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; import java.util.Collection; -import java.util.logging.Logger; import javax.inject.Inject; @@ -38,8 +37,6 @@ public class BlogActivity extends BriarActivity implements BlogPostListener, static final String IS_NEW_BLOG = "briar.IS_NEW_BLOG"; private static final String BLOG_PAGER_ADAPTER = "briar.BLOG_PAGER_ADAPTER"; - private static final Logger LOG = - Logger.getLogger(BlogActivity.class.getName()); private ProgressBar progressBar; private ViewPager pager; diff --git a/briar-android/src/org/briarproject/android/blogs/BlogController.java b/briar-android/src/org/briarproject/android/blogs/BlogController.java index a805c2d344e52c6295d60b90e7a79b563604583e..532d2dd2505dbb0cd75498f308522df0026e669f 100644 --- a/briar-android/src/org/briarproject/android/blogs/BlogController.java +++ b/briar-android/src/org/briarproject/android/blogs/BlogController.java @@ -3,18 +3,18 @@ package org.briarproject.android.blogs; import android.support.annotation.Nullable; import org.briarproject.android.controller.ActivityLifecycleController; -import org.briarproject.android.controller.handler.UiResultHandler; +import org.briarproject.android.controller.handler.ResultHandler; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; -import java.util.TreeSet; +import java.util.SortedSet; public interface BlogController extends ActivityLifecycleController { - void loadBlog(final GroupId groupId, final boolean reload, - final UiResultHandler<Boolean> resultHandler); + void loadBlog(GroupId groupId, boolean reload, + ResultHandler<Boolean> resultHandler); - TreeSet<BlogPostItem> getBlogPosts(); + SortedSet<BlogPostItem> getBlogPosts(); @Nullable BlogPostItem getBlogPost(MessageId postId); @@ -22,10 +22,10 @@ public interface BlogController extends ActivityLifecycleController { @Nullable MessageId getBlogPostId(int position); - void deleteBlog(final UiResultHandler<Boolean> resultHandler); + void deleteBlog(ResultHandler<Boolean> resultHandler); interface BlogPostListener { - void onBlogPostAdded(final BlogPostItem post, final boolean local); + void onBlogPostAdded(BlogPostItem post, boolean local); } } diff --git a/briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java b/briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java index d2898602c68dd664a4709cd761667b7d4e01a1dd..f34e63469e100c88d33d796faa766681d46b9444 100644 --- a/briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java +++ b/briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java @@ -4,7 +4,7 @@ import android.app.Activity; import android.support.annotation.Nullable; import org.briarproject.android.controller.DbControllerImpl; -import org.briarproject.android.controller.handler.UiResultHandler; +import org.briarproject.android.controller.handler.ResultHandler; import org.briarproject.api.blogs.Blog; import org.briarproject.api.blogs.BlogManager; import org.briarproject.api.blogs.BlogPostHeader; @@ -19,6 +19,7 @@ import org.briarproject.api.sync.MessageId; import java.util.ArrayList; import java.util.Collection; +import java.util.SortedSet; import java.util.TreeSet; import java.util.logging.Logger; @@ -39,10 +40,11 @@ public class BlogControllerImpl extends DbControllerImpl protected volatile BlogManager blogManager; @Inject protected volatile EventBus eventBus; - @Inject - protected BlogPersistentData data; private volatile BlogPostListener listener; + private volatile GroupId groupId = null; + // FIXME: This collection isn't thread-safe, isn't updated atomically + private volatile TreeSet<BlogPostItem> posts = null; @Inject BlogControllerImpl() { @@ -71,22 +73,25 @@ public class BlogControllerImpl extends DbControllerImpl @Override public void onActivityDestroy() { - if (activity.isFinishing()) { - data.clearAll(); - } } @Override public void eventOccurred(Event e) { if (e instanceof BlogPostAddedEvent) { final BlogPostAddedEvent m = (BlogPostAddedEvent) e; - if (m.getGroupId().equals(data.getGroupId())) { + if (m.getGroupId().equals(groupId)) { LOG.info("New blog post added"); + if (posts == null) { + LOG.info("Posts have not loaded, yet"); + // FIXME: Race condition, new post may not get loaded + return; + } final BlogPostHeader header = m.getHeader(); + // FIXME: Don't make blocking calls in event handlers try { final byte[] body = blogManager.getPostBody(header.getId()); final BlogPostItem post = new BlogPostItem(header, body); - data.addPost(post); + posts.add(post); listener.onBlogPostAdded(post, m.isLocal()); } catch (DbException ex) { if (LOG.isLoggable(WARNING)) @@ -95,7 +100,7 @@ public class BlogControllerImpl extends DbControllerImpl } } else if (e instanceof GroupRemovedEvent) { GroupRemovedEvent s = (GroupRemovedEvent) e; - if (s.getGroup().getId().equals(data.getGroupId())) { + if (s.getGroup().getId().equals(groupId)) { LOG.info("Blog removed"); activity.runOnUiThread(new Runnable() { @Override @@ -108,31 +113,29 @@ public class BlogControllerImpl extends DbControllerImpl } @Override - public void loadBlog(final GroupId groupId, final boolean reload, - final UiResultHandler<Boolean> resultHandler) { + public void loadBlog(final GroupId g, final boolean reload, + final ResultHandler<Boolean> resultHandler) { - LOG.info("Loading blog..."); runOnDbThread(new Runnable() { @Override public void run() { try { - if (reload || data.getGroupId() == null || - !data.getGroupId().equals(groupId)) { - data.setGroupId(groupId); + if (reload || posts == null) { + groupId = g; + posts = new TreeSet<>(); // load blog posts long now = System.currentTimeMillis(); - Collection<BlogPostItem> posts = new ArrayList<>(); + Collection<BlogPostItem> newPosts = new ArrayList<>(); Collection<BlogPostHeader> header = - blogManager.getPostHeaders(groupId); + blogManager.getPostHeaders(g); for (BlogPostHeader h : header) { byte[] body = blogManager.getPostBody(h.getId()); - posts.add(new BlogPostItem(h, body)); + newPosts.add(new BlogPostItem(h, body)); } - data.setPosts(posts); + posts.addAll(newPosts); long duration = System.currentTimeMillis() - now; if (LOG.isLoggable(INFO)) - LOG.info("Post header load took " + duration + - " ms"); + LOG.info("Loading blog took " + duration + " ms"); } resultHandler.onResult(true); } catch (DbException e) { @@ -145,14 +148,16 @@ public class BlogControllerImpl extends DbControllerImpl } @Override - public TreeSet<BlogPostItem> getBlogPosts() { - return data.getBlogPosts(); + @Nullable + public SortedSet<BlogPostItem> getBlogPosts() { + return posts; } @Override @Nullable public BlogPostItem getBlogPost(MessageId id) { - for (BlogPostItem item : getBlogPosts()) { + if (posts == null) return null; + for (BlogPostItem item : posts) { if (item.getId().equals(id)) return item; } return null; @@ -161,8 +166,9 @@ public class BlogControllerImpl extends DbControllerImpl @Override @Nullable public MessageId getBlogPostId(int position) { + if (posts == null) return null; int i = 0; - for (BlogPostItem post : getBlogPosts()) { + for (BlogPostItem post : posts) { if (i == position) return post.getId(); i++; } @@ -170,16 +176,16 @@ public class BlogControllerImpl extends DbControllerImpl } @Override - public void deleteBlog(final UiResultHandler<Boolean> resultHandler) { + public void deleteBlog(final ResultHandler<Boolean> resultHandler) { runOnDbThread(new Runnable() { @Override public void run() { - if (data.getGroupId() == null) { + if (groupId == null) { resultHandler.onResult(false); return; } try { - Blog b = blogManager.getBlog(data.getGroupId()); + Blog b = blogManager.getBlog(groupId); blogManager.removeBlog(b); resultHandler.onResult(true); } catch (DbException e) { diff --git a/briar-android/src/org/briarproject/android/blogs/BlogPersistentData.java b/briar-android/src/org/briarproject/android/blogs/BlogPersistentData.java deleted file mode 100644 index a2834c809cd5afc0643be76ccdb7d6d5b3de1025..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/blogs/BlogPersistentData.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.briarproject.android.blogs; - -import org.briarproject.api.sync.GroupId; - -import java.util.Collection; -import java.util.TreeSet; - -import javax.inject.Inject; - -/** - * This class is a singleton that defines the data that should persist, i.e. - * still be present in memory after activity restarts. This class is not thread - * safe. - */ -public class BlogPersistentData { - - private volatile GroupId groupId; - private volatile TreeSet<BlogPostItem> posts = new TreeSet<>(); - - public BlogPersistentData() { - - } - - public void setGroupId(GroupId groupId) { - this.groupId = groupId; - } - - public GroupId getGroupId() { - return groupId; - } - - public void setPosts(Collection<BlogPostItem> posts) { - this.posts.clear(); - this.posts.addAll(posts); - } - - void addPost(BlogPostItem post) { - posts.add(post); - } - - TreeSet<BlogPostItem> getBlogPosts() { - return posts; - } - - void clearAll() { - groupId = null; - posts.clear(); - } -} diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java index 77f574f20f4a2a18f4471c01e0d9e1e63006fd06..f6a0c597f583591fa249157d91f12f8f36bfc13b 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java +++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java @@ -37,6 +37,7 @@ import org.briarproject.android.controller.handler.UiResultHandler; import org.briarproject.android.util.AndroidUtils; import org.briarproject.android.util.BriarRecyclerView; import org.briarproject.android.util.TrustIndicatorView; +import org.briarproject.api.forum.Forum; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; import org.briarproject.util.StringUtils; @@ -117,7 +118,8 @@ public class ForumActivity extends BriarActivity implements @Override public void onResultUi(Boolean result) { if (result) { - setTitle(forumController.getForumName()); + Forum forum = forumController.getForum(); + if (forum != null) setTitle(forum.getName()); forumAdapter = new ForumAdapter( forumController.getForumEntries()); recyclerView.setAdapter(forumAdapter); @@ -264,6 +266,7 @@ public class ForumActivity extends BriarActivity implements String text = textInput.getText().toString(); if (text.trim().length() == 0) return; + if (forumController.getForum() == null) return; ForumEntry replyEntry = forumAdapter.getReplyEntry(); if (replyEntry == null) { // root post diff --git a/briar-android/src/org/briarproject/android/forum/ForumController.java b/briar-android/src/org/briarproject/android/forum/ForumController.java index a3419b812f84edf39839f587186c2bcb2adff167..b492627e41e07a5ba18e7bd971484cc21cea91d1 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumController.java +++ b/briar-android/src/org/briarproject/android/forum/ForumController.java @@ -1,7 +1,10 @@ package org.briarproject.android.forum; +import android.support.annotation.Nullable; + import org.briarproject.android.controller.ActivityLifecycleController; -import org.briarproject.android.controller.handler.UiResultHandler; +import org.briarproject.android.controller.handler.ResultHandler; +import org.briarproject.api.forum.Forum; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; @@ -10,17 +13,26 @@ import java.util.List; public interface ForumController extends ActivityLifecycleController { - void loadForum(GroupId groupId, UiResultHandler<Boolean> resultHandler); - String getForumName(); + void loadForum(GroupId groupId, ResultHandler<Boolean> resultHandler); + + @Nullable + Forum getForum(); + List<ForumEntry> getForumEntries(); - void unsubscribe(UiResultHandler<Boolean> resultHandler); + + void unsubscribe(ResultHandler<Boolean> resultHandler); + void entryRead(ForumEntry forumEntry); + void entriesRead(Collection<ForumEntry> messageIds); + void createPost(byte[] body); + void createPost(byte[] body, MessageId parentId); interface ForumPostListener { void addLocalEntry(int index, ForumEntry entry); + void addForeignEntry(int index, ForumEntry entry); } diff --git a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java b/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java index b5e83f8f4fa1c317eefc0130c2aed156e0cc2f87..638074ca13753aa13438866160f96bbfe343144b 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java +++ b/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java @@ -1,10 +1,12 @@ package org.briarproject.android.forum; import android.app.Activity; +import android.support.annotation.Nullable; import org.briarproject.android.controller.DbControllerImpl; -import org.briarproject.android.controller.handler.UiResultHandler; +import org.briarproject.android.controller.handler.ResultHandler; import org.briarproject.api.FormatException; +import org.briarproject.api.clients.MessageTree; import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.crypto.KeyParser; @@ -15,15 +17,16 @@ import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventListener; import org.briarproject.api.event.ForumPostReceivedEvent; import org.briarproject.api.event.GroupRemovedEvent; +import org.briarproject.api.forum.Forum; import org.briarproject.api.forum.ForumManager; import org.briarproject.api.forum.ForumPost; import org.briarproject.api.forum.ForumPostFactory; import org.briarproject.api.forum.ForumPostHeader; -import org.briarproject.api.identity.Author; import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; +import org.briarproject.clients.MessageTreeImpl; import org.briarproject.util.StringUtils; import java.security.GeneralSecurityException; @@ -31,7 +34,9 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Stack; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -62,8 +67,14 @@ public class ForumControllerImpl extends DbControllerImpl protected volatile EventBus eventBus; @Inject protected volatile IdentityManager identityManager; - @Inject - protected ForumPersistentData data; + + private final Map<MessageId, byte[]> bodyCache = new ConcurrentHashMap<>(); + private final MessageTree<ForumPostHeader> tree = new MessageTreeImpl<>(); + + private volatile LocalAuthor localAuthor = null; + private volatile Forum forum = null; + // FIXME: This collection isn't thread-safe, isn't updated atomically + private volatile List<ForumEntry> forumEntries = null; private ForumPostListener listener; @@ -95,22 +106,22 @@ public class ForumControllerImpl extends DbControllerImpl @Override public void onActivityDestroy() { - if (activity.isFinishing()) { - data.clearAll(); - } } @Override public void eventOccurred(Event e) { + if (forum == null) return; + if (e instanceof ForumPostReceivedEvent) { ForumPostReceivedEvent pe = (ForumPostReceivedEvent) e; - if (pe.getGroupId().equals(data.getGroupId())) { + if (pe.getGroupId().equals(forum.getId())) { LOG.info("Forum Post received, adding..."); + // FIXME: Don't make blocking calls in event handlers addNewPost(pe.getForumPostHeader()); } } else if (e instanceof GroupRemovedEvent) { GroupRemovedEvent s = (GroupRemovedEvent) e; - if (s.getGroup().getId().equals(data.getGroupId())) { + if (s.getGroup().getId().equals(forum.getId())) { LOG.info("Forum removed"); activity.runOnUiThread(new Runnable() { @Override @@ -123,28 +134,29 @@ public class ForumControllerImpl extends DbControllerImpl } private void addNewPost(final ForumPostHeader h) { - if (data == null) return; + if (forum == null) return; runOnDbThread(new Runnable() { @Override public void run() { - data.addHeader(h); - data.clearForumEntries(); - - try { - byte[] body = forumManager.getPostBody(h.getId()); - data.addBody(h.getId(), body); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); + if (!bodyCache.containsKey(h.getId())) { + try { + byte[] body = forumManager.getPostBody(h.getId()); + bodyCache.put(h.getId(), body); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + return; + } } - Author a = data.getLocalAuthor(); + tree.add(h); + forumEntries = null; // FIXME we should not need to calculate the index here // the index is essentially stored in two different locations int i = 0; for (ForumEntry entry : getForumEntries()) { if (entry.getMessageId().equals(h.getId())) { - if (a != null && a.equals(h.getAuthor())) { + if (localAuthor != null && localAuthor.equals(h.getAuthor())) { addLocalEntry(i, entry); } else { addForeignEntry(i, entry); @@ -156,31 +168,29 @@ public class ForumControllerImpl extends DbControllerImpl }); } - private void loadAuthor() throws DbException { - Collection<LocalAuthor> localAuthors = - identityManager.getLocalAuthors(); - - for (LocalAuthor author : localAuthors) { - if (author == null) - continue; - data.setLocalAuthor(author); - break; - } - } - + /** + * This should only be run from the DbThread. + * @throws DbException + */ private void loadPosts() throws DbException { + if (forum == null) + throw new RuntimeException("Forum has not been initialized"); + + // Get Headers long now = System.currentTimeMillis(); Collection<ForumPostHeader> headers = - forumManager.getPostHeaders(data.getGroupId()); - data.addHeaders(headers); + forumManager.getPostHeaders(forum.getId()); + tree.add(headers); long duration = System.currentTimeMillis() - now; if (LOG.isLoggable(INFO)) LOG.info("Loading headers took " + duration + " ms"); + + // Get Bodies now = System.currentTimeMillis(); for (ForumPostHeader header : headers) { - if (data.getBody(header.getId()) == null) { + if (!bodyCache.containsKey(header.getId())) { byte[] body = forumManager.getPostBody(header.getId()); - data.addBody(header.getId(), body); + bodyCache.put(header.getId(), body); } } duration = System.currentTimeMillis() - now; @@ -190,29 +200,32 @@ public class ForumControllerImpl extends DbControllerImpl @Override public void loadForum(final GroupId groupId, - final UiResultHandler<Boolean> resultHandler) { - LOG.info("Loading forum..."); - + final ResultHandler<Boolean> resultHandler) { runOnDbThread(new Runnable() { @Override public void run() { + LOG.info("Loading forum..."); try { - if (data.getGroupId() == null || - !data.getGroupId().equals(groupId)) { - data.clearAll(); - data.setGroupId(groupId); + if (forum == null) { + // Get Forum long now = System.currentTimeMillis(); - data.setForum(forumManager.getForum(groupId)); + forum = forumManager.getForum(groupId); long duration = System.currentTimeMillis() - now; if (LOG.isLoggable(INFO)) LOG.info("Loading forum took " + duration + " ms"); + + // Get First Identity now = System.currentTimeMillis(); - loadAuthor(); + localAuthor = + identityManager.getLocalAuthors().iterator() + .next(); duration = System.currentTimeMillis() - now; if (LOG.isLoggable(INFO)) LOG.info("Loading author took " + duration + " ms"); + + // Get Forum Posts and Bodies loadPosts(); } resultHandler.onResult(true); @@ -223,21 +236,21 @@ public class ForumControllerImpl extends DbControllerImpl } } }); - } @Override - public String getForumName() { - return data.getForum() == null ? null : data.getForum().getName(); + @Nullable + public Forum getForum() { + return forum; } @Override public List<ForumEntry> getForumEntries() { - if (data.getForumEntries() != null) { - return data.getForumEntries(); + if (forumEntries != null) { + return forumEntries; } - Collection<ForumPostHeader> headers = data.getHeaders(); - List<ForumEntry> forumEntries = new ArrayList<>(); + Collection<ForumPostHeader> headers = getHeaders(); + List<ForumEntry> entries = new ArrayList<>(); Stack<MessageId> idStack = new Stack<>(); for (ForumPostHeader h : headers) { @@ -251,21 +264,23 @@ public class ForumControllerImpl extends DbControllerImpl idStack.pop(); } while (!h.getParentId().equals(idStack.peek())); } - forumEntries.add(new ForumEntry(h, - StringUtils.fromUtf8(data.getBody(h.getId())), - idStack.size())); + byte[] body = bodyCache.get(h.getId()); + entries.add(new ForumEntry(h, StringUtils.fromUtf8(body), + idStack.size())); } - data.setForumEntries(forumEntries); - return forumEntries; + forumEntries = entries; + return entries; } @Override - public void unsubscribe(final UiResultHandler<Boolean> resultHandler) { + public void unsubscribe(final ResultHandler<Boolean> resultHandler) { + if (forum == null) return; runOnDbThread(new Runnable() { + @Override public void run() { try { long now = System.currentTimeMillis(); - forumManager.removeForum(data.getForum()); + forumManager.removeForum(forum); long duration = System.currentTimeMillis() - now; if (LOG.isLoggable(INFO)) LOG.info("Removing forum took " + duration + " ms"); @@ -287,6 +302,7 @@ public class ForumControllerImpl extends DbControllerImpl @Override public void entriesRead(final Collection<ForumEntry> forumEntries) { runOnDbThread(new Runnable() { + @Override public void run() { try { long now = System.currentTimeMillis(); @@ -312,10 +328,11 @@ public class ForumControllerImpl extends DbControllerImpl @Override public void createPost(final byte[] body, final MessageId parentId) { cryptoExecutor.execute(new Runnable() { + @Override public void run() { long timestamp = System.currentTimeMillis(); long newestTimeStamp = 0; - Collection<ForumPostHeader> headers = data.getHeaders(); + Collection<ForumPostHeader> headers = getHeaders(); if (headers != null) { for (ForumPostHeader h : headers) { if (h.getTimestamp() > newestTimeStamp) @@ -329,16 +346,18 @@ public class ForumControllerImpl extends DbControllerImpl ForumPost p; try { KeyParser keyParser = crypto.getSignatureKeyParser(); - byte[] b = data.getLocalAuthor().getPrivateKey(); + byte[] b = localAuthor.getPrivateKey(); PrivateKey authorKey = keyParser.parsePrivateKey(b); p = forumPostFactory.createPseudonymousPost( - data.getGroupId(), timestamp, parentId, - data.getLocalAuthor(), "text/plain", body, + forum.getId(), timestamp, parentId, + localAuthor, "text/plain", body, authorKey); } catch (GeneralSecurityException | FormatException e) { throw new RuntimeException(e); } + bodyCache.put(p.getMessage().getId(), body); storePost(p); + // FIXME: Don't make DB calls on the crypto executor addNewPost(p); } }); @@ -364,6 +383,7 @@ public class ForumControllerImpl extends DbControllerImpl private void storePost(final ForumPost p) { runOnDbThread(new Runnable() { + @Override public void run() { try { long now = System.currentTimeMillis(); @@ -388,4 +408,8 @@ public class ForumControllerImpl extends DbControllerImpl addNewPost(h); } + private Collection<ForumPostHeader> getHeaders() { + return tree.depthFirstOrder(); + } + } diff --git a/briar-android/src/org/briarproject/android/forum/ForumPersistentData.java b/briar-android/src/org/briarproject/android/forum/ForumPersistentData.java deleted file mode 100644 index 6464be24ead03476e301674648cee386da43b0df..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/forum/ForumPersistentData.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.briarproject.android.forum; - -import org.briarproject.api.clients.MessageTree; -import org.briarproject.api.forum.Forum; -import org.briarproject.api.forum.ForumPostHeader; -import org.briarproject.api.identity.LocalAuthor; -import org.briarproject.api.sync.GroupId; -import org.briarproject.api.sync.MessageId; -import org.briarproject.clients.MessageTreeImpl; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * This class is a singleton that defines the data that should persist, i.e. - * still be present in memory after activity restarts. This class is not thread - * safe. - */ -public class ForumPersistentData { - - private volatile MessageTree<ForumPostHeader> tree = - new MessageTreeImpl<>(); - private volatile Map<MessageId, byte[]> bodyCache = new HashMap<>(); - private volatile LocalAuthor localAuthor; - private volatile Forum forum; - private volatile GroupId groupId; - private List<ForumEntry> forumEntries; - - void clearAll() { - clearForumEntries(); - tree.clear(); - bodyCache.clear(); - localAuthor = null; - forum = null; - groupId = null; - } - - void clearForumEntries() { - forumEntries = null; - } - - void addHeaders(Collection<ForumPostHeader> headers) { - tree.add(headers); - } - - void addHeader(ForumPostHeader header) { - tree.add(header); - } - - public Collection<ForumPostHeader> getHeaders() { - return tree.depthFirstOrder(); - } - - void addBody(MessageId messageId, byte[] body) { - bodyCache.put(messageId, body); - } - - byte[] getBody(MessageId messageId) { - return bodyCache.get(messageId); - } - - public LocalAuthor getLocalAuthor() { - return localAuthor; - } - - public void setLocalAuthor( - LocalAuthor localAuthor) { - this.localAuthor = localAuthor; - } - - public Forum getForum() { - return forum; - } - - public void setForum(Forum forum) { - this.forum = forum; - } - - public GroupId getGroupId() { - return groupId; - } - - public void setGroupId(GroupId groupId) { - this.groupId = groupId; - } - - List<ForumEntry> getForumEntries() { - return forumEntries; - } - - void setForumEntries(List<ForumEntry> forumEntries) { - this.forumEntries = forumEntries; - } -} diff --git a/briar-android/src/org/briarproject/android/forum/ForumTestControllerImpl.java b/briar-android/src/org/briarproject/android/forum/ForumTestControllerImpl.java index 2aef2ae5e121fe61e60789800aea97ac75e51a0b..8f90062415305e34021dc4ad87c8f8294245f858 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumTestControllerImpl.java +++ b/briar-android/src/org/briarproject/android/forum/ForumTestControllerImpl.java @@ -1,7 +1,9 @@ package org.briarproject.android.forum; +import org.briarproject.android.controller.handler.ResultHandler; import org.briarproject.android.controller.handler.UiResultHandler; import org.briarproject.api.UniqueId; +import org.briarproject.api.forum.Forum; import org.briarproject.api.identity.AuthorId; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; @@ -63,7 +65,7 @@ public class ForumTestControllerImpl implements ForumController { private ForumEntry[] forumEntries; @Inject - public ForumTestControllerImpl() { + ForumTestControllerImpl() { } @@ -94,7 +96,7 @@ public class ForumTestControllerImpl implements ForumController { @Override public void loadForum(GroupId groupId, - UiResultHandler<Boolean> resultHandler) { + ResultHandler<Boolean> resultHandler) { SecureRandom random = new SecureRandom(); forumEntries = new ForumEntry[100]; // string cut off index @@ -124,14 +126,14 @@ public class ForumTestControllerImpl implements ForumController { } @Override - public String getForumName() { - return "SAGA"; + public Forum getForum() { + return null; } @Override public List<ForumEntry> getForumEntries() { return forumEntries == null ? null : - new ArrayList<ForumEntry>(Arrays.asList(forumEntries)); + new ArrayList<>(Arrays.asList(forumEntries)); } @Override