mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Move post/message creation into clients
This way the forum and private group client do not need to keep track of message timestamps themselves and do not need to interact with post/message factories.
This commit is contained in:
@@ -3,16 +3,14 @@ package org.briarproject;
|
||||
import net.jodah.concurrentunit.Waiter;
|
||||
|
||||
import org.briarproject.api.Bytes;
|
||||
import org.briarproject.api.clients.MessageQueueManager;
|
||||
import org.briarproject.api.clients.ContactGroupFactory;
|
||||
import org.briarproject.api.clients.MessageQueueManager;
|
||||
import org.briarproject.api.clients.SessionId;
|
||||
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.KeyParser;
|
||||
import org.briarproject.api.crypto.PrivateKey;
|
||||
import org.briarproject.api.crypto.SecretKey;
|
||||
import org.briarproject.api.data.BdfList;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
@@ -820,12 +818,10 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
|
||||
|
||||
// sharer posts into the forum
|
||||
long time = clock.currentTimeMillis();
|
||||
byte[] body = TestUtils.getRandomBytes(42);
|
||||
KeyParser keyParser = cryptoComponent.getSignatureKeyParser();
|
||||
PrivateKey key = keyParser.parsePrivateKey(author0.getPrivateKey());
|
||||
String body = TestUtils.getRandomString(42);
|
||||
ForumPost p = forumPostFactory
|
||||
.createPseudonymousPost(forum0.getId(), time, null, author0,
|
||||
"text/plain", body, key);
|
||||
body);
|
||||
forumManager0.addLocalPost(p);
|
||||
|
||||
// sync forum post
|
||||
@@ -841,11 +837,10 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
|
||||
|
||||
// now invitee creates a post
|
||||
time = clock.currentTimeMillis();
|
||||
body = TestUtils.getRandomBytes(42);
|
||||
key = keyParser.parsePrivateKey(author1.getPrivateKey());
|
||||
body = TestUtils.getRandomString(42);
|
||||
p = forumPostFactory
|
||||
.createPseudonymousPost(forum0.getId(), time, null, author1,
|
||||
"text/plain", body, key);
|
||||
body);
|
||||
forumManager1.addLocalPost(p);
|
||||
|
||||
// sync forum post
|
||||
@@ -886,11 +881,10 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
|
||||
|
||||
// now invitee creates a post
|
||||
time = clock.currentTimeMillis();
|
||||
body = TestUtils.getRandomBytes(42);
|
||||
key = keyParser.parsePrivateKey(author1.getPrivateKey());
|
||||
body = TestUtils.getRandomString(42);
|
||||
p = forumPostFactory
|
||||
.createPseudonymousPost(forum0.getId(), time, null, author1,
|
||||
"text/plain", body, key);
|
||||
body);
|
||||
forumManager1.addLocalPost(p);
|
||||
|
||||
// sync forum post
|
||||
|
||||
@@ -6,8 +6,8 @@ import org.briarproject.api.crypto.PrivateKey;
|
||||
import org.briarproject.api.forum.ForumConstants;
|
||||
import org.briarproject.api.forum.ForumPost;
|
||||
import org.briarproject.api.forum.ForumPostFactory;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorFactory;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.messaging.MessagingConstants;
|
||||
import org.briarproject.api.messaging.PrivateMessage;
|
||||
import org.briarproject.api.messaging.PrivateMessageFactory;
|
||||
@@ -68,17 +68,17 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
|
||||
String authorName = TestUtils.getRandomString(
|
||||
MAX_AUTHOR_NAME_LENGTH);
|
||||
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
|
||||
Author author = authorFactory.createAuthor(authorName, authorPublic);
|
||||
PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
|
||||
LocalAuthor author = authorFactory
|
||||
.createLocalAuthor(authorName, authorPublic,
|
||||
privateKey.getEncoded());
|
||||
// Create a maximum-length forum post
|
||||
GroupId groupId = new GroupId(TestUtils.getRandomId());
|
||||
long timestamp = Long.MAX_VALUE;
|
||||
MessageId parent = new MessageId(TestUtils.getRandomId());
|
||||
String contentType = TestUtils.getRandomString(
|
||||
ForumConstants.MAX_CONTENT_TYPE_LENGTH);
|
||||
byte[] body = new byte[MAX_FORUM_POST_BODY_LENGTH];
|
||||
PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
|
||||
String body = TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
|
||||
ForumPost post = forumPostFactory.createPseudonymousPost(groupId,
|
||||
timestamp, parent, author, contentType, body, privateKey);
|
||||
timestamp, parent, author, body);
|
||||
// Check the size of the serialised message
|
||||
int length = post.getMessage().getRaw().length;
|
||||
assertTrue(length > UniqueId.LENGTH + 8 + UniqueId.LENGTH
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.feed.FeedManager;
|
||||
import org.briarproject.api.forum.ForumManager;
|
||||
import org.briarproject.api.forum.ForumPostFactory;
|
||||
import org.briarproject.api.forum.ForumSharingManager;
|
||||
import org.briarproject.api.identity.AuthorFactory;
|
||||
import org.briarproject.api.identity.IdentityManager;
|
||||
@@ -35,7 +34,6 @@ import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.api.plugins.ConnectionRegistry;
|
||||
import org.briarproject.api.plugins.PluginManager;
|
||||
import org.briarproject.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.api.privategroup.PrivateGroupManager;
|
||||
import org.briarproject.api.settings.SettingsManager;
|
||||
import org.briarproject.plugins.AndroidPluginsModule;
|
||||
@@ -97,16 +95,12 @@ public interface AndroidComponent extends CoreEagerSingletons {
|
||||
|
||||
PrivateGroupManager privateGroupManager();
|
||||
|
||||
GroupMessageFactory groupMessageFactory();
|
||||
|
||||
ForumManager forumManager();
|
||||
|
||||
ForumSharingManager forumSharingManager();
|
||||
|
||||
BlogSharingManager blogSharingManager();
|
||||
|
||||
ForumPostFactory forumPostFactory();
|
||||
|
||||
BlogManager blogManager();
|
||||
|
||||
BlogPostFactory blogPostFactory();
|
||||
|
||||
@@ -3,13 +3,8 @@ package org.briarproject.android.forum;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.briarproject.android.api.AndroidNotificationManager;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.android.threaded.ThreadListControllerImpl;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
import org.briarproject.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.api.crypto.KeyParser;
|
||||
import org.briarproject.api.crypto.PrivateKey;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.event.Event;
|
||||
@@ -18,47 +13,36 @@ import org.briarproject.api.event.ForumPostReceivedEvent;
|
||||
import org.briarproject.api.forum.Forum;
|
||||
import org.briarproject.api.forum.ForumManager;
|
||||
import org.briarproject.api.forum.ForumPost;
|
||||
import org.briarproject.api.forum.ForumPostFactory;
|
||||
import org.briarproject.api.forum.ForumPostHeader;
|
||||
import org.briarproject.api.identity.IdentityManager;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.identity.Author.Status.OURSELVES;
|
||||
|
||||
public class ForumControllerImpl
|
||||
extends ThreadListControllerImpl<Forum, ForumEntry, ForumPostHeader>
|
||||
extends ThreadListControllerImpl<Forum, ForumEntry, ForumPostHeader, ForumPost>
|
||||
implements ForumController {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(ForumControllerImpl.class.getName());
|
||||
|
||||
private final ForumPostFactory forumPostFactory;
|
||||
private final ForumManager forumManager;
|
||||
|
||||
@Inject
|
||||
ForumControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager,
|
||||
@CryptoExecutor Executor cryptoExecutor,
|
||||
ForumPostFactory forumPostFactory, CryptoComponent crypto,
|
||||
ForumManager forumManager, EventBus eventBus,
|
||||
IdentityManager identityManager,
|
||||
AndroidNotificationManager notificationManager) {
|
||||
super(dbExecutor, lifecycleManager, cryptoExecutor, crypto, eventBus,
|
||||
identityManager, notificationManager);
|
||||
super(dbExecutor, lifecycleManager, cryptoExecutor, eventBus,
|
||||
notificationManager);
|
||||
this.forumManager = forumManager;
|
||||
this.forumPostFactory = forumPostFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,7 +60,6 @@ public class ForumControllerImpl
|
||||
if (pe.getGroupId().equals(groupId)) {
|
||||
LOG.info("Forum post received, adding...");
|
||||
final ForumPostHeader fph = pe.getForumPostHeader();
|
||||
updateNewestTimestamp(fph.getTimestamp());
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -115,65 +98,15 @@ public class ForumControllerImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final String body, @Nullable final MessageId parentId,
|
||||
final ResultExceptionHandler<ForumEntry, DbException> handler) {
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Create post...");
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.max(timestamp, newestTimeStamp.get());
|
||||
ForumPost p;
|
||||
try {
|
||||
LocalAuthor a = identityManager.getLocalAuthor();
|
||||
KeyParser keyParser = crypto.getSignatureKeyParser();
|
||||
byte[] k = a.getPrivateKey();
|
||||
PrivateKey authorKey = keyParser.parsePrivateKey(k);
|
||||
byte[] b = StringUtils.toUtf8(body);
|
||||
p = forumPostFactory
|
||||
.createPseudonymousPost(groupId, timestamp,
|
||||
parentId, a, "text/plain", b, authorKey);
|
||||
} catch (GeneralSecurityException | FormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
return;
|
||||
}
|
||||
bodyCache.put(p.getMessage().getId(), body);
|
||||
storePost(p, handler);
|
||||
}
|
||||
});
|
||||
protected ForumPost createLocalMessage(GroupId g, String body,
|
||||
@Nullable MessageId parentId) throws DbException {
|
||||
return forumManager.createLocalPost(groupId, body, parentId);
|
||||
}
|
||||
|
||||
private void storePost(final ForumPost p,
|
||||
final ResultExceptionHandler<ForumEntry, DbException> resultHandler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LOG.info("Store post...");
|
||||
long now = System.currentTimeMillis();
|
||||
forumManager.addLocalPost(p);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Storing message took " + duration + " ms");
|
||||
|
||||
ForumPostHeader h =
|
||||
new ForumPostHeader(p.getMessage().getId(),
|
||||
p.getParent(),
|
||||
p.getMessage().getTimestamp(),
|
||||
p.getAuthor(), OURSELVES, true);
|
||||
|
||||
resultHandler.onResult(buildItem(h));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
resultHandler.onException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
@Override
|
||||
protected ForumPostHeader addLocalMessage(ForumPost p)
|
||||
throws DbException {
|
||||
return forumManager.addLocalPost(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,45 +2,46 @@ package org.briarproject.android.privategroup.conversation;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.android.api.AndroidNotificationManager;
|
||||
import org.briarproject.android.threaded.ThreadListControllerImpl;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.GroupMessageAddedEvent;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.privategroup.GroupMessage;
|
||||
import org.briarproject.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
||||
import org.briarproject.api.privategroup.PrivateGroup;
|
||||
import org.briarproject.api.privategroup.PrivateGroupManager;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.identity.Author.Status.OURSELVES;
|
||||
|
||||
public class GroupControllerImpl
|
||||
extends ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader>
|
||||
extends ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader, GroupMessage>
|
||||
implements GroupController {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(GroupControllerImpl.class.getName());
|
||||
|
||||
@Inject
|
||||
volatile GroupMessageFactory groupMessageFactory;
|
||||
@Inject
|
||||
volatile PrivateGroupManager privateGroupManager;
|
||||
private final PrivateGroupManager privateGroupManager;
|
||||
|
||||
@Inject
|
||||
GroupControllerImpl() {
|
||||
super();
|
||||
GroupControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager,
|
||||
@CryptoExecutor Executor cryptoExecutor,
|
||||
PrivateGroupManager privateGroupManager, EventBus eventBus,
|
||||
AndroidNotificationManager notificationManager) {
|
||||
super(dbExecutor, lifecycleManager, cryptoExecutor, eventBus,
|
||||
notificationManager);
|
||||
this.privateGroupManager = privateGroupManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,7 +59,6 @@ public class GroupControllerImpl
|
||||
if (!pe.isLocal() && pe.getGroupId().equals(groupId)) {
|
||||
LOG.info("Group message received, adding...");
|
||||
final GroupMessageHeader fph = pe.getHeader();
|
||||
updateNewestTimestamp(fph.getTimestamp());
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -97,59 +97,15 @@ public class GroupControllerImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final String body, @Nullable final MessageId parentId,
|
||||
final ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Create message...");
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.max(timestamp, newestTimeStamp.get());
|
||||
GroupMessage gm;
|
||||
try {
|
||||
LocalAuthor a = identityManager.getLocalAuthor();
|
||||
gm = groupMessageFactory.createGroupMessage(groupId,
|
||||
timestamp, parentId, a, body);
|
||||
} catch (GeneralSecurityException | FormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
return;
|
||||
}
|
||||
bodyCache.put(gm.getMessage().getId(), body);
|
||||
storeMessage(gm, handler);
|
||||
}
|
||||
});
|
||||
protected GroupMessage createLocalMessage(GroupId g, String body,
|
||||
@Nullable MessageId parentId) throws DbException {
|
||||
return privateGroupManager.createLocalMessage(groupId, body, parentId);
|
||||
}
|
||||
|
||||
private void storeMessage(final GroupMessage gm,
|
||||
final ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LOG.info("Store message...");
|
||||
long now = System.currentTimeMillis();
|
||||
privateGroupManager.addLocalMessage(gm);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Storing message took " + duration + " ms");
|
||||
|
||||
GroupMessageHeader h = new GroupMessageHeader(groupId,
|
||||
gm.getMessage().getId(), gm.getParent(),
|
||||
gm.getMessage().getTimestamp(), gm.getAuthor(),
|
||||
OURSELVES, true);
|
||||
|
||||
handler.onResult(buildItem(h));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
@Override
|
||||
protected GroupMessageHeader addLocalMessage(GroupMessage message)
|
||||
throws DbException {
|
||||
return privateGroupManager.addLocalMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,13 +2,14 @@ package org.briarproject.android.threaded;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.annotation.CallSuper;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.briarproject.android.api.AndroidNotificationManager;
|
||||
import org.briarproject.android.controller.DbControllerImpl;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.api.clients.BaseGroup;
|
||||
import org.briarproject.api.clients.BaseMessage;
|
||||
import org.briarproject.api.clients.PostHeader;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
import org.briarproject.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
@@ -16,9 +17,6 @@ import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.EventListener;
|
||||
import org.briarproject.api.event.GroupRemovedEvent;
|
||||
import org.briarproject.api.forum.ForumManager;
|
||||
import org.briarproject.api.forum.ForumPostFactory;
|
||||
import org.briarproject.api.identity.IdentityManager;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
@@ -30,13 +28,12 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends ThreadItem, H extends PostHeader>
|
||||
public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends ThreadItem, H extends PostHeader, M extends BaseMessage>
|
||||
extends DbControllerImpl
|
||||
implements ThreadListController<G, I, H>, EventListener {
|
||||
|
||||
@@ -44,14 +41,11 @@ public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends Th
|
||||
Logger.getLogger(ThreadListControllerImpl.class.getName());
|
||||
|
||||
protected final Executor cryptoExecutor;
|
||||
protected final CryptoComponent crypto;
|
||||
protected final EventBus eventBus;
|
||||
protected final IdentityManager identityManager;
|
||||
protected final AndroidNotificationManager notificationManager;
|
||||
private final EventBus eventBus;
|
||||
|
||||
protected final Map<MessageId, String> bodyCache =
|
||||
new ConcurrentHashMap<>();
|
||||
protected final AtomicLong newestTimeStamp = new AtomicLong();
|
||||
|
||||
protected volatile GroupId groupId;
|
||||
|
||||
@@ -59,14 +53,11 @@ public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends Th
|
||||
|
||||
protected ThreadListControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager,
|
||||
@CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto,
|
||||
EventBus eventBus, IdentityManager identityManager,
|
||||
@CryptoExecutor Executor cryptoExecutor, EventBus eventBus,
|
||||
AndroidNotificationManager notificationManager) {
|
||||
super(dbExecutor, lifecycleManager);
|
||||
this.cryptoExecutor = cryptoExecutor;
|
||||
this.crypto = crypto;
|
||||
this.eventBus = eventBus;
|
||||
this.identityManager = identityManager;
|
||||
this.notificationManager = notificationManager;
|
||||
}
|
||||
|
||||
@@ -164,9 +155,6 @@ public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends Th
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading headers took " + duration + " ms");
|
||||
|
||||
// Update timestamp of newest item
|
||||
updateNewestTimeStamp(headers);
|
||||
|
||||
// Load bodies
|
||||
now = System.currentTimeMillis();
|
||||
loadBodies(headers);
|
||||
@@ -259,6 +247,63 @@ public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends Th
|
||||
send(body, null, resultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final String body, @Nullable final MessageId parentId,
|
||||
final ResultExceptionHandler<I, DbException> handler) {
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Creating message...");
|
||||
try {
|
||||
M msg = createLocalMessage(groupId, body, parentId);
|
||||
bodyCache.put(msg.getMessage().getId(), body);
|
||||
storePost(msg, handler);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This should only be run from the DbThread.
|
||||
*
|
||||
* @throws DbException
|
||||
*/
|
||||
protected abstract M createLocalMessage(GroupId g, String body,
|
||||
@Nullable MessageId parentId) throws DbException;
|
||||
|
||||
private void storePost(final M p,
|
||||
final ResultExceptionHandler<I, DbException> resultHandler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LOG.info("Store message...");
|
||||
long now = System.currentTimeMillis();
|
||||
H h = addLocalMessage(p);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Storing message took " + duration + " ms");
|
||||
resultHandler.onResult(buildItem(h));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
resultHandler.onException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This should only be run from the DbThread.
|
||||
*
|
||||
* @throws DbException
|
||||
*/
|
||||
protected abstract H addLocalMessage(M message) throws DbException;
|
||||
|
||||
@Override
|
||||
public void deleteGroupItem(
|
||||
final ResultExceptionHandler<Void, DbException> handler) {
|
||||
@@ -303,20 +348,6 @@ public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends Th
|
||||
*/
|
||||
protected abstract I buildItem(H header);
|
||||
|
||||
private void updateNewestTimeStamp(Collection<H> headers) {
|
||||
for (H h : headers) {
|
||||
updateNewestTimestamp(h.getTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateNewestTimestamp(long update) {
|
||||
long newest = newestTimeStamp.get();
|
||||
while (newest < update) {
|
||||
if (newestTimeStamp.compareAndSet(newest, update)) return;
|
||||
newest = newestTimeStamp.get();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkGroupId() {
|
||||
if (groupId == null) {
|
||||
throw new IllegalStateException(
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.briarproject.api.db.Transaction;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -20,8 +21,12 @@ public interface ForumManager extends MessageTracker {
|
||||
/** Unsubscribes from a forum. */
|
||||
void removeForum(Forum f) throws DbException;
|
||||
|
||||
/** Creates a local forum post. */
|
||||
ForumPost createLocalPost(GroupId groupId, String text,
|
||||
@Nullable MessageId parentId) throws DbException;
|
||||
|
||||
/** Stores a local forum post. */
|
||||
void addLocalPost(ForumPost p) throws DbException;
|
||||
ForumPostHeader addLocalPost(ForumPost p) throws DbException;
|
||||
|
||||
/** Returns the forum with the given ID. */
|
||||
Forum getForum(GroupId g) throws DbException;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package org.briarproject.api.forum;
|
||||
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.crypto.PrivateKey;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
|
||||
@@ -15,7 +14,6 @@ public interface ForumPostFactory {
|
||||
throws FormatException;
|
||||
|
||||
ForumPost createPseudonymousPost(GroupId groupId, long timestamp,
|
||||
MessageId parent, Author author, String contentType, byte[] body,
|
||||
PrivateKey privateKey) throws FormatException,
|
||||
GeneralSecurityException;
|
||||
MessageId parent, LocalAuthor author, String body)
|
||||
throws FormatException, GeneralSecurityException;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -19,8 +20,12 @@ public interface PrivateGroupManager extends MessageTracker {
|
||||
/** Removes a dissolved private group. */
|
||||
void removePrivateGroup(GroupId g) throws DbException;
|
||||
|
||||
/** Creates a local group message. */
|
||||
GroupMessage createLocalMessage(GroupId groupId, String text,
|
||||
@Nullable MessageId parentId) throws DbException;
|
||||
|
||||
/** Stores (and sends) a local group message. */
|
||||
void addLocalMessage(GroupMessage p) throws DbException;
|
||||
GroupMessageHeader addLocalMessage(GroupMessage p) throws DbException;
|
||||
|
||||
/** Returns the private group with the given ID. */
|
||||
@NotNull
|
||||
|
||||
@@ -13,19 +13,24 @@ import org.briarproject.api.forum.Forum;
|
||||
import org.briarproject.api.forum.ForumFactory;
|
||||
import org.briarproject.api.forum.ForumManager;
|
||||
import org.briarproject.api.forum.ForumPost;
|
||||
import org.briarproject.api.forum.ForumPostFactory;
|
||||
import org.briarproject.api.forum.ForumPostHeader;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.Author.Status;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.IdentityManager;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.clients.BdfIncomingMessageHook;
|
||||
import org.briarproject.util.StringUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -47,6 +52,7 @@ import static org.briarproject.api.forum.ForumConstants.KEY_PARENT;
|
||||
import static org.briarproject.api.forum.ForumConstants.KEY_PUBLIC_NAME;
|
||||
import static org.briarproject.api.forum.ForumConstants.KEY_TIMESTAMP;
|
||||
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;
|
||||
|
||||
class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
|
||||
@@ -57,16 +63,21 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
|
||||
|
||||
private final IdentityManager identityManager;
|
||||
private final ForumFactory forumFactory;
|
||||
private final ForumPostFactory forumPostFactory;
|
||||
private final Clock clock;
|
||||
private final List<RemoveForumHook> removeHooks;
|
||||
|
||||
@Inject
|
||||
ForumManagerImpl(DatabaseComponent db, IdentityManager identityManager,
|
||||
ClientHelper clientHelper, MetadataParser metadataParser,
|
||||
ForumFactory forumFactory) {
|
||||
ForumFactory forumFactory, ForumPostFactory forumPostFactory,
|
||||
Clock clock) {
|
||||
super(db, clientHelper, metadataParser);
|
||||
|
||||
this.identityManager = identityManager;
|
||||
this.forumFactory = forumFactory;
|
||||
this.forumPostFactory = forumPostFactory;
|
||||
this.clock = clock;
|
||||
removeHooks = new CopyOnWriteArrayList<RemoveForumHook>();
|
||||
}
|
||||
|
||||
@@ -118,7 +129,38 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLocalPost(ForumPost p) throws DbException {
|
||||
public ForumPost createLocalPost(final GroupId groupId,
|
||||
final String body, final @Nullable MessageId parentId)
|
||||
throws DbException {
|
||||
|
||||
LocalAuthor author;
|
||||
GroupCount count;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
author = identityManager.getLocalAuthor(txn);
|
||||
count = getGroupCount(txn, groupId);
|
||||
txn.setComplete();
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
timestamp = Math.max(timestamp, count.getLatestMsgTime());
|
||||
|
||||
ForumPost p;
|
||||
try {
|
||||
p = forumPostFactory
|
||||
.createPseudonymousPost(groupId, timestamp, parentId,
|
||||
author, body);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForumPostHeader addLocalPost(ForumPost p) throws DbException {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
@@ -142,6 +184,8 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return new ForumPostHeader(p.getMessage().getId(), p.getParent(),
|
||||
p.getMessage().getTimestamp(), p.getAuthor(), OURSELVES, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,12 +3,13 @@ package org.briarproject.forum;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
import org.briarproject.api.crypto.KeyParser;
|
||||
import org.briarproject.api.crypto.PrivateKey;
|
||||
import org.briarproject.api.crypto.Signature;
|
||||
import org.briarproject.api.data.BdfList;
|
||||
import org.briarproject.api.forum.ForumPost;
|
||||
import org.briarproject.api.forum.ForumPostFactory;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
@@ -49,9 +50,10 @@ class ForumPostFactoryImpl implements ForumPostFactory {
|
||||
|
||||
@Override
|
||||
public ForumPost createPseudonymousPost(GroupId groupId, long timestamp,
|
||||
MessageId parent, Author author, String contentType, byte[] body,
|
||||
PrivateKey privateKey) throws FormatException,
|
||||
GeneralSecurityException {
|
||||
MessageId parent, LocalAuthor author, String bodyStr)
|
||||
throws FormatException, GeneralSecurityException {
|
||||
String contentType = "text/plain";
|
||||
byte[] body = StringUtils.toUtf8(bodyStr);
|
||||
// Validate the arguments
|
||||
if (StringUtils.toUtf8(contentType).length > MAX_CONTENT_TYPE_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
@@ -62,6 +64,10 @@ class ForumPostFactoryImpl implements ForumPostFactory {
|
||||
author.getPublicKey());
|
||||
BdfList signed = BdfList.of(groupId, timestamp, parent, authorList,
|
||||
contentType, body);
|
||||
// Get private key
|
||||
KeyParser keyParser = crypto.getSignatureKeyParser();
|
||||
byte[] k = author.getPrivateKey();
|
||||
PrivateKey privateKey = keyParser.parsePrivateKey(k);
|
||||
// Generate the signature
|
||||
Signature signature = crypto.getSignature();
|
||||
signature.initSign(privateKey);
|
||||
|
||||
@@ -9,7 +9,9 @@ import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.Transaction;
|
||||
import org.briarproject.api.identity.IdentityManager;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.privategroup.GroupMessage;
|
||||
import org.briarproject.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
||||
import org.briarproject.api.privategroup.PrivateGroup;
|
||||
import org.briarproject.api.privategroup.PrivateGroupFactory;
|
||||
@@ -19,16 +21,21 @@ import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.clients.BdfIncomingMessageHook;
|
||||
import org.briarproject.util.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.api.identity.Author.Status.OURSELVES;
|
||||
|
||||
public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
||||
PrivateGroupManager {
|
||||
|
||||
@@ -40,16 +47,21 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
||||
|
||||
private final IdentityManager identityManager;
|
||||
private final PrivateGroupFactory privateGroupFactory;
|
||||
private final GroupMessageFactory groupMessageFactory;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
PrivateGroupManagerImpl(ClientHelper clientHelper,
|
||||
MetadataParser metadataParser, DatabaseComponent db,
|
||||
IdentityManager identityManager,
|
||||
PrivateGroupFactory privateGroupFactory) {
|
||||
PrivateGroupFactory privateGroupFactory,
|
||||
GroupMessageFactory groupMessageFactory, Clock clock) {
|
||||
super(db, clientHelper, metadataParser);
|
||||
|
||||
this.identityManager = identityManager;
|
||||
this.privateGroupFactory = privateGroupFactory;
|
||||
this.groupMessageFactory = groupMessageFactory;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -64,7 +76,25 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLocalMessage(GroupMessage m) throws DbException {
|
||||
public GroupMessage createLocalMessage(GroupId groupId, String body,
|
||||
@Nullable MessageId parentId) throws DbException {
|
||||
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
try {
|
||||
return groupMessageFactory
|
||||
.createGroupMessage(groupId, timestamp, parentId, author,
|
||||
body);
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupMessageHeader addLocalMessage(GroupMessage m)
|
||||
throws DbException {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
@@ -76,6 +106,9 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return new GroupMessageHeader(m.getMessage().getGroupId(),
|
||||
m.getMessage().getId(), m.getParent(),
|
||||
m.getMessage().getTimestamp(), m.getAuthor(), OURSELVES, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
Reference in New Issue
Block a user