diff --git a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java index 41fe53fff3ee27be453ddcc3d4b781890df97cde..4f47c3444ad8bacf7f7dc57dfad82725ee8664f1 100644 --- a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java @@ -9,6 +9,7 @@ import org.briarproject.api.blogs.BlogManager; import org.briarproject.api.blogs.BlogPostFactory; import org.briarproject.api.blogs.BlogSharingManager; import org.briarproject.api.clients.ContactGroupFactory; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactManager; @@ -70,6 +71,7 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { lifecycleManager2; private SyncSessionFactory sync0, sync1; private BlogManager blogManager0, blogManager1; + private MessageTracker messageTracker0, messageTracker1; private ContactManager contactManager0, contactManager1, contactManager2; private Contact contact1, contact2, contact01, contact02; private ContactId contactId1, contactId01; @@ -142,6 +144,8 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { contactManager2 = t2.getContactManager(); blogManager0 = t0.getBlogManager(); blogManager1 = t1.getBlogManager(); + messageTracker0 = t0.getMessageTracker(); + messageTracker1 = t1.getMessageTracker(); blogSharingManager0 = t0.getBlogSharingManager(); blogSharingManager1 = t1.getBlogSharingManager(); blogSharingManager2 = t2.getBlogSharingManager(); @@ -192,19 +196,19 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { // get sharing group and assert group message count GroupId g = contactGroupFactory.createContactGroup(CLIENT_ID, contact1) .getId(); - assertGroupCount(blogSharingManager0, g, 1, 0); + assertGroupCount(messageTracker0, g, 1, 0); // sync first request message sync0To1(); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); - assertGroupCount(blogSharingManager1, g, 2, 1); + assertGroupCount(messageTracker1, g, 2, 1); // sync response back sync1To0(); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.responseReceived); - assertGroupCount(blogSharingManager0, g, 2, 1); + assertGroupCount(messageTracker0, g, 2, 1); // blog was added successfully assertEquals(0, blogSharingManager0.getInvitations().size()); @@ -242,8 +246,8 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { assertFalse(blogSharingManager1.canBeShared(blog2.getId(), contact01)); // group message count is still correct - assertGroupCount(blogSharingManager0, g, 2, 1); - assertGroupCount(blogSharingManager1, g, 2, 1); + assertGroupCount(messageTracker0, g, 2, 1); + assertGroupCount(messageTracker1, g, 2, 1); stopLifecycles(); } diff --git a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTestComponent.java index 5515094fb97cb88a6519fbe1757d864149c347b0..d1cde03d4242cb388436625bb01112914b79661f 100644 --- a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTestComponent.java +++ b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTestComponent.java @@ -2,6 +2,7 @@ package org.briarproject; import org.briarproject.api.blogs.BlogManager; import org.briarproject.api.blogs.BlogSharingManager; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.ContactManager; import org.briarproject.api.event.EventBus; import org.briarproject.api.identity.IdentityManager; @@ -82,6 +83,8 @@ interface BlogSharingIntegrationTestComponent { BlogManager getBlogManager(); + MessageTracker getMessageTracker(); + SyncSessionFactory getSyncSessionFactory(); } diff --git a/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java index fd653c56d66e23eaa34f5cbe45d8d35019733ab5..3436fe962ec9c22d37033c876c83f6ae3a1c2b23 100644 --- a/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java @@ -9,7 +9,7 @@ import static org.junit.Assert.assertEquals; public abstract class BriarIntegrationTest extends BriarTestCase { - protected void assertGroupCount(MessageTracker tracker, GroupId g, + protected static void assertGroupCount(MessageTracker tracker, GroupId g, long msgCount, long unreadCount, long latestMsg) throws DbException { @@ -19,7 +19,7 @@ public abstract class BriarIntegrationTest extends BriarTestCase { assertEquals(latestMsg, groupCount.getLatestMsgTime()); } - protected void assertGroupCount(MessageTracker tracker, GroupId g, + protected static void assertGroupCount(MessageTracker tracker, GroupId g, long msgCount, long unreadCount) throws DbException { GroupCount c1 = tracker.getGroupCount(g); diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java index 07e11e038f93ba4cc85908a71e33d2f384616e04..e574d224ae38278d9edd50ee43d0fbf4c50d4658 100644 --- a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java @@ -4,11 +4,11 @@ import junit.framework.Assert; import net.jodah.concurrentunit.Waiter; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactManager; import org.briarproject.api.crypto.CryptoComponent; -import org.briarproject.api.crypto.KeyPair; import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.db.DbException; import org.briarproject.api.event.Event; @@ -66,6 +66,7 @@ public class ForumManagerTest extends BriarIntegrationTest { private SyncSessionFactory sync0, sync1; private ForumManager forumManager0, forumManager1; private ContactManager contactManager0, contactManager1; + private MessageTracker messageTracker0, messageTracker1; private ContactId contactId0,contactId1; private IdentityManager identityManager0, identityManager1; private LocalAuthor author0, author1; @@ -118,6 +119,8 @@ public class ForumManagerTest extends BriarIntegrationTest { identityManager1 = t1.getIdentityManager(); contactManager0 = t0.getContactManager(); contactManager1 = t1.getContactManager(); + messageTracker0 = t0.getMessageTracker(); + messageTracker1 = t1.getMessageTracker(); forumManager0 = t0.getForumManager(); forumManager1 = t1.getForumManager(); forumSharingManager0 = t0.getForumSharingManager(); @@ -156,16 +159,16 @@ public class ForumManagerTest extends BriarIntegrationTest { forumManager0.addLocalPost(post1); forumManager0.setReadFlag(forum.getGroup().getId(), post1.getMessage().getId(), true); - assertGroupCount(forumManager0, forum.getGroup().getId(), 1, 0, + assertGroupCount(messageTracker0, forum.getGroup().getId(), 1, 0, post1.getMessage().getTimestamp()); forumManager0.addLocalPost(post2); forumManager0.setReadFlag(forum.getGroup().getId(), post2.getMessage().getId(), false); - assertGroupCount(forumManager0, forum.getGroup().getId(), 2, 1, + assertGroupCount(messageTracker0, forum.getGroup().getId(), 2, 1, post2.getMessage().getTimestamp()); forumManager0.setReadFlag(forum.getGroup().getId(), post2.getMessage().getId(), false); - assertGroupCount(forumManager0, forum.getGroup().getId(), 2, 1, + assertGroupCount(messageTracker0, forum.getGroup().getId(), 2, 1, post2.getMessage().getTimestamp()); Collection<ForumPostHeader> headers = forumManager0.getPostHeaders(forum.getGroup().getId()); @@ -215,14 +218,14 @@ public class ForumManagerTest extends BriarIntegrationTest { forumManager0.addLocalPost(post1); assertEquals(1, forumManager0.getPostHeaders(g).size()); assertEquals(0, forumManager1.getPostHeaders(g).size()); - assertGroupCount(forumManager0, g, 1, 0, time); - assertGroupCount(forumManager1, g, 0, 0, 0); + assertGroupCount(messageTracker0, g, 1, 0, time); + assertGroupCount(messageTracker1, g, 0, 0, 0); // send post to 1 sync0To1(); deliveryWaiter.await(TIMEOUT, 1); assertEquals(1, forumManager1.getPostHeaders(g).size()); - assertGroupCount(forumManager1, g, 1, 1, time); + assertGroupCount(messageTracker1, g, 1, 1, time); // add another forum post long time2 = clock.currentTimeMillis(); @@ -230,14 +233,14 @@ public class ForumManagerTest extends BriarIntegrationTest { forumManager1.addLocalPost(post2); assertEquals(1, forumManager0.getPostHeaders(g).size()); assertEquals(2, forumManager1.getPostHeaders(g).size()); - assertGroupCount(forumManager0, g, 1, 0, time); - assertGroupCount(forumManager1, g, 2, 1, time2); + assertGroupCount(messageTracker0, g, 1, 0, time); + assertGroupCount(messageTracker1, g, 2, 1, time2); // send post to 0 sync1To0(); deliveryWaiter.await(TIMEOUT, 1); assertEquals(2, forumManager1.getPostHeaders(g).size()); - assertGroupCount(forumManager0, g, 2, 1, time2); + assertGroupCount(messageTracker0, g, 2, 1, time2); stopLifecycles(); } diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTestComponent.java index fee35a0088438d7d5d04547f210002e58c3de28f..24278e4af5e878c5c16e9ff55730fd0fa52044cd 100644 --- a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTestComponent.java +++ b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTestComponent.java @@ -1,5 +1,6 @@ package org.briarproject; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.ContactManager; import org.briarproject.api.event.EventBus; import org.briarproject.api.forum.ForumManager; @@ -78,6 +79,8 @@ interface ForumManagerTestComponent { ContactManager getContactManager(); + MessageTracker getMessageTracker(); + ForumSharingManager getForumSharingManager(); ForumManager getForumManager(); diff --git a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java index 90beb6595796b115400bcb8b1513286bd5b7e409..d3745f08b00c7ad667cb7f1ce7a1a6f6544e3a0c 100644 --- a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java @@ -9,6 +9,7 @@ import org.briarproject.TestDatabaseModule; import org.briarproject.TestUtils; import org.briarproject.api.FormatException; import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -105,6 +106,7 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { lifecycleManager2; private SyncSessionFactory sync0, sync1, sync2; private ContactManager contactManager0, contactManager1, contactManager2; + private MessageTracker messageTracker0, messageTracker1, messageTracker2; private ContactId contactId0, contactId1, contactId2; private IdentityManager identityManager0, identityManager1, identityManager2; @@ -172,6 +174,9 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { contactManager0 = t0.getContactManager(); contactManager1 = t1.getContactManager(); contactManager2 = t2.getContactManager(); + messageTracker0 = t0.getMessageTracker(); + messageTracker1 = t1.getMessageTracker(); + messageTracker2 = t2.getMessageTracker(); introductionManager0 = t0.getIntroductionManager(); introductionManager1 = t1.getIntroductionManager(); introductionManager2 = t2.getIntroductionManager(); @@ -205,38 +210,38 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { .createIntroductionGroup(introducee1); Group g2 = introductionGroupFactory .createIntroductionGroup(introducee2); - assertGroupCount(introductionManager0, g1.getId(), 1, 0, time); - assertGroupCount(introductionManager0, g2.getId(), 1, 0, time); + assertGroupCount(messageTracker0, g1.getId(), 1, 0, time); + assertGroupCount(messageTracker0, g2.getId(), 1, 0, time); // sync first request message deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); - assertGroupCount(introductionManager1, g1.getId(), 2, 1); + assertGroupCount(messageTracker1, g1.getId(), 2, 1); // sync second request message deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); eventWaiter.await(TIMEOUT, 1); assertTrue(listener2.requestReceived); - assertGroupCount(introductionManager2, g2.getId(), 2, 1); + assertGroupCount(messageTracker2, g2.getId(), 2, 1); // sync first response deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.response1Received); - assertGroupCount(introductionManager0, g1.getId(), 2, 1); + assertGroupCount(messageTracker0, g1.getId(), 2, 1); // sync second response deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0"); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.response2Received); - assertGroupCount(introductionManager0, g2.getId(), 2, 1); + assertGroupCount(messageTracker0, g2.getId(), 2, 1); // sync forwarded responses to introducees deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); - assertGroupCount(introductionManager1, g1.getId(), 3, 2); - assertGroupCount(introductionManager2, g2.getId(), 3, 2); + assertGroupCount(messageTracker1, g1.getId(), 3, 2); + assertGroupCount(messageTracker2, g2.getId(), 3, 2); // sync first ACK and its forward deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); @@ -269,10 +274,10 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { } assertDefaultUiMessages(); - assertGroupCount(introductionManager0, g1.getId(), 2, 1); - assertGroupCount(introductionManager0, g2.getId(), 2, 1); - assertGroupCount(introductionManager1, g1.getId(), 3, 2); - assertGroupCount(introductionManager2, g2.getId(), 3, 2); + assertGroupCount(messageTracker0, g1.getId(), 2, 1); + assertGroupCount(messageTracker0, g2.getId(), 2, 1); + assertGroupCount(messageTracker1, g1.getId(), 3, 2); + assertGroupCount(messageTracker2, g2.getId(), 3, 2); } finally { stopLifecycles(); } diff --git a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTestComponent.java index 617fa1cee530f83f0125018fdda60e0ac80c71fe..1741364824258fd826122d5814cb27bd133144d6 100644 --- a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTestComponent.java +++ b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTestComponent.java @@ -4,6 +4,7 @@ import org.briarproject.TestDatabaseModule; import org.briarproject.TestPluginsModule; import org.briarproject.TestSeedProviderModule; import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.ContactManager; import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.event.EventBus; @@ -50,7 +51,7 @@ import dagger.Component; PropertiesModule.class, MessagingModule.class }) -public interface IntroductionIntegrationTestComponent { +interface IntroductionIntegrationTestComponent { void inject(IntroductionIntegrationTest testCase); @@ -82,6 +83,8 @@ public interface IntroductionIntegrationTestComponent { TransportPropertyManager getTransportPropertyManager(); + MessageTracker getMessageTracker(); + SyncSessionFactory getSyncSessionFactory(); /* the following methods are only needed to manually construct messages */ diff --git a/briar-api/src/org/briarproject/api/clients/MessageQueueManager.java b/briar-api/src/org/briarproject/api/clients/MessageQueueManager.java index b5b49ad16adb1a06e3525ae94cfca59928325a39..0766e5e4be1adfaed44267f08b2b3f1804aa39bf 100644 --- a/briar-api/src/org/briarproject/api/clients/MessageQueueManager.java +++ b/briar-api/src/org/briarproject/api/clients/MessageQueueManager.java @@ -1,14 +1,15 @@ package org.briarproject.api.clients; -import org.briarproject.api.FormatException; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Metadata; import org.briarproject.api.db.Transaction; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.MessageContext; +@NotNullByDefault public interface MessageQueueManager { /** @@ -52,17 +53,17 @@ public interface MessageQueueManager { * * @throws DbException Should only be used for real database errors. * If this is thrown, delivery will be attempted again at next startup, - * whereas if an FormatException is thrown, + * whereas if an InvalidMessageException is thrown, * the message will be permanently invalidated. - * @throws FormatException for any non-database error + * @throws InvalidMessageException for any non-database error * that occurs while handling remotely created data. * This includes errors that occur while handling locally created data * in a context controlled by remotely created data * (for example, parsing the metadata of a dependency * of an incoming message). - * Never rethrow DbException as FormatException! + * Never rethrow DbException as InvalidMessageException! */ void incomingMessage(Transaction txn, QueueMessage q, Metadata meta) - throws DbException, FormatException; + throws DbException, InvalidMessageException; } } diff --git a/briar-api/src/org/briarproject/api/clients/MessageTracker.java b/briar-api/src/org/briarproject/api/clients/MessageTracker.java index a73c87183fa949d61cd7858c2a6a443e99236f46..6351491c74742bc1e0f50eab04ce368bc02089b1 100644 --- a/briar-api/src/org/briarproject/api/clients/MessageTracker.java +++ b/briar-api/src/org/briarproject/api/clients/MessageTracker.java @@ -1,9 +1,13 @@ package org.briarproject.api.clients; import org.briarproject.api.db.DbException; +import org.briarproject.api.db.Transaction; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.GroupId; +import org.briarproject.api.sync.Message; import org.briarproject.api.sync.MessageId; +@NotNullByDefault public interface MessageTracker { /** @@ -13,11 +17,34 @@ public interface MessageTracker { GroupCount getGroupCount(GroupId g) throws DbException; /** - * Marks a message as read or unread and updates the group counts in g. + * Gets the number of visible and unread messages in the group + * as well as the timestamp of the latest message **/ + GroupCount getGroupCount(Transaction txn, GroupId g) throws DbException; + + /** + * Updates the group count for the given incoming message. + */ + void trackIncomingMessage(Transaction txn, Message m) throws DbException; + + /** + * Updates the group count for the given outgoing message. + */ + void trackOutgoingMessage(Transaction txn, Message m) throws DbException; + + /** + * Updates the group count for the given message. + */ + void trackMessage(Transaction txn, GroupId g, long timestamp, boolean read) + throws DbException; + + /** + * Marks a message as read or unread and updates the group count. + */ void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException; class GroupCount { + private final int msgCount, unreadCount; private final long latestMsgTime; diff --git a/briar-api/src/org/briarproject/api/forum/ForumManager.java b/briar-api/src/org/briarproject/api/forum/ForumManager.java index 37aadb723b7798d4429d5feee69214fc1da0728b..75c9b9eafc912f12561144834bf240e65700c256 100644 --- a/briar-api/src/org/briarproject/api/forum/ForumManager.java +++ b/briar-api/src/org/briarproject/api/forum/ForumManager.java @@ -1,10 +1,11 @@ package org.briarproject.api.forum; -import org.briarproject.api.clients.MessageTracker; +import org.briarproject.api.clients.MessageTracker.GroupCount; import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Transaction; import org.briarproject.api.identity.LocalAuthor; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; @@ -12,43 +13,76 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; -public interface ForumManager extends MessageTracker { +@NotNullByDefault +public interface ForumManager { - /** The unique ID of the forum client. */ + /** + * The unique ID of the forum client. + */ ClientId CLIENT_ID = new ClientId("org.briarproject.briar.forum"); - /** Subscribes to a forum. */ + /** + * Subscribes to a forum. + */ Forum addForum(String name) throws DbException; - /** Unsubscribes from a forum. */ + /** + * Unsubscribes from a forum. + */ void removeForum(Forum f) throws DbException; - /** Creates a local forum post. */ + /** + * Creates a local forum post. + */ @CryptoExecutor ForumPost createLocalPost(GroupId groupId, String body, long timestamp, @Nullable MessageId parentId, LocalAuthor author); - /** Stores a local forum post. */ + /** + * Stores a local forum post. + */ ForumPostHeader addLocalPost(ForumPost p) throws DbException; - /** Returns the forum with the given ID. */ + /** + * Returns the forum with the given ID. + */ Forum getForum(GroupId g) throws DbException; - /** Returns the forum with the given ID. */ + /** + * Returns the forum with the given ID. + */ Forum getForum(Transaction txn, GroupId g) throws DbException; - /** Returns all forums to which the user subscribes. */ + /** + * Returns all forums to which the user subscribes. + */ Collection<Forum> getForums() throws DbException; - /** Returns the body of the forum post with the given ID. */ + /** + * Returns the body of the forum post with the given ID. + */ String getPostBody(MessageId m) throws DbException; - /** Returns the headers of all posts in the given forum. */ + /** + * Returns the headers of all posts in the given forum. + */ Collection<ForumPostHeader> getPostHeaders(GroupId g) throws DbException; - /** Registers a hook to be called whenever a forum is removed. */ + /** + * Registers a hook to be called whenever a forum is removed. + */ void registerRemoveForumHook(RemoveForumHook hook); + /** + * Returns the group count for the given forum. + */ + GroupCount getGroupCount(GroupId g) throws DbException; + + /** + * Marks a message as read or unread and updates the group count. + */ + void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException; + interface RemoveForumHook { void removingForum(Transaction txn, Forum f) throws DbException; } diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java b/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java index 6914318d833b95d2b213bc2e2cb34e107cf94819..12cc01323d3cf012f617a03981525ac4a620612f 100644 --- a/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java +++ b/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java @@ -1,16 +1,18 @@ package org.briarproject.api.introduction; import org.briarproject.api.FormatException; -import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.db.DbException; +import org.briarproject.api.messaging.ConversationManager.ConversationClient; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.ClientId; import java.util.Collection; -public interface IntroductionManager extends MessageTracker { +@NotNullByDefault +public interface IntroductionManager extends ConversationClient { /** The unique ID of the introduction client. */ ClientId CLIENT_ID = new ClientId("org.briarproject.briar.introduction"); diff --git a/briar-api/src/org/briarproject/api/messaging/ConversationManager.java b/briar-api/src/org/briarproject/api/messaging/ConversationManager.java index a48a8ade84aa4ae6083e46ff29aae93c5d6a81c5..69ecc3016a7bdddc60f1ff35969f9816bae72f98 100644 --- a/briar-api/src/org/briarproject/api/messaging/ConversationManager.java +++ b/briar-api/src/org/briarproject/api/messaging/ConversationManager.java @@ -1,10 +1,16 @@ package org.briarproject.api.messaging; import org.briarproject.api.clients.MessageTracker.GroupCount; +import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Transaction; +import org.briarproject.api.nullsafety.NotNullByDefault; +import org.briarproject.api.sync.Group; +import org.briarproject.api.sync.GroupId; +import org.briarproject.api.sync.MessageId; +@NotNullByDefault public interface ConversationManager { /** @@ -13,11 +19,19 @@ public interface ConversationManager { */ void registerConversationClient(ConversationClient client); - /** Get the unified group count for all private conversation messages. */ - GroupCount getGroupCount(ContactId contactId) throws DbException; + /** + * Get the unified group count for all private conversation messages. + */ + GroupCount getGroupCount(ContactId c) throws DbException; interface ConversationClient { - GroupCount getGroupCount(Transaction txn, ContactId contactId) + + Group getContactGroup(Contact c); + + GroupCount getGroupCount(Transaction txn, ContactId c) + throws DbException; + + void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException; } diff --git a/briar-api/src/org/briarproject/api/messaging/MessagingManager.java b/briar-api/src/org/briarproject/api/messaging/MessagingManager.java index c6de1772f1dded122d3249a3ed00f802e3041552..78c7c4a7593d6e8f7135c404ae5bee961198d0b8 100644 --- a/briar-api/src/org/briarproject/api/messaging/MessagingManager.java +++ b/briar-api/src/org/briarproject/api/messaging/MessagingManager.java @@ -1,15 +1,17 @@ package org.briarproject.api.messaging; -import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.ContactId; import org.briarproject.api.db.DbException; +import org.briarproject.api.messaging.ConversationManager.ConversationClient; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; import java.util.Collection; -public interface MessagingManager extends MessageTracker { +@NotNullByDefault +public interface MessagingManager extends ConversationClient { /** The unique ID of the messaging client. */ ClientId CLIENT_ID = new ClientId("org.briarproject.briar.messaging"); diff --git a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java b/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java index 636678052d41359dd1ba0c8aefcc04a823167807..0a203e23ba2c04eac02fc67ed1f0531c89b54501 100644 --- a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java +++ b/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java @@ -1,7 +1,7 @@ package org.briarproject.api.privategroup; import org.briarproject.api.FormatException; -import org.briarproject.api.clients.MessageTracker; +import org.briarproject.api.clients.MessageTracker.GroupCount; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Transaction; import org.briarproject.api.identity.Author; @@ -14,7 +14,7 @@ import org.briarproject.api.sync.MessageId; import java.util.Collection; @NotNullByDefault -public interface PrivateGroupManager extends MessageTracker { +public interface PrivateGroupManager { /** * The unique ID of the private group client. @@ -24,9 +24,9 @@ public interface PrivateGroupManager extends MessageTracker { /** * Adds a new private group and joins it. * - * @param group The private group to add - * @param joinMsg The creators's join message - * @param creator True if the group is added by its creator + * @param group The private group to add + * @param joinMsg The creators's join message + * @param creator True if the group is added by its creator */ void addPrivateGroup(PrivateGroup group, GroupMessage joinMsg, boolean creator) throws DbException; @@ -34,9 +34,9 @@ public interface PrivateGroupManager extends MessageTracker { /** * Adds a new private group and joins it. * - * @param group The private group to add - * @param joinMsg The new member's join message - * @param creator True if the group is added by its creator + * @param group The private group to add + * @param joinMsg The new member's join message + * @param creator True if the group is added by its creator */ void addPrivateGroup(Transaction txn, PrivateGroup group, GroupMessage joinMsg, boolean creator) throws DbException; @@ -107,13 +107,23 @@ public interface PrivateGroupManager extends MessageTracker { */ boolean isMember(Transaction txn, GroupId g, Author a) throws DbException; + /** + * Returns the group count for the given group. + */ + GroupCount getGroupCount(GroupId g) throws DbException; + + /** + * Marks a message as read or unread and updates the group count. + */ + void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException; + /** * This method needs to be called when a contact relationship * has been revealed between the user and the Author with AuthorId a * in the Group identified by the GroupId g. * * @param byContact true if the remote contact has revealed - * the relationship first. Otherwise false. + * the relationship first. Otherwise false. */ void relationshipRevealed(Transaction txn, GroupId g, AuthorId a, boolean byContact) throws FormatException, DbException; diff --git a/briar-api/src/org/briarproject/api/sharing/SharingManager.java b/briar-api/src/org/briarproject/api/sharing/SharingManager.java index 934818f955ccd9af4f370c13d5a914e245f5eef2..66b6ef82f6c275763d6f8a9e5c2720836d0c4b93 100644 --- a/briar-api/src/org/briarproject/api/sharing/SharingManager.java +++ b/briar-api/src/org/briarproject/api/sharing/SharingManager.java @@ -1,15 +1,18 @@ package org.briarproject.api.sharing; -import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.db.DbException; +import org.briarproject.api.messaging.ConversationManager.ConversationClient; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.GroupId; import java.util.Collection; -public interface SharingManager<S extends Shareable> extends MessageTracker { +@NotNullByDefault +public interface SharingManager<S extends Shareable> + extends ConversationClient { /** * Sends an invitation to share the given group with the given contact diff --git a/briar-api/src/org/briarproject/api/sync/MessageFactory.java b/briar-api/src/org/briarproject/api/sync/MessageFactory.java index 6b599a8f1fb8dfafbf9d643f2318e8de560fc122..191770e2c269cc6f447f132bdd349319e3f7054e 100644 --- a/briar-api/src/org/briarproject/api/sync/MessageFactory.java +++ b/briar-api/src/org/briarproject/api/sync/MessageFactory.java @@ -1,5 +1,8 @@ package org.briarproject.api.sync; +import org.briarproject.api.nullsafety.NotNullByDefault; + +@NotNullByDefault public interface MessageFactory { Message createMessage(GroupId g, long timestamp, byte[] body); diff --git a/briar-api/src/org/briarproject/api/sync/ValidationManager.java b/briar-api/src/org/briarproject/api/sync/ValidationManager.java index 911ba4771831f7b718ab2329292d690fb280af90..b35a0bd8fd85ba0972f164ab8b675953370e735d 100644 --- a/briar-api/src/org/briarproject/api/sync/ValidationManager.java +++ b/briar-api/src/org/briarproject/api/sync/ValidationManager.java @@ -3,11 +3,13 @@ package org.briarproject.api.sync; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Metadata; import org.briarproject.api.db.Transaction; +import org.briarproject.api.nullsafety.NotNullByDefault; /** * Responsible for managing message validators and passing them messages to * validate. */ +@NotNullByDefault public interface ValidationManager { enum State { diff --git a/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java b/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java index e591fd2d2b986726f57effd25a7293209d6110eb..cfb4706894501bf75fdbd07f6791e0478660eb4a 100644 --- a/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java +++ b/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java @@ -27,6 +27,7 @@ import org.briarproject.api.identity.Author.Status; import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.LocalAuthor; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.Message; @@ -69,6 +70,7 @@ import static org.briarproject.api.contact.ContactManager.AddContactHook; import static org.briarproject.api.contact.ContactManager.RemoveContactHook; import static org.briarproject.blogs.BlogPostValidator.authorToBdfDictionary; +@NotNullByDefault class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, AddContactHook, RemoveContactHook, Client { @@ -127,10 +129,8 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, @Override public void removingContact(Transaction txn, Contact c) throws DbException { - if (c != null) { - Blog b = blogFactory.createBlog(c.getAuthor()); - db.removeGroup(txn, b.getGroup()); - } + Blog b = blogFactory.createBlog(c.getAuthor()); + db.removeGroup(txn, b.getGroup()); } @Override diff --git a/briar-core/src/org/briarproject/blogs/BlogPostValidator.java b/briar-core/src/org/briarproject/blogs/BlogPostValidator.java index dfbe7709897b3ab36fd7f60146367af5bddb0370..088354fc1697caa67d714f2eb554fc4a332e42e5 100644 --- a/briar-core/src/org/briarproject/blogs/BlogPostValidator.java +++ b/briar-core/src/org/briarproject/blogs/BlogPostValidator.java @@ -11,6 +11,7 @@ import org.briarproject.api.data.BdfEntry; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.identity.Author; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.GroupFactory; import org.briarproject.api.sync.InvalidMessageException; @@ -42,6 +43,7 @@ import static org.briarproject.api.blogs.MessageType.COMMENT; import static org.briarproject.api.blogs.MessageType.POST; import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; +@NotNullByDefault class BlogPostValidator extends BdfMessageValidator { private final GroupFactory groupFactory; @@ -76,10 +78,10 @@ class BlogPostValidator extends BdfMessageValidator { addMessageMetadata(c, m.getTimestamp()); break; case WRAPPED_POST: - c = validateWrappedPost(m, g, body); + c = validateWrappedPost(body); break; case WRAPPED_COMMENT: - c = validateWrappedComment(m, g, body); + c = validateWrappedComment(body); break; default: throw new InvalidMessageException("Unknown Message Type"); @@ -164,8 +166,8 @@ class BlogPostValidator extends BdfMessageValidator { return new BdfMessageContext(meta, dependencies); } - private BdfMessageContext validateWrappedPost(Message m, Group g, - BdfList body) throws InvalidMessageException, FormatException { + private BdfMessageContext validateWrappedPost(BdfList body) + throws InvalidMessageException, FormatException { // p_group descriptor, p_timestamp, p_content, p_signature checkSize(body, 4); @@ -202,8 +204,8 @@ class BlogPostValidator extends BdfMessageValidator { return new BdfMessageContext(meta); } - private BdfMessageContext validateWrappedComment(Message m, Group g, - BdfList body) throws InvalidMessageException, FormatException { + private BdfMessageContext validateWrappedComment(BdfList body) + throws InvalidMessageException, FormatException { // c_group descriptor, c_timestamp, c_comment, c_parent_original_id, // c_parent_id, c_signature, parent_id diff --git a/briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java b/briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java index 43de4f400db948e4a4acba0b787bbf3620fbf4c7..41c402133433d3006acc34346d81b0fd28cbed60 100644 --- a/briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java +++ b/briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java @@ -3,31 +3,25 @@ package org.briarproject.clients; import org.briarproject.api.FormatException; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.MessageQueueManager.IncomingQueueMessageHook; -import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.QueueMessage; import org.briarproject.api.data.BdfDictionary; -import org.briarproject.api.data.BdfEntry; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataParser; import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Metadata; import org.briarproject.api.db.Transaction; -import org.briarproject.api.sync.GroupId; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.Message; -import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.ValidationManager.IncomingMessageHook; import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; -import static org.briarproject.clients.BdfConstants.GROUP_KEY_LATEST_MSG; -import static org.briarproject.clients.BdfConstants.GROUP_KEY_MSG_COUNT; -import static org.briarproject.clients.BdfConstants.GROUP_KEY_UNREAD_COUNT; -import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; +@NotNullByDefault public abstract class BdfIncomingMessageHook implements IncomingMessageHook, - IncomingQueueMessageHook, MessageTracker { + IncomingQueueMessageHook { protected final DatabaseComponent db; protected final ClientHelper clientHelper; @@ -44,16 +38,16 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook, * Called once for each incoming message that passes validation. * * @throws DbException Should only be used for real database errors. - * Do not rethrow + * If this is thrown, delivery will be attempted again at next startup, + * whereas if a FormatException is thrown, the message will be permanently + * invalidated. * @throws FormatException Use this for any non-database error * that occurs while handling remotely created data. * This includes errors that occur while handling locally created data * in a context controlled by remotely created data * (for example, parsing the metadata of a dependency * of an incoming message). - * Throwing this will delete the incoming message and its metadata - * marking it as invalid in the database. - * Never rethrow DbException as FormatException + * Never rethrow DbException as FormatException! */ protected abstract boolean incomingMessage(Transaction txn, Message m, BdfList body, BdfDictionary meta) throws DbException, @@ -71,8 +65,12 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook, @Override public void incomingMessage(Transaction txn, QueueMessage q, Metadata meta) - throws DbException, FormatException { - incomingMessage(txn, q, meta, QUEUE_MESSAGE_HEADER_LENGTH); + throws DbException, InvalidMessageException { + try { + incomingMessage(txn, q, meta, QUEUE_MESSAGE_HEADER_LENGTH); + } catch (FormatException e) { + throw new InvalidMessageException(e); + } } private boolean incomingMessage(Transaction txn, Message m, Metadata meta, @@ -84,102 +82,4 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook, return incomingMessage(txn, m, body, metaDictionary); } - protected void trackIncomingMessage(Transaction txn, Message m) - throws DbException { - trackMessage(txn, m.getGroupId(), m.getTimestamp(), false); - } - - protected void trackOutgoingMessage(Transaction txn, Message m) - throws DbException { - trackMessage(txn, m.getGroupId(), m.getTimestamp(), true); - } - - protected void trackMessage(Transaction txn, GroupId g, long time, - boolean read) throws DbException { - GroupCount c = getGroupCount(txn, g); - int msgCount = c.getMsgCount() + 1; - int unreadCount = c.getUnreadCount() + (read ? 0 : 1); - long latestTime = - time > c.getLatestMsgTime() ? time : c.getLatestMsgTime(); - storeGroupCount(txn, g, - new GroupCount(msgCount, unreadCount, latestTime)); - } - - @Override - public GroupCount getGroupCount(GroupId g) throws DbException { - GroupCount count; - Transaction txn = db.startTransaction(true); - try { - count = getGroupCount(txn, g); - db.commitTransaction(txn); - } - finally { - db.endTransaction(txn); - } - return count; - } - - protected GroupCount getGroupCount(Transaction txn, GroupId g) - throws DbException { - GroupCount count; - try { - BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g); - count = new GroupCount( - d.getLong(GROUP_KEY_MSG_COUNT, 0L).intValue(), - d.getLong(GROUP_KEY_UNREAD_COUNT, 0L).intValue(), - d.getLong(GROUP_KEY_LATEST_MSG, 0L) - ); - } catch (FormatException e) { - throw new DbException(e); - } - return count; - } - - private void storeGroupCount(Transaction txn, GroupId g, GroupCount c) - throws DbException{ - try { - BdfDictionary d = BdfDictionary.of( - new BdfEntry(GROUP_KEY_MSG_COUNT, c.getMsgCount()), - new BdfEntry(GROUP_KEY_UNREAD_COUNT, c.getUnreadCount()), - new BdfEntry(GROUP_KEY_LATEST_MSG, c.getLatestMsgTime()) - ); - clientHelper.mergeGroupMetadata(txn, g, d); - } catch (FormatException e) { - throw new DbException(e); - } - } - - @Override - public void setReadFlag(GroupId g, MessageId m, boolean read) - throws DbException { - Transaction txn = db.startTransaction(false); - try { - // check current read status of message - BdfDictionary old = - clientHelper.getMessageMetadataAsDictionary(txn, m); - boolean wasRead = old.getBoolean(MSG_KEY_READ, false); - - // if status changed - if (wasRead != read) { - // mark individual message as read - BdfDictionary meta = new BdfDictionary(); - meta.put(MSG_KEY_READ, read); - clientHelper.mergeMessageMetadata(txn, m, meta); - - // update unread counter in group metadata - GroupCount c = getGroupCount(txn, g); - BdfDictionary d = new BdfDictionary(); - int count = c.getUnreadCount() + (read ? -1 : 1); - if (count < 0) throw new DbException(); - d.put(GROUP_KEY_UNREAD_COUNT, count); - clientHelper.mergeGroupMetadata(txn, g, d); - } - db.commitTransaction(txn); - } catch (FormatException e) { - throw new DbException(e); - } finally { - db.endTransaction(txn); - } - } - } diff --git a/briar-core/src/org/briarproject/clients/BdfMessageValidator.java b/briar-core/src/org/briarproject/clients/BdfMessageValidator.java index 2a78e794dd05b74f22a6262071e981fea975ade7..700724766586b54d99767b4bdca4eb74663e0023 100644 --- a/briar-core/src/org/briarproject/clients/BdfMessageValidator.java +++ b/briar-core/src/org/briarproject/clients/BdfMessageValidator.java @@ -9,6 +9,7 @@ import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.db.Metadata; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.Message; @@ -25,6 +26,7 @@ import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LEN import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE; +@NotNullByDefault public abstract class BdfMessageValidator implements MessageValidator, QueueMessageValidator { @@ -108,7 +110,7 @@ public abstract class BdfMessageValidator implements MessageValidator, if (b != null && b.length != length) throw new FormatException(); } - protected void checkSize(BdfList list, int minSize, int maxSize) + protected void checkSize(@Nullable BdfList list, int minSize, int maxSize) throws FormatException { if (list != null) { if (list.size() < minSize) throw new FormatException(); diff --git a/briar-core/src/org/briarproject/clients/ClientsModule.java b/briar-core/src/org/briarproject/clients/ClientsModule.java index 480c7f016d1439ebce37e7ab691c6ae629fafbc3..cd8e17538aece2ec4ae6185b7de24b3a5eadc596 100644 --- a/briar-core/src/org/briarproject/clients/ClientsModule.java +++ b/briar-core/src/org/briarproject/clients/ClientsModule.java @@ -3,6 +3,7 @@ package org.briarproject.clients; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.MessageQueueManager; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.QueueMessageFactory; import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.data.BdfReaderFactory; @@ -52,4 +53,8 @@ public class ClientsModule { return new QueueMessageFactoryImpl(crypto); } + @Provides + MessageTracker provideMessageTracker(MessageTrackerImpl messageTracker) { + return messageTracker; + } } diff --git a/briar-core/src/org/briarproject/clients/ConversationClientImpl.java b/briar-core/src/org/briarproject/clients/ConversationClientImpl.java index 807e6d2f1c5b01c82a97365c43070ed87730ad0f..a19e939fc5fa29ab2e31ea2b6c0d3c9552076ce0 100644 --- a/briar-core/src/org/briarproject/clients/ConversationClientImpl.java +++ b/briar-core/src/org/briarproject/clients/ConversationClientImpl.java @@ -1,6 +1,8 @@ package org.briarproject.clients; import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.clients.MessageTracker; +import org.briarproject.api.clients.MessageTracker.GroupCount; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.data.MetadataParser; @@ -8,25 +10,34 @@ import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Transaction; import org.briarproject.api.messaging.ConversationManager.ConversationClient; -import org.briarproject.api.sync.Group; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.GroupId; +import org.briarproject.api.sync.MessageId; +@NotNullByDefault public abstract class ConversationClientImpl extends BdfIncomingMessageHook implements ConversationClient { + protected final MessageTracker messageTracker; + protected ConversationClientImpl(DatabaseComponent db, - ClientHelper clientHelper, MetadataParser metadataParser) { + ClientHelper clientHelper, MetadataParser metadataParser, + MessageTracker messageTracker) { super(db, clientHelper, metadataParser); + this.messageTracker = messageTracker; } - protected abstract Group getContactGroup(Contact contact); - @Override public GroupCount getGroupCount(Transaction txn, ContactId contactId) throws DbException { Contact contact = db.getContact(txn, contactId); GroupId groupId = getContactGroup(contact).getId(); - return getGroupCount(txn, groupId); + return messageTracker.getGroupCount(txn, groupId); } + @Override + public void setReadFlag(GroupId g, MessageId m, boolean read) + throws DbException { + messageTracker.setReadFlag(g, m, read); + } } diff --git a/briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java b/briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java index bcb9ff72dbfa38b20df92a3c57462af16669ba2f..d666598509dd68f5ff2f43e70d26e529d68f0e00 100644 --- a/briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java +++ b/briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java @@ -11,6 +11,7 @@ import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Metadata; import org.briarproject.api.db.Transaction; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.GroupId; @@ -20,6 +21,7 @@ import org.briarproject.api.sync.MessageContext; import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.ValidationManager; import org.briarproject.api.sync.ValidationManager.IncomingMessageHook; +import org.briarproject.api.sync.ValidationManager.MessageValidator; import org.briarproject.util.ByteUtils; import java.util.ArrayList; @@ -29,12 +31,14 @@ import java.util.Map.Entry; import java.util.TreeMap; import java.util.logging.Logger; +import javax.annotation.Nullable; import javax.inject.Inject; import static java.util.logging.Level.INFO; import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; +@NotNullByDefault class MessageQueueManagerImpl implements MessageQueueManager { private static final String OUTGOING_POSITION_KEY = "nextOut"; @@ -139,6 +143,7 @@ class MessageQueueManagerImpl implements MessageQueueManager { this.pending = pending; } + @Nullable MessageId popIncomingMessageId() { Iterator<Entry<Long, MessageId>> it = pending.entrySet().iterator(); if (!it.hasNext()) { @@ -161,8 +166,9 @@ class MessageQueueManagerImpl implements MessageQueueManager { } } + @NotNullByDefault private static class DelegatingMessageValidator - implements ValidationManager.MessageValidator { + implements MessageValidator { private final QueueMessageValidator delegate; @@ -174,21 +180,24 @@ class MessageQueueManagerImpl implements MessageQueueManager { public MessageContext validateMessage(Message m, Group g) throws InvalidMessageException { byte[] raw = m.getRaw(); - if (raw.length < QUEUE_MESSAGE_HEADER_LENGTH) return null; + if (raw.length < QUEUE_MESSAGE_HEADER_LENGTH) + throw new InvalidMessageException(); long queuePosition = ByteUtils.readUint64(raw, MESSAGE_HEADER_LENGTH); - if (queuePosition < 0) return null; + if (queuePosition < 0) throw new InvalidMessageException(); QueueMessage q = new QueueMessage(m.getId(), m.getGroupId(), m.getTimestamp(), queuePosition, raw); return delegate.validateMessage(q, g); } } + @NotNullByDefault private class DelegatingIncomingMessageHook implements IncomingMessageHook { private final IncomingQueueMessageHook delegate; - private DelegatingIncomingMessageHook(IncomingQueueMessageHook delegate) { + private DelegatingIncomingMessageHook( + IncomingQueueMessageHook delegate) { this.delegate = delegate; } @@ -227,20 +236,16 @@ class MessageQueueManagerImpl implements MessageQueueManager { // Save the queue state before passing control to the delegate saveQueueState(txn, m.getGroupId(), queueState); // Deliver the messages to the delegate - try { - delegate.incomingMessage(txn, q, meta); - for (MessageId id : consecutive) { - byte[] raw = db.getRawMessage(txn, id); - meta = db.getMessageMetadata(txn, id); - q = queueMessageFactory.createMessage(id, raw); - if (LOG.isLoggable(INFO)) { - LOG.info("Delivering pending message with position " - + q.getQueuePosition()); - } - delegate.incomingMessage(txn, q, meta); + delegate.incomingMessage(txn, q, meta); + for (MessageId id : consecutive) { + byte[] raw = db.getRawMessage(txn, id); + meta = db.getMessageMetadata(txn, id); + q = queueMessageFactory.createMessage(id, raw); + if (LOG.isLoggable(INFO)) { + LOG.info("Delivering pending message with position " + + q.getQueuePosition()); } - } catch (FormatException e) { - throw new InvalidMessageException(e); + delegate.incomingMessage(txn, q, meta); } } // message queues are only useful for groups with two members diff --git a/briar-core/src/org/briarproject/clients/MessageTrackerImpl.java b/briar-core/src/org/briarproject/clients/MessageTrackerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..0d5328eee6f4e1db77942bcf3d206785be25804f --- /dev/null +++ b/briar-core/src/org/briarproject/clients/MessageTrackerImpl.java @@ -0,0 +1,132 @@ +package org.briarproject.clients; + +import org.briarproject.api.FormatException; +import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.clients.MessageTracker; +import org.briarproject.api.data.BdfDictionary; +import org.briarproject.api.data.BdfEntry; +import org.briarproject.api.db.DatabaseComponent; +import org.briarproject.api.db.DbException; +import org.briarproject.api.db.Transaction; +import org.briarproject.api.nullsafety.NotNullByDefault; +import org.briarproject.api.sync.GroupId; +import org.briarproject.api.sync.Message; +import org.briarproject.api.sync.MessageId; + +import javax.inject.Inject; + +import static org.briarproject.clients.BdfConstants.GROUP_KEY_LATEST_MSG; +import static org.briarproject.clients.BdfConstants.GROUP_KEY_MSG_COUNT; +import static org.briarproject.clients.BdfConstants.GROUP_KEY_UNREAD_COUNT; +import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; + +@NotNullByDefault +class MessageTrackerImpl implements MessageTracker { + + private final DatabaseComponent db; + private final ClientHelper clientHelper; + + @Inject + MessageTrackerImpl(DatabaseComponent db, ClientHelper clientHelper) { + this.db = db; + this.clientHelper = clientHelper; + } + + @Override + public void trackIncomingMessage(Transaction txn, Message m) + throws DbException { + trackMessage(txn, m.getGroupId(), m.getTimestamp(), false); + } + + @Override + public void trackOutgoingMessage(Transaction txn, Message m) + throws DbException { + trackMessage(txn, m.getGroupId(), m.getTimestamp(), true); + } + + @Override + public void trackMessage(Transaction txn, GroupId g, long time, + boolean read) throws DbException { + GroupCount c = getGroupCount(txn, g); + int msgCount = c.getMsgCount() + 1; + int unreadCount = c.getUnreadCount() + (read ? 0 : 1); + long latestMsgTime = Math.max(c.getLatestMsgTime(), time); + storeGroupCount(txn, g, new GroupCount(msgCount, unreadCount, + latestMsgTime)); + } + + @Override + public GroupCount getGroupCount(GroupId g) throws DbException { + GroupCount count; + Transaction txn = db.startTransaction(true); + try { + count = getGroupCount(txn, g); + db.commitTransaction(txn); + } finally { + db.endTransaction(txn); + } + return count; + } + + @Override + public GroupCount getGroupCount(Transaction txn, GroupId g) + throws DbException { + try { + BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g); + return new GroupCount( + d.getLong(GROUP_KEY_MSG_COUNT, 0L).intValue(), + d.getLong(GROUP_KEY_UNREAD_COUNT, 0L).intValue(), + d.getLong(GROUP_KEY_LATEST_MSG, 0L) + ); + } catch (FormatException e) { + throw new DbException(e); + } + } + + private void storeGroupCount(Transaction txn, GroupId g, GroupCount c) + throws DbException { + try { + BdfDictionary d = BdfDictionary.of( + new BdfEntry(GROUP_KEY_MSG_COUNT, c.getMsgCount()), + new BdfEntry(GROUP_KEY_UNREAD_COUNT, c.getUnreadCount()), + new BdfEntry(GROUP_KEY_LATEST_MSG, c.getLatestMsgTime()) + ); + clientHelper.mergeGroupMetadata(txn, g, d); + } catch (FormatException e) { + throw new DbException(e); + } + } + + @Override + public void setReadFlag(GroupId g, MessageId m, boolean read) + throws DbException { + Transaction txn = db.startTransaction(false); + try { + // check current read status of message + BdfDictionary old = + clientHelper.getMessageMetadataAsDictionary(txn, m); + boolean wasRead = old.getBoolean(MSG_KEY_READ, false); + + // if status changed + if (wasRead != read) { + // mark individual message as read + BdfDictionary meta = new BdfDictionary(); + meta.put(MSG_KEY_READ, read); + clientHelper.mergeMessageMetadata(txn, m, meta); + + // update unread counter in group metadata + GroupCount c = getGroupCount(txn, g); + int unreadCount = c.getUnreadCount() + (read ? -1 : 1); + if (unreadCount < 0) throw new DbException(); + storeGroupCount(txn, g, new GroupCount(c.getMsgCount(), + unreadCount, c.getLatestMsgTime())); + } + db.commitTransaction(txn); + } catch (FormatException e) { + throw new DbException(e); + } finally { + db.endTransaction(txn); + } + } + +} diff --git a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java index db82d71c123545e7a3549825f7f921e5a54f87cb..ff88d9fdbeb7537d14f34756e577abb2a6ee3eb7 100644 --- a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java +++ b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java @@ -2,6 +2,8 @@ package org.briarproject.forum; import org.briarproject.api.FormatException; import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.clients.MessageTracker; +import org.briarproject.api.clients.MessageTracker.GroupCount; import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataParser; @@ -20,6 +22,7 @@ import org.briarproject.api.identity.Author.Status; import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.LocalAuthor; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.Message; @@ -52,22 +55,25 @@ import static org.briarproject.api.identity.Author.Status.ANONYMOUS; import static org.briarproject.api.identity.Author.Status.OURSELVES; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; +@NotNullByDefault class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { private final IdentityManager identityManager; private final ForumFactory forumFactory; private final ForumPostFactory forumPostFactory; + private final MessageTracker messageTracker; private final List<RemoveForumHook> removeHooks; @Inject ForumManagerImpl(DatabaseComponent db, IdentityManager identityManager, ClientHelper clientHelper, MetadataParser metadataParser, - ForumFactory forumFactory, ForumPostFactory forumPostFactory) { + ForumFactory forumFactory, ForumPostFactory forumPostFactory, + MessageTracker messageTracker) { super(db, clientHelper, metadataParser); - this.identityManager = identityManager; this.forumFactory = forumFactory; this.forumPostFactory = forumPostFactory; + this.messageTracker = messageTracker; removeHooks = new CopyOnWriteArrayList<RemoveForumHook>(); } @@ -75,7 +81,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { protected boolean incomingMessage(Transaction txn, Message m, BdfList body, BdfDictionary meta) throws DbException, FormatException { - trackIncomingMessage(txn, m); + messageTracker.trackIncomingMessage(txn, m); ForumPostHeader post = getForumPostHeader(txn, m.getId(), meta); ForumPostReceivedEvent event = @@ -146,7 +152,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { meta.put(KEY_LOCAL, true); meta.put(MSG_KEY_READ, true); clientHelper.addLocalMessage(txn, p.getMessage(), meta, true); - trackOutgoingMessage(txn, p.getMessage()); + messageTracker.trackOutgoingMessage(txn, p.getMessage()); db.commitTransaction(txn); } catch (FormatException e) { throw new RuntimeException(e); @@ -204,6 +210,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { try { // Parent ID, author, forum post body, signature BdfList message = clientHelper.getMessageAsList(m); + if (message == null) throw new DbException(); return message.getString(2); } catch (FormatException e) { throw new DbException(e); @@ -253,6 +260,17 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { removeHooks.add(hook); } + @Override + public GroupCount getGroupCount(GroupId g) throws DbException { + return messageTracker.getGroupCount(g); + } + + @Override + public void setReadFlag(GroupId g, MessageId m, boolean read) + throws DbException { + messageTracker.setReadFlag(g, m, read); + } + private Forum parseForum(Group g) throws FormatException { byte[] descriptor = g.getDescriptor(); // Name, salt diff --git a/briar-core/src/org/briarproject/forum/ForumPostValidator.java b/briar-core/src/org/briarproject/forum/ForumPostValidator.java index a763b821e8200d7e5b4d95b7010c7bdbfe1730be..19e62584c84227c35d35b1b54a53c740e36da380 100644 --- a/briar-core/src/org/briarproject/forum/ForumPostValidator.java +++ b/briar-core/src/org/briarproject/forum/ForumPostValidator.java @@ -9,6 +9,7 @@ import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.identity.Author; import org.briarproject.api.identity.AuthorFactory; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.Message; @@ -25,6 +26,7 @@ import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENG import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; +@NotNullByDefault class ForumPostValidator extends BdfMessageValidator { private final AuthorFactory authorFactory; diff --git a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java b/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java index 30cae32f45b85f3ed3cbc83141edb65afbffd042..e59f34e8498ac4de2b74db755a520fd929e0fa42 100644 --- a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java +++ b/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java @@ -3,6 +3,7 @@ package org.briarproject.introduction; import org.briarproject.api.FormatException; import org.briarproject.api.clients.Client; import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -23,6 +24,7 @@ import org.briarproject.api.introduction.IntroductionManager; import org.briarproject.api.introduction.IntroductionMessage; import org.briarproject.api.introduction.IntroductionRequest; import org.briarproject.api.introduction.IntroductionResponse; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.Message; @@ -73,6 +75,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUE import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; +@NotNullByDefault class IntroductionManagerImpl extends ConversationClientImpl implements IntroductionManager, Client, AddContactHook, RemoveContactHook { @@ -86,11 +89,12 @@ class IntroductionManagerImpl extends ConversationClientImpl @Inject IntroductionManagerImpl(DatabaseComponent db, ClientHelper clientHelper, - MetadataParser metadataParser, IntroducerManager introducerManager, + MetadataParser metadataParser, MessageTracker messageTracker, + IntroducerManager introducerManager, IntroduceeManager introduceeManager, IntroductionGroupFactory introductionGroupFactory) { - super(db, clientHelper, metadataParser); + super(db, clientHelper, metadataParser, messageTracker); this.introducerManager = introducerManager; this.introduceeManager = introduceeManager; this.introductionGroupFactory = introductionGroupFactory; @@ -213,7 +217,7 @@ class IntroductionManagerImpl extends ConversationClientImpl introduceeManager.initialize(txn, groupId, message); try { introduceeManager.incomingMessage(txn, state, message); - trackIncomingMessage(txn, m); + messageTracker.trackIncomingMessage(txn, m); } catch (DbException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); introduceeManager.abort(txn, state); @@ -239,7 +243,8 @@ class IntroductionManagerImpl extends ConversationClientImpl LOG.warning("Unknown role '" + role + "'"); throw new DbException(); } - if (type == TYPE_RESPONSE) trackIncomingMessage(txn, m); + if (type == TYPE_RESPONSE) + messageTracker.trackIncomingMessage(txn, m); } catch (DbException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (role == ROLE_INTRODUCER) introducerManager.abort(txn, state); @@ -260,7 +265,7 @@ class IntroductionManagerImpl extends ConversationClientImpl } @Override - protected Group getContactGroup(Contact contact) { + public Group getContactGroup(Contact contact) { return introductionGroupFactory.createIntroductionGroup(contact); } @@ -274,8 +279,8 @@ class IntroductionManagerImpl extends ConversationClientImpl introducerManager.makeIntroduction(txn, c1, c2, msg, timestamp); Group g1 = getContactGroup(c1); Group g2 = getContactGroup(c2); - trackMessage(txn, g1.getId(), timestamp, true); - trackMessage(txn, g2.getId(), timestamp, true); + messageTracker.trackMessage(txn, g1.getId(), timestamp, true); + messageTracker.trackMessage(txn, g2.getId(), timestamp, true); db.commitTransaction(txn); } finally { db.endTransaction(txn); @@ -295,7 +300,7 @@ class IntroductionManagerImpl extends ConversationClientImpl getSessionState(txn, g.getId(), sessionId.getBytes()); introduceeManager.acceptIntroduction(txn, state, timestamp); - trackMessage(txn, g.getId(), timestamp, true); + messageTracker.trackMessage(txn, g.getId(), timestamp, true); db.commitTransaction(txn); } finally { db.endTransaction(txn); @@ -315,7 +320,7 @@ class IntroductionManagerImpl extends ConversationClientImpl getSessionState(txn, g.getId(), sessionId.getBytes()); introduceeManager.declineIntroduction(txn, state, timestamp); - trackMessage(txn, g.getId(), timestamp, true); + messageTracker.trackMessage(txn, g.getId(), timestamp, true); db.commitTransaction(txn); } finally { db.endTransaction(txn); diff --git a/briar-core/src/org/briarproject/introduction/IntroductionValidator.java b/briar-core/src/org/briarproject/introduction/IntroductionValidator.java index e2227e12eab424ab4fa2cead2ae29f70333e3240..d22163227f4e8a74cce990c92fdef86a29714cf1 100644 --- a/briar-core/src/org/briarproject/introduction/IntroductionValidator.java +++ b/briar-core/src/org/briarproject/introduction/IntroductionValidator.java @@ -7,6 +7,7 @@ import org.briarproject.api.clients.SessionId; import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataEncoder; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Message; import org.briarproject.api.system.Clock; @@ -39,6 +40,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPO import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT; import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH; +@NotNullByDefault class IntroductionValidator extends BdfMessageValidator { IntroductionValidator(ClientHelper clientHelper, diff --git a/briar-core/src/org/briarproject/messaging/ConversationManagerImpl.java b/briar-core/src/org/briarproject/messaging/ConversationManagerImpl.java index fafd48e75c3724d88c90cfd9e194c39538b52ecb..2a480850a605fb0fcf705ac98ea8d740e18f21c2 100644 --- a/briar-core/src/org/briarproject/messaging/ConversationManagerImpl.java +++ b/briar-core/src/org/briarproject/messaging/ConversationManagerImpl.java @@ -6,12 +6,14 @@ import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Transaction; import org.briarproject.api.messaging.ConversationManager; +import org.briarproject.api.nullsafety.NotNullByDefault; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import javax.inject.Inject; +@NotNullByDefault class ConversationManagerImpl implements ConversationManager { private final DatabaseComponent db; @@ -32,9 +34,7 @@ class ConversationManagerImpl implements ConversationManager { } @Override - public GroupCount getGroupCount(ContactId contactId) - throws DbException { - + public GroupCount getGroupCount(ContactId contactId) throws DbException { int msgCount = 0, unreadCount = 0; long latestTime = 0; Transaction txn = db.startTransaction(true); diff --git a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java index 624bf1b74486e81b08f5829fee342316a29a9bc7..233682600d938251ffc597a747f5be787fedc192 100644 --- a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java +++ b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java @@ -4,6 +4,7 @@ import org.briarproject.api.FormatException; import org.briarproject.api.clients.Client; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ContactGroupFactory; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactManager.AddContactHook; @@ -18,6 +19,7 @@ import org.briarproject.api.event.PrivateMessageReceivedEvent; import org.briarproject.api.messaging.MessagingManager; import org.briarproject.api.messaging.PrivateMessage; import org.briarproject.api.messaging.PrivateMessageHeader; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.Message; @@ -33,6 +35,7 @@ import javax.inject.Inject; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; +@NotNullByDefault class MessagingManagerImpl extends ConversationClientImpl implements MessagingManager, Client, AddContactHook, RemoveContactHook { @@ -40,9 +43,9 @@ class MessagingManagerImpl extends ConversationClientImpl @Inject MessagingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, - MetadataParser metadataParser, + MetadataParser metadataParser, MessageTracker messageTracker, ContactGroupFactory contactGroupFactory) { - super(db, clientHelper, metadataParser); + super(db, clientHelper, metadataParser, messageTracker); this.contactGroupFactory = contactGroupFactory; } @@ -72,7 +75,7 @@ class MessagingManagerImpl extends ConversationClientImpl } @Override - protected Group getContactGroup(Contact c) { + public Group getContactGroup(Contact c) { return contactGroupFactory.createContactGroup(CLIENT_ID, c); } @@ -95,7 +98,7 @@ class MessagingManagerImpl extends ConversationClientImpl PrivateMessageReceivedEvent event = new PrivateMessageReceivedEvent( header, contactId, groupId); txn.attach(event); - trackIncomingMessage(txn, m); + messageTracker.trackIncomingMessage(txn, m); // don't share message return false; @@ -110,7 +113,7 @@ class MessagingManagerImpl extends ConversationClientImpl meta.put("local", true); meta.put("read", true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); - trackOutgoingMessage(txn, m.getMessage()); + messageTracker.trackOutgoingMessage(txn, m.getMessage()); db.commitTransaction(txn); } catch (FormatException e) { throw new RuntimeException(e); @@ -195,20 +198,11 @@ class MessagingManagerImpl extends ConversationClientImpl try { // 0: private message body BdfList message = clientHelper.getMessageAsList(m); + if (message == null) throw new DbException(); return message.getString(0); } catch (FormatException e) { throw new DbException(e); } } - @Override - public GroupCount getGroupCount(Transaction txn, ContactId contactId) - throws DbException { - - Contact contact = db.getContact(txn, contactId); - GroupId groupId = getContactGroup(contact).getId(); - - return getGroupCount(txn, groupId); - } - } diff --git a/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java b/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java index 209a4b24666f22930d51b461c047f111d09140d9..9eeae2409606d424638a75f8ed55e27e5e01f7b8 100644 --- a/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java +++ b/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java @@ -6,6 +6,7 @@ import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataEncoder; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Message; import org.briarproject.api.system.Clock; @@ -14,6 +15,7 @@ import org.briarproject.clients.BdfMessageValidator; import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; +@NotNullByDefault class PrivateMessageValidator extends BdfMessageValidator { PrivateMessageValidator(ClientHelper clientHelper, diff --git a/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java b/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java index 54b6324fc5b2a3d52d8d87716e364f52905c3d8c..5d400c883852081f889b48c2e5dba9d5379c33b3 100644 --- a/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java +++ b/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java @@ -8,6 +8,7 @@ import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.identity.Author; import org.briarproject.api.identity.AuthorFactory; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.privategroup.MessageType; import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroupFactory; @@ -38,6 +39,7 @@ import static org.briarproject.privategroup.GroupConstants.KEY_READ; import static org.briarproject.privategroup.GroupConstants.KEY_TIMESTAMP; import static org.briarproject.privategroup.GroupConstants.KEY_TYPE; +@NotNullByDefault class GroupMessageValidator extends BdfMessageValidator { private final PrivateGroupFactory privateGroupFactory; diff --git a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java index c2bdf6cf493060e57de864e01fbb16c985c5150a..37c524889347063eff8423053bf891cd93a6cdcc 100644 --- a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java +++ b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java @@ -2,6 +2,8 @@ package org.briarproject.privategroup; import org.briarproject.api.FormatException; import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.clients.MessageTracker; +import org.briarproject.api.clients.MessageTracker.GroupCount; import org.briarproject.api.clients.ProtocolStateException; import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfEntry; @@ -75,17 +77,18 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements private final PrivateGroupFactory privateGroupFactory; private final IdentityManager identityManager; + private final MessageTracker messageTracker; private final List<PrivateGroupHook> hooks; @Inject PrivateGroupManagerImpl(ClientHelper clientHelper, MetadataParser metadataParser, DatabaseComponent db, PrivateGroupFactory privateGroupFactory, - IdentityManager identityManager) { + IdentityManager identityManager, MessageTracker messageTracker) { super(db, clientHelper, metadataParser); - this.privateGroupFactory = privateGroupFactory; this.identityManager = identityManager; + this.messageTracker = messageTracker; hooks = new CopyOnWriteArrayList<PrivateGroupHook>(); } @@ -126,7 +129,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements meta.put(KEY_TYPE, JOIN.getInt()); addMessageMetadata(meta, m, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); - trackOutgoingMessage(txn, m.getMessage()); + messageTracker.trackOutgoingMessage(txn, m.getMessage()); addMember(txn, m.getMessage().getGroupId(), m.getMember(), VISIBLE); setPreviousMsgId(txn, m.getMessage().getGroupId(), m.getMessage().getId()); @@ -218,7 +221,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements // track message setPreviousMsgId(txn, g, m.getMessage().getId()); - trackOutgoingMessage(txn, m.getMessage()); + messageTracker.trackOutgoingMessage(txn, m.getMessage()); // broadcast event attachGroupMessageAddedEvent(txn, m.getMessage(), meta, true); @@ -437,6 +440,17 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements return false; } + @Override + public GroupCount getGroupCount(GroupId g) throws DbException { + return messageTracker.getGroupCount(g); + } + + @Override + public void setReadFlag(GroupId g, MessageId m, boolean read) + throws DbException { + messageTracker.setReadFlag(g, m, read); + } + @Override public void relationshipRevealed(Transaction txn, GroupId g, AuthorId a, boolean byContact) throws FormatException, DbException { @@ -500,7 +514,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements } addMember(txn, m.getGroupId(), member, v); // track message and broadcast event - trackIncomingMessage(txn, m); + messageTracker.trackIncomingMessage(txn, m); attachJoinMessageAddedEvent(txn, m, meta, false, v); } @@ -537,7 +551,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements if (previousType != JOIN && previousType != POST) throw new FormatException(); // track message and broadcast event - trackIncomingMessage(txn, m); + messageTracker.trackIncomingMessage(txn, m); attachGroupMessageAddedEvent(txn, m, meta, false); } diff --git a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationManagerImpl.java b/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationManagerImpl.java index ae11b48b850f13154046c447614061e910e8dd4c..472f55ed7544f64f13b636101dc7b9e1acd2dd7b 100644 --- a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationManagerImpl.java +++ b/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationManagerImpl.java @@ -4,6 +4,7 @@ import org.briarproject.api.FormatException; import org.briarproject.api.clients.Client; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ContactGroupFactory; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -74,13 +75,14 @@ class GroupInvitationManagerImpl extends ConversationClientImpl @Inject protected GroupInvitationManagerImpl(DatabaseComponent db, ClientHelper clientHelper, MetadataParser metadataParser, + MessageTracker messageTracker, ContactGroupFactory contactGroupFactory, PrivateGroupFactory privateGroupFactory, PrivateGroupManager privateGroupManager, MessageParser messageParser, SessionParser sessionParser, SessionEncoder sessionEncoder, ProtocolEngineFactory engineFactory) { - super(db, clientHelper, metadataParser); + super(db, clientHelper, metadataParser, messageTracker); this.contactGroupFactory = contactGroupFactory; this.privateGroupFactory = privateGroupFactory; this.privateGroupManager = privateGroupManager; @@ -131,7 +133,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl } @Override - protected Group getContactGroup(Contact c) { + public Group getContactGroup(Contact c) { return contactGroupFactory.createContactGroup(CLIENT_ID, c); } diff --git a/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java b/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java index 940c6b0f1c955eee2152fc3b5f1e0afb133a559e..14aef6715d4ee1575a03163ff4e4b0666e5500e4 100644 --- a/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java +++ b/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java @@ -1,11 +1,12 @@ package org.briarproject.properties; import org.briarproject.api.FormatException; -import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.BdfMessageContext; +import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataEncoder; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Message; import org.briarproject.api.system.Clock; @@ -15,6 +16,7 @@ import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_LENGTH; import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT; import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH; +@NotNullByDefault public class TransportPropertyValidator extends BdfMessageValidator { TransportPropertyValidator(ClientHelper clientHelper, diff --git a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java index 39533d7d936a12ddc57d2c4ee6a852fb1eb0a7d9..c28ad5792dceaaebddd09c9f457e428598810d12 100644 --- a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java +++ b/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java @@ -12,6 +12,7 @@ import org.briarproject.api.blogs.BlogSharingMessage.BlogInvitation; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.MessageQueueManager; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -28,6 +29,7 @@ import org.briarproject.api.identity.Author; import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.LocalAuthor; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sharing.InvitationMessage; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.GroupId; @@ -43,6 +45,7 @@ import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY; import static org.briarproject.api.sharing.SharingConstants.INVITATION_ID; import static org.briarproject.api.sharing.SharingConstants.RESPONSE_ID; +@NotNullByDefault class BlogSharingManagerImpl extends SharingManagerImpl<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationReceivedEvent, BlogInvitationResponseReceivedEvent> implements BlogSharingManager, RemoveBlogHook { @@ -63,10 +66,11 @@ class BlogSharingManagerImpl extends DatabaseComponent db, MessageQueueManager messageQueueManager, MetadataEncoder metadataEncoder, MetadataParser metadataParser, ContactGroupFactory contactGroupFactory, SecureRandom random, - IdentityManager identityManager) { + IdentityManager identityManager, MessageTracker messageTracker) { super(db, messageQueueManager, clientHelper, metadataParser, - metadataEncoder, random, contactGroupFactory, clock); + metadataEncoder, random, contactGroupFactory, messageTracker, + clock); this.blogManager = blogManager; this.identityManager = identityManager; diff --git a/briar-core/src/org/briarproject/sharing/BlogSharingValidator.java b/briar-core/src/org/briarproject/sharing/BlogSharingValidator.java index 781555917cbe378dc4cd2aae584bb743f01f1199..3244abca1a4ca71bca0dd354b9894df2a1308483 100644 --- a/briar-core/src/org/briarproject/sharing/BlogSharingValidator.java +++ b/briar-core/src/org/briarproject/sharing/BlogSharingValidator.java @@ -7,6 +7,7 @@ import org.briarproject.api.clients.SessionId; import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataEncoder; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Message; import org.briarproject.api.system.Clock; @@ -30,6 +31,7 @@ import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE import static org.briarproject.api.sharing.SharingConstants.TIME; import static org.briarproject.api.sharing.SharingConstants.TYPE; +@NotNullByDefault class BlogSharingValidator extends BdfMessageValidator { @Inject diff --git a/briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java index d4c04971a0e4a3961cfe2e05b2b3bc5a5fced674..29462307477a4bb5196e35832259212af1e01c5c 100644 --- a/briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java +++ b/briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java @@ -4,6 +4,7 @@ import org.briarproject.api.FormatException; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.MessageQueueManager; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.ContactId; import org.briarproject.api.data.BdfDictionary; @@ -20,8 +21,10 @@ import org.briarproject.api.forum.ForumFactory; import org.briarproject.api.forum.ForumInvitationRequest; import org.briarproject.api.forum.ForumInvitationResponse; import org.briarproject.api.forum.ForumManager; +import org.briarproject.api.forum.ForumManager.RemoveForumHook; import org.briarproject.api.forum.ForumSharingManager; import org.briarproject.api.forum.ForumSharingMessage.ForumInvitation; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sharing.InvitationMessage; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.GroupId; @@ -37,9 +40,10 @@ import static org.briarproject.api.forum.ForumConstants.FORUM_SALT; import static org.briarproject.api.sharing.SharingConstants.INVITATION_ID; import static org.briarproject.api.sharing.SharingConstants.RESPONSE_ID; +@NotNullByDefault class ForumSharingManagerImpl extends SharingManagerImpl<Forum, ForumInvitation, ForumInviteeSessionState, ForumSharerSessionState, ForumInvitationReceivedEvent, ForumInvitationResponseReceivedEvent> - implements ForumSharingManager, ForumManager.RemoveForumHook { + implements ForumSharingManager, RemoveForumHook { private final SFactory sFactory; private final IFactory iFactory; @@ -57,9 +61,10 @@ class ForumSharingManagerImpl extends MetadataEncoder metadataEncoder, MetadataParser metadataParser, ContactGroupFactory contactGroupFactory, - SecureRandom random) { + SecureRandom random, MessageTracker messageTracker) { super(db, messageQueueManager, clientHelper, metadataParser, - metadataEncoder, random, contactGroupFactory, clock); + metadataEncoder, random, contactGroupFactory, messageTracker, + clock); sFactory = new SFactory(forumFactory, forumManager); iFactory = new IFactory(); diff --git a/briar-core/src/org/briarproject/sharing/ForumSharingValidator.java b/briar-core/src/org/briarproject/sharing/ForumSharingValidator.java index 11343f53803433a40675bb5ee916c27870ee8e17..471446b6f4dd9ae1617ad58ab9f6bf9d6f9932ec 100644 --- a/briar-core/src/org/briarproject/sharing/ForumSharingValidator.java +++ b/briar-core/src/org/briarproject/sharing/ForumSharingValidator.java @@ -7,6 +7,7 @@ import org.briarproject.api.clients.SessionId; import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataEncoder; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Message; import org.briarproject.api.system.Clock; @@ -30,6 +31,7 @@ import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE import static org.briarproject.api.sharing.SharingConstants.TIME; import static org.briarproject.api.sharing.SharingConstants.TYPE; +@NotNullByDefault class ForumSharingValidator extends BdfMessageValidator { @Inject diff --git a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java index cd525096c8543ea428cf05b71c0163a2deabc1f1..95697ffa40a493b0cbcb678c0ff0e39f0f4edc0d 100644 --- a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java +++ b/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java @@ -6,6 +6,7 @@ import org.briarproject.api.clients.Client; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.MessageQueueManager; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -25,6 +26,7 @@ import org.briarproject.api.event.Event; import org.briarproject.api.event.InvitationRequestReceivedEvent; import org.briarproject.api.event.InvitationResponseReceivedEvent; import org.briarproject.api.identity.LocalAuthor; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sharing.InvitationMessage; import org.briarproject.api.sharing.Shareable; import org.briarproject.api.sharing.SharingInvitationItem; @@ -52,6 +54,8 @@ import java.util.Map; import java.util.Set; import java.util.logging.Logger; +import javax.annotation.Nullable; + import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.api.clients.ProtocolEngine.StateUpdate; @@ -86,6 +90,7 @@ import static org.briarproject.api.sharing.SharingMessage.Invitation; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; import static org.briarproject.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE; +@NotNullByDefault abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS extends InviteeSessionState, SS extends SharerSessionState, IR extends InvitationRequestReceivedEvent, IRR extends InvitationResponseReceivedEvent> extends ConversationClientImpl implements SharingManager<S>, Client, AddContactHook, @@ -105,9 +110,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS MessageQueueManager messageQueueManager, ClientHelper clientHelper, MetadataParser metadataParser, MetadataEncoder metadataEncoder, SecureRandom random, ContactGroupFactory contactGroupFactory, - Clock clock) { - super(db, clientHelper, metadataParser); - + MessageTracker messageTracker, Clock clock) { + super(db, clientHelper, metadataParser, messageTracker); this.messageQueueManager = messageQueueManager; this.metadataEncoder = metadataEncoder; this.random = random; @@ -226,7 +230,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS new InviteeEngine<IS, IR>(getIRFactory(), clock); processInviteeStateUpdate(txn, m.getId(), engine.onMessageReceived(state, msg)); - trackIncomingMessage(txn, m); + messageTracker.trackIncomingMessage(txn, m); } else if (msg.getType() == SHARE_MSG_TYPE_ACCEPT || msg.getType() == SHARE_MSG_TYPE_DECLINE) { // we are a sharer who just received a response @@ -237,7 +241,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS getIRRFactory(), clock); processSharerStateUpdate(txn, m.getId(), engine.onMessageReceived(state, msg)); - trackIncomingMessage(txn, m); + messageTracker.trackIncomingMessage(txn, m); } else if (msg.getType() == SHARE_MSG_TYPE_LEAVE || msg.getType() == SHARE_MSG_TYPE_ABORT) { // we don't know who we are, so figure it out @@ -296,7 +300,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS // track message // TODO handle this properly without engine hacks (#376) long time = update.toSend.get(0).getTime(); - trackMessage(txn, localState.getGroupId(), time, true); + messageTracker.trackMessage(txn, localState.getGroupId(), time, + true); db.commitTransaction(txn); } catch (FormatException e) { @@ -359,7 +364,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS // track message // TODO handle this properly without engine hacks (#376) long time = update.toSend.get(0).getTime(); - trackMessage(txn, localState.getGroupId(), time, true); + messageTracker.trackMessage(txn, localState.getGroupId(), time, true); } @Override @@ -581,16 +586,6 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS } } - @Override - public GroupCount getGroupCount(Transaction txn, ContactId contactId) - throws DbException { - - Contact contact = db.getContact(txn, contactId); - GroupId groupId = getContactGroup(contact).getId(); - - return getGroupCount(txn, groupId); - } - void removingShareable(Transaction txn, S f) throws DbException { try { for (Contact c : db.getContacts(txn)) { @@ -827,7 +822,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS throw new FormatException(); } - private void processStateUpdate(Transaction txn, MessageId messageId, + private void processStateUpdate(Transaction txn, + @Nullable MessageId messageId, StateUpdate<SharingSessionState, BaseMessage> result, S f) throws DbException, FormatException { @@ -859,8 +855,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS } } - private void processSharerStateUpdate(Transaction txn, MessageId messageId, - StateUpdate<SS, BaseMessage> result) + private void processSharerStateUpdate(Transaction txn, + @Nullable MessageId messageId, StateUpdate<SS, BaseMessage> result) throws DbException, FormatException { StateUpdate<SharingSessionState, BaseMessage> r = @@ -874,8 +870,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS processStateUpdate(txn, messageId, r, f); } - private void processInviteeStateUpdate(Transaction txn, MessageId messageId, - StateUpdate<IS, BaseMessage> result) + private void processInviteeStateUpdate(Transaction txn, + @Nullable MessageId messageId, StateUpdate<IS, BaseMessage> result) throws DbException, FormatException { StateUpdate<SharingSessionState, BaseMessage> r = @@ -947,7 +943,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS } @Override - protected Group getContactGroup(Contact c) { + public Group getContactGroup(Contact c) { return contactGroupFactory.createContactGroup(getClientId(), c); } diff --git a/briar-core/src/org/briarproject/sync/MessageFactoryImpl.java b/briar-core/src/org/briarproject/sync/MessageFactoryImpl.java index a92f550c648f676af05cfc09a3c4d8d32aa7b148..c245ea53b83b9a89417285b9f4cdb3f9ff4d9255 100644 --- a/briar-core/src/org/briarproject/sync/MessageFactoryImpl.java +++ b/briar-core/src/org/briarproject/sync/MessageFactoryImpl.java @@ -1,19 +1,22 @@ package org.briarproject.sync; - import org.briarproject.api.UniqueId; import org.briarproject.api.crypto.CryptoComponent; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.Message; import org.briarproject.api.sync.MessageFactory; import org.briarproject.api.sync.MessageId; import org.briarproject.util.ByteUtils; +import javax.annotation.concurrent.Immutable; import javax.inject.Inject; import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; +@Immutable +@NotNullByDefault class MessageFactoryImpl implements MessageFactory { private final CryptoComponent crypto; diff --git a/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java b/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java index 289bde12288c21c8e402743a85507c8b3f210072..c4be29aa40011a39d389927f2321690c9081eaf0 100644 --- a/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java +++ b/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java @@ -1,6 +1,5 @@ package org.briarproject.sync; -import org.briarproject.api.UniqueId; import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DatabaseExecutor; @@ -13,15 +12,15 @@ import org.briarproject.api.event.Event; import org.briarproject.api.event.EventListener; import org.briarproject.api.event.MessageAddedEvent; import org.briarproject.api.lifecycle.Service; +import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.Group; -import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.Message; import org.briarproject.api.sync.MessageContext; +import org.briarproject.api.sync.MessageFactory; import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.ValidationManager; -import org.briarproject.util.ByteUtils; import java.util.Collection; import java.util.LinkedList; @@ -33,15 +32,17 @@ import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; +import javax.annotation.concurrent.ThreadSafe; import javax.inject.Inject; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; -import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.ValidationManager.State.DELIVERED; import static org.briarproject.api.sync.ValidationManager.State.INVALID; import static org.briarproject.api.sync.ValidationManager.State.PENDING; +@ThreadSafe +@NotNullByDefault class ValidationManagerImpl implements ValidationManager, Service, EventListener { @@ -51,6 +52,7 @@ class ValidationManagerImpl implements ValidationManager, Service, private final DatabaseComponent db; private final Executor dbExecutor; private final Executor cryptoExecutor; + private final MessageFactory messageFactory; private final Map<ClientId, MessageValidator> validators; private final Map<ClientId, IncomingMessageHook> hooks; private final AtomicBoolean used = new AtomicBoolean(false); @@ -58,10 +60,12 @@ class ValidationManagerImpl implements ValidationManager, Service, @Inject ValidationManagerImpl(DatabaseComponent db, @DatabaseExecutor Executor dbExecutor, - @CryptoExecutor Executor cryptoExecutor) { + @CryptoExecutor Executor cryptoExecutor, + MessageFactory messageFactory) { this.db = db; this.dbExecutor = dbExecutor; this.cryptoExecutor = cryptoExecutor; + this.messageFactory = messageFactory; validators = new ConcurrentHashMap<ClientId, MessageValidator>(); hooks = new ConcurrentHashMap<ClientId, IncomingMessageHook>(); } @@ -134,7 +138,8 @@ class ValidationManagerImpl implements ValidationManager, Service, try { MessageId id = unvalidated.poll(); byte[] raw = db.getRawMessage(txn, id); - m = parseMessage(id, raw); + if (raw == null) throw new DbException(); + m = messageFactory.createMessage(id, raw); g = db.getGroup(txn, m.getGroupId()); db.commitTransaction(txn); } finally { @@ -210,7 +215,9 @@ class ValidationManagerImpl implements ValidationManager, Service, invalidateMessage(txn, id); invalidate = getDependentsToInvalidate(txn, id); } else if (allDelivered) { - Message m = parseMessage(id, db.getRawMessage(txn, id)); + byte[] raw = db.getRawMessage(txn, id); + if (raw == null) throw new DbException(); + Message m = messageFactory.createMessage(id, raw); Group g = db.getGroup(txn, m.getGroupId()); ClientId c = g.getClientId(); Metadata meta = db.getMessageMetadataForValidator(txn, @@ -247,15 +254,6 @@ class ValidationManagerImpl implements ValidationManager, Service, } } - private Message parseMessage(MessageId id, byte[] raw) { - if (raw.length <= MESSAGE_HEADER_LENGTH) - throw new IllegalArgumentException(); - byte[] groupId = new byte[UniqueId.LENGTH]; - System.arraycopy(raw, 0, groupId, 0, UniqueId.LENGTH); - long timestamp = ByteUtils.readUint64(raw, UniqueId.LENGTH); - return new Message(id, new GroupId(groupId), timestamp, raw); - } - private void validateMessageAsync(final Message m, final Group g) { cryptoExecutor.execute(new Runnable() { @Override @@ -412,7 +410,7 @@ class ValidationManagerImpl implements ValidationManager, Service, /** * Shares the next message from the toShare queue asynchronously. - * + * <p> * This method should only be called for messages that have all their * dependencies delivered and have been delivered themselves. */ diff --git a/briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java b/briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java index 39a166f4e76e0626d8539c6ecc209f78a8a26f00..8e750a9c68fcfd56fee96beed40959d894087fd8 100644 --- a/briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java +++ b/briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java @@ -16,6 +16,7 @@ import org.briarproject.api.db.Transaction; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.GroupId; +import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.Message; import org.briarproject.api.sync.MessageContext; import org.briarproject.api.sync.MessageId; @@ -37,8 +38,8 @@ import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LEN import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; public class MessageQueueManagerImplTest extends BriarTestCase { @@ -152,7 +153,12 @@ public class MessageQueueManagerImplTest extends BriarTestCase { MessageValidator delegate = captured.get(); assertNotNull(delegate); // The message should be invalid - assertNull(delegate.validateMessage(message, group)); + try { + delegate.validateMessage(message, group); + fail(); + } catch (InvalidMessageException expected) { + // Expected + } context.assertIsSatisfied(); } @@ -193,7 +199,12 @@ public class MessageQueueManagerImplTest extends BriarTestCase { MessageValidator delegate = captured.get(); assertNotNull(delegate); // The message should be invalid - assertNull(delegate.validateMessage(message, group)); + try { + delegate.validateMessage(message, group); + fail(); + } catch (InvalidMessageException expected) { + // Expected + } context.assertIsSatisfied(); } diff --git a/briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java b/briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java index e3c7d2ea5aee81a354f7870d9bee1f7c79bd075e..463d4a8671a1a29efb2d282bc3cab5c6ecab4936 100644 --- a/briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java +++ b/briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java @@ -4,6 +4,7 @@ import org.briarproject.BriarTestCase; import org.briarproject.TestUtils; import org.briarproject.api.FormatException; import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -41,9 +42,6 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; -import static org.briarproject.clients.BdfConstants.GROUP_KEY_LATEST_MSG; -import static org.briarproject.clients.BdfConstants.GROUP_KEY_MSG_COUNT; -import static org.briarproject.clients.BdfConstants.GROUP_KEY_UNREAD_COUNT; import static org.junit.Assert.assertFalse; public class IntroductionManagerImplTest extends BriarTestCase { @@ -54,6 +52,7 @@ public class IntroductionManagerImplTest extends BriarTestCase { private final IntroduceeManager introduceeManager; private final DatabaseComponent db; private final ClientHelper clientHelper; + private final MessageTracker messageTracker; private final IntroductionGroupFactory introductionGroupFactory; private final SessionId sessionId = new SessionId(TestUtils.getRandomId()); private final long time = 42L; @@ -63,7 +62,6 @@ public class IntroductionManagerImplTest extends BriarTestCase { private final Group introductionGroup2; private final Message message1; private Transaction txn; - private BdfDictionary metadataBefore, metadataAfter; public IntroductionManagerImplTest() { AuthorId authorId1 = new AuthorId(TestUtils.getRandomId()); @@ -94,16 +92,6 @@ public class IntroductionManagerImplTest extends BriarTestCase { time, TestUtils.getRandomBytes(MESSAGE_HEADER_LENGTH + 1) ); - metadataBefore = BdfDictionary.of( - new BdfEntry(GROUP_KEY_MSG_COUNT, 41), - new BdfEntry(GROUP_KEY_UNREAD_COUNT, 0), - new BdfEntry(GROUP_KEY_LATEST_MSG, 0) - ); - metadataAfter = BdfDictionary.of( - new BdfEntry(GROUP_KEY_MSG_COUNT, 42), - new BdfEntry(GROUP_KEY_UNREAD_COUNT, 0), - new BdfEntry(GROUP_KEY_LATEST_MSG, time) - ); // mock ALL THE THINGS!!! context = new Mockery(); @@ -113,12 +101,12 @@ public class IntroductionManagerImplTest extends BriarTestCase { db = context.mock(DatabaseComponent.class); clientHelper = context.mock(ClientHelper.class); MetadataParser metadataParser = context.mock(MetadataParser.class); + messageTracker = context.mock(MessageTracker.class); introductionGroupFactory = context.mock(IntroductionGroupFactory.class); - introductionManager = new IntroductionManagerImpl( - db, clientHelper, metadataParser, introducerManager, - introduceeManager, introductionGroupFactory - ); + introductionManager = new IntroductionManagerImpl(db, clientHelper, + metadataParser, messageTracker, introducerManager, + introduceeManager, introductionGroupFactory); } @Test @@ -139,19 +127,11 @@ public class IntroductionManagerImplTest extends BriarTestCase { .createIntroductionGroup(introducee2); will(returnValue(introductionGroup2)); // track message for group 1 - oneOf(clientHelper).getGroupMetadataAsDictionary(txn, - introductionGroup1.getId()); - will(returnValue(metadataBefore)); - oneOf(clientHelper) - .mergeGroupMetadata(txn, introductionGroup1.getId(), - metadataAfter); + oneOf(messageTracker).trackMessage(txn, + introductionGroup1.getId(), time, true); // track message for group 2 - oneOf(clientHelper).getGroupMetadataAsDictionary(txn, - introductionGroup2.getId()); - will(returnValue(metadataBefore)); - oneOf(clientHelper) - .mergeGroupMetadata(txn, introductionGroup2.getId(), - metadataAfter); + oneOf(messageTracker).trackMessage(txn, + introductionGroup2.getId(), time, true); oneOf(db).commitTransaction(txn); oneOf(db).endTransaction(txn); }}); @@ -181,12 +161,8 @@ public class IntroductionManagerImplTest extends BriarTestCase { will(returnValue(state)); oneOf(introduceeManager).acceptIntroduction(txn, state, time); // track message - oneOf(clientHelper).getGroupMetadataAsDictionary(txn, - introductionGroup1.getId()); - will(returnValue(metadataBefore)); - oneOf(clientHelper) - .mergeGroupMetadata(txn, introductionGroup1.getId(), - metadataAfter); + oneOf(messageTracker).trackMessage(txn, + introductionGroup1.getId(), time, true); oneOf(db).commitTransaction(txn); oneOf(db).endTransaction(txn); }}); @@ -216,12 +192,8 @@ public class IntroductionManagerImplTest extends BriarTestCase { will(returnValue(state)); oneOf(introduceeManager).declineIntroduction(txn, state, time); // track message - oneOf(clientHelper).getGroupMetadataAsDictionary(txn, - introductionGroup1.getId()); - will(returnValue(metadataBefore)); - oneOf(clientHelper) - .mergeGroupMetadata(txn, introductionGroup1.getId(), - metadataAfter); + oneOf(messageTracker).trackMessage(txn, + introductionGroup1.getId(), time, true); oneOf(db).commitTransaction(txn); oneOf(db).endTransaction(txn); }}); @@ -272,9 +244,6 @@ public class IntroductionManagerImplTest extends BriarTestCase { final BdfDictionary state = new BdfDictionary(); txn = new Transaction(null, false); - metadataBefore.put(GROUP_KEY_UNREAD_COUNT, 1); - metadataAfter.put(GROUP_KEY_UNREAD_COUNT, 2); - context.checking(new Expectations() {{ oneOf(introduceeManager) .initialize(txn, introductionGroup1.getId(), msg); @@ -282,12 +251,7 @@ public class IntroductionManagerImplTest extends BriarTestCase { oneOf(introduceeManager) .incomingMessage(txn, state, msg); // track message - oneOf(clientHelper).getGroupMetadataAsDictionary(txn, - introductionGroup1.getId()); - will(returnValue(metadataBefore)); - oneOf(clientHelper) - .mergeGroupMetadata(txn, introductionGroup1.getId(), - metadataAfter); + oneOf(messageTracker).trackIncomingMessage(txn, message1); }}); introductionManager @@ -313,20 +277,12 @@ public class IntroductionManagerImplTest extends BriarTestCase { txn = new Transaction(null, false); - metadataBefore.put(GROUP_KEY_UNREAD_COUNT, 41); - metadataAfter.put(GROUP_KEY_UNREAD_COUNT, 42); - context.checking(new Expectations() {{ oneOf(clientHelper).getMessageMetadataAsDictionary(txn, sessionId); will(returnValue(state)); oneOf(introducerManager).incomingMessage(txn, state, msg); // track message - oneOf(clientHelper).getGroupMetadataAsDictionary(txn, - introductionGroup1.getId()); - will(returnValue(metadataBefore)); - oneOf(clientHelper) - .mergeGroupMetadata(txn, introductionGroup1.getId(), - metadataAfter); + oneOf(messageTracker).trackIncomingMessage(txn, message1); }}); introductionManager diff --git a/briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java b/briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java index 373f94f808637c41a719d3b534a526b79c0687ad..905ba25294b0075573157924cf587ffdacfab644 100644 --- a/briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java +++ b/briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java @@ -17,6 +17,7 @@ import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.Message; import org.briarproject.api.sync.MessageContext; +import org.briarproject.api.sync.MessageFactory; import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.ValidationManager.IncomingMessageHook; import org.briarproject.api.sync.ValidationManager.MessageValidator; @@ -74,6 +75,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -97,6 +100,8 @@ public class ValidationManagerImplTest extends BriarTestCase { will(returnValue(txn1)); oneOf(db).getRawMessage(txn1, messageId); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId, raw); + will(returnValue(message)); oneOf(db).getGroup(txn1, groupId); will(returnValue(group)); oneOf(db).commitTransaction(txn1); @@ -122,6 +127,8 @@ public class ValidationManagerImplTest extends BriarTestCase { will(returnValue(txn3)); oneOf(db).getRawMessage(txn3, messageId1); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId1, raw); + will(returnValue(message1)); oneOf(db).getGroup(txn3, groupId); will(returnValue(group)); oneOf(db).commitTransaction(txn3); @@ -159,7 +166,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.startService(); @@ -173,6 +180,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -207,6 +216,8 @@ public class ValidationManagerImplTest extends BriarTestCase { // Get the message and its metadata to deliver oneOf(db).getRawMessage(txn2, messageId); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId, raw); + will(returnValue(message)); oneOf(db).getGroup(txn2, groupId); will(returnValue(group)); oneOf(db).getMessageMetadataForValidator(txn2, messageId); @@ -230,6 +241,8 @@ public class ValidationManagerImplTest extends BriarTestCase { // Get the dependent and its metadata to deliver oneOf(db).getRawMessage(txn3, messageId2); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId2, raw); + will(returnValue(message2)); oneOf(db).getGroup(txn3, groupId); will(returnValue(group)); oneOf(db).getMessageMetadataForValidator(txn3, messageId2); @@ -254,7 +267,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.startService(); @@ -268,6 +281,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -319,7 +334,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.startService(); @@ -333,6 +348,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -380,7 +397,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.eventOccurred(new MessageAddedEvent(message, contactId)); @@ -395,6 +412,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -424,6 +443,8 @@ public class ValidationManagerImplTest extends BriarTestCase { will(returnValue(txn2)); oneOf(db).getRawMessage(txn2, messageId1); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId1, raw); + will(returnValue(message1)); oneOf(db).getGroup(txn2, groupId); will(returnValue(group)); oneOf(db).commitTransaction(txn2); @@ -461,7 +482,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.startService(); @@ -476,6 +497,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -498,6 +521,8 @@ public class ValidationManagerImplTest extends BriarTestCase { will(returnValue(txn1)); oneOf(db).getRawMessage(txn1, messageId); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId, raw); + will(returnValue(message)); // Load the group - *gasp* it's gone! oneOf(db).getGroup(txn1, groupId); will(throwException(new NoSuchGroupException())); @@ -508,6 +533,8 @@ public class ValidationManagerImplTest extends BriarTestCase { will(returnValue(txn2)); oneOf(db).getRawMessage(txn2, messageId1); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId1, raw); + will(returnValue(message1)); oneOf(db).getGroup(txn2, groupId); will(returnValue(group)); oneOf(db).commitTransaction(txn2); @@ -545,7 +572,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.startService(); @@ -559,6 +586,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -591,7 +620,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.eventOccurred(new MessageAddedEvent(message, contactId)); @@ -605,12 +634,14 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.eventOccurred(new MessageAddedEvent(message, null)); @@ -626,6 +657,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -656,7 +689,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.eventOccurred(new MessageAddedEvent(message, contactId)); @@ -671,6 +704,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -707,7 +742,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.eventOccurred(new MessageAddedEvent(message, contactId)); @@ -722,6 +757,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -773,7 +810,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.eventOccurred(new MessageAddedEvent(message, contactId)); @@ -787,6 +824,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -888,7 +927,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.eventOccurred(new MessageAddedEvent(message, contactId)); @@ -902,6 +941,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -958,6 +999,8 @@ public class ValidationManagerImplTest extends BriarTestCase { // Get message 1 and its metadata oneOf(db).getRawMessage(txn2, messageId1); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId1, raw); + will(returnValue(message1)); oneOf(db).getGroup(txn2, groupId); will(returnValue(group)); oneOf(db).getMessageMetadataForValidator(txn2, messageId1); @@ -981,6 +1024,8 @@ public class ValidationManagerImplTest extends BriarTestCase { // Get message 2 and its metadata oneOf(db).getRawMessage(txn3, messageId2); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId2, raw); + will(returnValue(message2)); oneOf(db).getGroup(txn3, groupId); will(returnValue(group)); oneOf(db).getMessageMetadataForValidator(txn3, messageId2); @@ -1004,6 +1049,8 @@ public class ValidationManagerImplTest extends BriarTestCase { // Get message 3 and its metadata oneOf(db).getRawMessage(txn4, messageId3); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId3, raw); + will(returnValue(message3)); oneOf(db).getGroup(txn4, groupId); will(returnValue(group)); oneOf(db).getMessageMetadataForValidator(txn4, messageId3); @@ -1033,6 +1080,8 @@ public class ValidationManagerImplTest extends BriarTestCase { // Get message 4 and its metadata oneOf(db).getRawMessage(txn6, messageId4); will(returnValue(raw)); + oneOf(messageFactory).createMessage(messageId4, raw); + will(returnValue(message4)); oneOf(db).getGroup(txn6, groupId); will(returnValue(group)); oneOf(db).getMessageMetadataForValidator(txn6, messageId4); @@ -1049,7 +1098,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.eventOccurred(new MessageAddedEvent(message, contactId)); @@ -1063,6 +1112,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -1108,7 +1159,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.eventOccurred(new MessageAddedEvent(message, contactId)); @@ -1125,6 +1176,8 @@ public class ValidationManagerImplTest extends BriarTestCase { final DatabaseComponent db = context.mock(DatabaseComponent.class); final Executor dbExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor(); + final MessageFactory messageFactory = + context.mock(MessageFactory.class); final MessageValidator validator = context.mock(MessageValidator.class); final IncomingMessageHook hook = context.mock(IncomingMessageHook.class); @@ -1178,7 +1231,7 @@ public class ValidationManagerImplTest extends BriarTestCase { }}); ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, - cryptoExecutor); + cryptoExecutor, messageFactory); vm.registerMessageValidator(clientId, validator); vm.registerIncomingMessageHook(clientId, hook); vm.eventOccurred(new MessageAddedEvent(message, contactId));