Merge branch '392-use-new-metadata-queries-for-forum-sharing' into 'master'

Handle invitations to the same forum by multiple contacts

This also uses the new metadata queries in the forum sharing client.

Please note that this is based on !184.

See merge request !188
This commit is contained in:
Torsten Grote
2016-05-19 14:35:58 +00:00
4 changed files with 210 additions and 75 deletions

View File

@@ -49,6 +49,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -65,15 +66,15 @@ import static org.junit.Assert.assertTrue;
public class ForumSharingIntegrationTest extends BriarTestCase { public class ForumSharingIntegrationTest extends BriarTestCase {
LifecycleManager lifecycleManager0, lifecycleManager1; LifecycleManager lifecycleManager0, lifecycleManager1, lifecycleManager2;
SyncSessionFactory sync0, sync1; SyncSessionFactory sync0, sync1, sync2;
ForumManager forumManager0, forumManager1; ForumManager forumManager0, forumManager1, forumManager2;
ContactManager contactManager0, contactManager1; ContactManager contactManager0, contactManager1, contactManager2;
ContactId contactId0, contactId1; ContactId contactId0, contactId2, contactId1, contactId21;
IdentityManager identityManager0, identityManager1; IdentityManager identityManager0, identityManager1, identityManager2;
LocalAuthor author0, author1; LocalAuthor author0, author1, author2;
Forum forum0; Forum forum0;
SharerListener listener0; SharerListener listener0, listener2;
InviteeListener listener1; InviteeListener listener1;
@Inject @Inject
@@ -84,6 +85,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// objects accessed from background threads need to be volatile // objects accessed from background threads need to be volatile
private volatile ForumSharingManager forumSharingManager0; private volatile ForumSharingManager forumSharingManager0;
private volatile ForumSharingManager forumSharingManager1; private volatile ForumSharingManager forumSharingManager1;
private volatile ForumSharingManager forumSharingManager2;
private volatile Waiter eventWaiter; private volatile Waiter eventWaiter;
private volatile Waiter msgWaiter; private volatile Waiter msgWaiter;
@@ -92,11 +94,12 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
private final int TIMEOUT = 15000; private final int TIMEOUT = 15000;
private final String SHARER = "Sharer"; private final String SHARER = "Sharer";
private final String INVITEE = "Invitee"; private final String INVITEE = "Invitee";
private final String SHARER2 = "Sharer2";
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(ForumSharingIntegrationTest.class.getName()); Logger.getLogger(ForumSharingIntegrationTest.class.getName());
private ForumSharingIntegrationTestComponent t0, t1; private ForumSharingIntegrationTestComponent t0, t1, t2;
@Rule @Rule
public ExpectedException thrown=ExpectedException.none(); public ExpectedException thrown=ExpectedException.none();
@@ -117,17 +120,26 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
t1 = DaggerForumSharingIntegrationTestComponent.builder() t1 = DaggerForumSharingIntegrationTestComponent.builder()
.testDatabaseModule(new TestDatabaseModule(t1Dir)).build(); .testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
injectEagerSingletons(t1); injectEagerSingletons(t1);
File t2Dir = new File(testDir, SHARER2);
t2 = DaggerForumSharingIntegrationTestComponent.builder()
.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
injectEagerSingletons(t2);
identityManager0 = t0.getIdentityManager(); identityManager0 = t0.getIdentityManager();
identityManager1 = t1.getIdentityManager(); identityManager1 = t1.getIdentityManager();
identityManager2 = t2.getIdentityManager();
contactManager0 = t0.getContactManager(); contactManager0 = t0.getContactManager();
contactManager1 = t1.getContactManager(); contactManager1 = t1.getContactManager();
contactManager2 = t2.getContactManager();
forumManager0 = t0.getForumManager(); forumManager0 = t0.getForumManager();
forumManager1 = t1.getForumManager(); forumManager1 = t1.getForumManager();
forumManager2 = t2.getForumManager();
forumSharingManager0 = t0.getForumSharingManager(); forumSharingManager0 = t0.getForumSharingManager();
forumSharingManager1 = t1.getForumSharingManager(); forumSharingManager1 = t1.getForumSharingManager();
forumSharingManager2 = t2.getForumSharingManager();
sync0 = t0.getSyncSessionFactory(); sync0 = t0.getSyncSessionFactory();
sync1 = t1.getSyncSessionFactory(); sync1 = t1.getSyncSessionFactory();
sync2 = t2.getSyncSessionFactory();
// initialize waiters fresh for each test // initialize waiters fresh for each test
eventWaiter = new Waiter(); eventWaiter = new Waiter();
@@ -474,7 +486,8 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
assertEquals(1, forumManager1.getForums().size()); assertEquals(1, forumManager1.getForums().size());
// invitee now shares same forum back // invitee now shares same forum back
forumSharingManager1.sendForumInvitation(forum0.getId(), contactId0, forumSharingManager1.sendForumInvitation(forum0.getId(),
contactId0,
"I am re-sharing this forum with you."); "I am re-sharing this forum with you.");
// sync re-share invitation // sync re-share invitation
@@ -526,7 +539,9 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// contacts now remove each other // contacts now remove each other
contactManager0.removeContact(contactId1); contactManager0.removeContact(contactId1);
contactManager2.removeContact(contactId21);
contactManager1.removeContact(contactId0); contactManager1.removeContact(contactId0);
contactManager1.removeContact(contactId2);
// make sure sharer does share the forum with nobody now // make sure sharer does share the forum with nobody now
assertEquals(0, assertEquals(0,
@@ -572,6 +587,75 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
} }
} }
@Test
public void testTwoContactsShareSameForum() throws Exception {
startLifecycles();
try {
// initialize
addDefaultIdentities();
addDefaultContacts();
addForumForSharer();
// second sharer adds the same forum
DatabaseComponent db2 = t2.getDatabaseComponent();
Transaction txn = db2.startTransaction(false);
db2.addGroup(txn, forum0.getGroup());
txn.setComplete();
db2.endTransaction(txn);
// add listeners
listener0 = new SharerListener();
t0.getEventBus().addListener(listener0);
listener1 = new InviteeListener(true, false);
t1.getEventBus().addListener(listener1);
listener2 = new SharerListener();
t2.getEventBus().addListener(listener2);
// send invitation
forumSharingManager0
.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
// sync first request message
syncToInvitee();
// second sharer sends invitation for same forum
forumSharingManager2
.sendForumInvitation(forum0.getId(), contactId1, null);
// sync second request message
deliverMessage(sync2, contactId2, sync1, contactId1,
"Sharer2 to Invitee");
// make sure we have only one forum available
Collection<Forum> forums =
forumSharingManager1.getAvailableForums();
assertEquals(1, forums.size());
// make sure both sharers actually share the forum
Collection<Contact> contacts =
forumSharingManager1.getSharedBy(forum0.getId());
assertEquals(2, contacts.size());
// answer second request
Contact c2 = contactManager1.getContact(contactId2);
forumSharingManager1.respondToInvitation(forum0, c2, true);
// sync response
deliverMessage(sync1, contactId21, sync2, contactId2,
"Invitee to Sharer2");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener2.responseReceived);
// answer first request
Contact c0 =
contactManager1.getContact(contactId0);
forumSharingManager1.respondToInvitation(forum0, c0, true);
// sync response
syncToSharer();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
} finally {
stopLifecycles();
}
}
@After @After
public void tearDown() throws InterruptedException { public void tearDown() throws InterruptedException {
@@ -609,7 +693,8 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
requestReceived = true; requestReceived = true;
Forum f = event.getForum(); Forum f = event.getForum();
try { try {
forumSharingManager0.respondToInvitation(f, true); Contact c = contactManager0.getContact(contactId1);
forumSharingManager0.respondToInvitation(f, c, true);
} catch (DbException ex) { } catch (DbException ex) {
eventWaiter.rethrow(ex); eventWaiter.rethrow(ex);
} finally { } finally {
@@ -624,10 +709,15 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
public volatile boolean requestReceived = false; public volatile boolean requestReceived = false;
public volatile boolean responseReceived = false; public volatile boolean responseReceived = false;
private final boolean accept; private final boolean accept, answer;
InviteeListener(boolean accept, boolean answer) {
this.accept = accept;
this.answer = answer;
}
InviteeListener(boolean accept) { InviteeListener(boolean accept) {
this.accept = accept; this(accept, true);
} }
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
@@ -644,11 +734,13 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
} else if (e instanceof ForumInvitationReceivedEvent) { } else if (e instanceof ForumInvitationReceivedEvent) {
ForumInvitationReceivedEvent event = ForumInvitationReceivedEvent event =
(ForumInvitationReceivedEvent) e; (ForumInvitationReceivedEvent) e;
eventWaiter.assertEquals(contactId0, event.getContactId());
requestReceived = true; requestReceived = true;
if (!answer) return;
Forum f = event.getForum(); Forum f = event.getForum();
try { try {
forumSharingManager1.respondToInvitation(f, accept); Contact c =
contactManager1.getContact(event.getContactId());
forumSharingManager1.respondToInvitation(f, c, accept);
} catch (DbException ex) { } catch (DbException ex) {
eventWaiter.rethrow(ex); eventWaiter.rethrow(ex);
} finally { } finally {
@@ -670,18 +762,23 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// Start the lifecycle manager and wait for it to finish // Start the lifecycle manager and wait for it to finish
lifecycleManager0 = t0.getLifecycleManager(); lifecycleManager0 = t0.getLifecycleManager();
lifecycleManager1 = t1.getLifecycleManager(); lifecycleManager1 = t1.getLifecycleManager();
lifecycleManager2 = t2.getLifecycleManager();
lifecycleManager0.startServices(); lifecycleManager0.startServices();
lifecycleManager1.startServices(); lifecycleManager1.startServices();
lifecycleManager2.startServices();
lifecycleManager0.waitForStartup(); lifecycleManager0.waitForStartup();
lifecycleManager1.waitForStartup(); lifecycleManager1.waitForStartup();
lifecycleManager2.waitForStartup();
} }
private void stopLifecycles() throws InterruptedException { private void stopLifecycles() throws InterruptedException {
// Clean up // Clean up
lifecycleManager0.stopServices(); lifecycleManager0.stopServices();
lifecycleManager1.stopServices(); lifecycleManager1.stopServices();
lifecycleManager2.stopServices();
lifecycleManager0.waitForShutdown(); lifecycleManager0.waitForShutdown();
lifecycleManager1.waitForShutdown(); lifecycleManager1.waitForShutdown();
lifecycleManager2.waitForShutdown();
} }
private void defaultInit(boolean accept) throws DbException { private void defaultInit(boolean accept) throws DbException {
@@ -700,6 +797,10 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH), TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123)); TestUtils.getRandomBytes(123));
identityManager1.addLocalAuthor(author1); identityManager1.addLocalAuthor(author1);
author2 = authorFactory.createLocalAuthor(SHARER2,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager2.addLocalAuthor(author2);
} }
private void addDefaultContacts() throws DbException { private void addDefaultContacts() throws DbException {
@@ -708,11 +809,20 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
author0.getId(), master, clock.currentTimeMillis(), true, author0.getId(), master, clock.currentTimeMillis(), true,
true true
); );
// invitee adds sharer back // second sharer does the same
contactId21 = contactManager2.addContact(author1,
author2.getId(), master, clock.currentTimeMillis(), true,
true
);
// invitee adds sharers back
contactId0 = contactManager1.addContact(author0, contactId0 = contactManager1.addContact(author0,
author1.getId(), master, clock.currentTimeMillis(), true, author1.getId(), master, clock.currentTimeMillis(), true,
true true
); );
contactId2 = contactManager1.addContact(author2,
author1.getId(), master, clock.currentTimeMillis(), true,
true
);
} }
private void addForumForSharer() throws DbException { private void addForumForSharer() throws DbException {
@@ -725,6 +835,8 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
t0.getEventBus().addListener(listener0); t0.getEventBus().addListener(listener0);
listener1 = new InviteeListener(accept); listener1 = new InviteeListener(accept);
t1.getEventBus().addListener(listener1); t1.getEventBus().addListener(listener1);
listener2 = new SharerListener();
t2.getEventBus().addListener(listener2);
} }
private void syncToInvitee() throws IOException, TimeoutException { private void syncToInvitee() throws IOException, TimeoutException {

View File

@@ -153,7 +153,7 @@ public class AvailableForumsActivity extends BriarActivity
@Override @Override
public void onItemClick(AvailableForumsItem item, boolean accept) { public void onItemClick(AvailableForumsItem item, boolean accept) {
respondToInvitation(item.getForum(), accept); respondToInvitation(item, accept);
// show toast // show toast
int res = R.string.forum_declined_toast; int res = R.string.forum_declined_toast;
@@ -161,12 +161,16 @@ public class AvailableForumsActivity extends BriarActivity
Toast.makeText(this, res, LENGTH_SHORT).show(); Toast.makeText(this, res, LENGTH_SHORT).show();
} }
private void respondToInvitation(final Forum f, final boolean accept) { private void respondToInvitation(final AvailableForumsItem item,
runOnDbThread(new Runnable() { final boolean accept) {
briarController.runOnDbThread(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
forumSharingManager.respondToInvitation(f, accept); Forum f = item.getForum();
for (Contact c : item.getContacts()) {
forumSharingManager.respondToInvitation(f, c, accept);
}
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);

View File

@@ -24,7 +24,8 @@ public interface ForumSharingManager {
/** /**
* Responds to a pending forum invitation * Responds to a pending forum invitation
*/ */
void respondToInvitation(Forum f, boolean accept) throws DbException; void respondToInvitation(Forum f, Contact c, boolean accept)
throws DbException;
/** /**
* Returns all forum sharing messages sent by the Contact * Returns all forum sharing messages sent by the Contact

View File

@@ -55,6 +55,7 @@ import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.api.clients.ProtocolEngine.StateUpdate; import static org.briarproject.api.clients.ProtocolEngine.StateUpdate;
import static org.briarproject.api.forum.ForumConstants.CONTACT_ID; import static org.briarproject.api.forum.ForumConstants.CONTACT_ID;
import static org.briarproject.api.forum.ForumConstants.FORUM_ID;
import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH; import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
import static org.briarproject.api.forum.ForumConstants.IS_SHARER; import static org.briarproject.api.forum.ForumConstants.IS_SHARER;
import static org.briarproject.api.forum.ForumConstants.LOCAL; import static org.briarproject.api.forum.ForumConstants.LOCAL;
@@ -67,6 +68,7 @@ import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ACCEPT;
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE; import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE;
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION; import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE; import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE;
import static org.briarproject.api.forum.ForumConstants.STATE;
import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US; import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US;
import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US; import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US;
import static org.briarproject.api.forum.ForumConstants.TASK_ADD_SHARED_FORUM; import static org.briarproject.api.forum.ForumConstants.TASK_ADD_SHARED_FORUM;
@@ -155,16 +157,18 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
@Override @Override
public void removingContact(Transaction txn, Contact c) throws DbException { public void removingContact(Transaction txn, Contact c) throws DbException {
// query for this contact c
BdfDictionary query = BdfDictionary.of(
new BdfEntry(CONTACT_ID, c.getId().getInt())
);
// clean up session states with that contact from localGroup // clean up session states with that contact from localGroup
Long id = (long) c.getId().getInt();
try { try {
Map<MessageId, BdfDictionary> map = clientHelper Map<MessageId, BdfDictionary> map = clientHelper
.getMessageMetadataAsDictionary(txn, localGroup.getId()); .getMessageMetadataAsDictionary(txn, localGroup.getId(),
query);
for (Map.Entry<MessageId, BdfDictionary> entry : map.entrySet()) { for (Map.Entry<MessageId, BdfDictionary> entry : map.entrySet()) {
BdfDictionary d = entry.getValue(); deleteMessage(txn, entry.getKey());
if (id.equals(d.getLong(CONTACT_ID))) {
deleteMessage(txn, entry.getKey());
}
} }
} catch (FormatException e) { } catch (FormatException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
@@ -279,13 +283,14 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
} }
@Override @Override
public void respondToInvitation(Forum f, boolean accept) public void respondToInvitation(Forum f, Contact c, boolean accept)
throws DbException { throws DbException {
Transaction txn = db.startTransaction(false); Transaction txn = db.startTransaction(false);
try { try {
// find session state based on forum // find session state based on forum
InviteeSessionState localState = getSessionStateForResponse(txn, f); InviteeSessionState localState =
getSessionStateForResponse(txn, f, c);
// define action // define action
InviteeSessionState.Action localAction; InviteeSessionState.Action localAction;
@@ -312,6 +317,11 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
public Collection<ForumInvitationMessage> getForumInvitationMessages( public Collection<ForumInvitationMessage> getForumInvitationMessages(
ContactId contactId) throws DbException { ContactId contactId) throws DbException {
// query for all invitations
BdfDictionary query = BdfDictionary.of(
new BdfEntry(TYPE, SHARE_MSG_TYPE_INVITATION)
);
Transaction txn = db.startTransaction(false); Transaction txn = db.startTransaction(false);
try { try {
Contact contact = db.getContact(txn, contactId); Contact contact = db.getContact(txn, contactId);
@@ -320,13 +330,10 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
Collection<ForumInvitationMessage> list = Collection<ForumInvitationMessage> list =
new ArrayList<ForumInvitationMessage>(); new ArrayList<ForumInvitationMessage>();
Map<MessageId, BdfDictionary> map = clientHelper Map<MessageId, BdfDictionary> map = clientHelper
.getMessageMetadataAsDictionary(txn, group.getId()); .getMessageMetadataAsDictionary(txn, group.getId(), query);
for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) { for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
BdfDictionary d = m.getValue(); BdfDictionary d = m.getValue();
try { try {
if (d.getLong(TYPE) != SHARE_MSG_TYPE_INVITATION)
continue;
Invitation msg = Invitation.from(group.getId(), d); Invitation msg = Invitation.from(group.getId(), d);
MessageStatus status = MessageStatus status =
db.getMessageStatus(txn, contactId, m.getKey()); db.getMessageStatus(txn, contactId, m.getKey());
@@ -542,23 +549,29 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
try { try {
return getSessionStateForSharer(txn, sessionId); return getSessionStateForSharer(txn, sessionId);
} catch (NoSuchMessageException e) { } catch (NoSuchMessageException e) {
// State not found directly, so iterate over all states // State not found directly, so query for state for invitee
// to find state for invitee BdfDictionary query = BdfDictionary.of(
new BdfEntry(SESSION_ID, sessionId)
);
Map<MessageId, BdfDictionary> map = clientHelper Map<MessageId, BdfDictionary> map = clientHelper
.getMessageMetadataAsDictionary(txn, localGroup.getId()); .getMessageMetadataAsDictionary(txn, localGroup.getId(),
for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) { query);
BdfDictionary state = m.getValue();
if (Arrays.equals(state.getRaw(SESSION_ID), if (map.size() > 1 && LOG.isLoggable(WARNING)) {
sessionId.getBytes())) {
return fromBdfDictionary(state);
}
}
if (warn && LOG.isLoggable(WARNING)) {
LOG.warning( LOG.warning(
"No session state found for message with session ID " + "More than one session state found for message with session ID " +
Arrays.hashCode(sessionId.getBytes())); Arrays.hashCode(sessionId.getBytes()));
} }
throw new FormatException(); if (map.isEmpty()) {
if (warn && LOG.isLoggable(WARNING)) {
LOG.warning(
"No session state found for message with session ID " +
Arrays.hashCode(sessionId.getBytes()));
}
throw new FormatException();
}
return fromBdfDictionary(map.values().iterator().next());
} }
} }
@@ -576,50 +589,55 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
} }
private InviteeSessionState getSessionStateForResponse(Transaction txn, private InviteeSessionState getSessionStateForResponse(Transaction txn,
Forum f) throws DbException, FormatException { Forum f, Contact c) throws DbException, FormatException {
// query for invitee states for that forum in state await response
BdfDictionary query = BdfDictionary.of(
new BdfEntry(IS_SHARER, false),
new BdfEntry(CONTACT_ID, c.getId().getInt()),
new BdfEntry(FORUM_ID, f.getId()),
new BdfEntry(STATE,
InviteeSessionState.State.AWAIT_LOCAL_RESPONSE
.getValue())
);
Map<MessageId, BdfDictionary> map = clientHelper Map<MessageId, BdfDictionary> map = clientHelper
.getMessageMetadataAsDictionary(txn, localGroup.getId()); .getMessageMetadataAsDictionary(txn, localGroup.getId(), query);
for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
BdfDictionary d = m.getValue();
try {
ForumSharingSessionState s = fromBdfDictionary(d);
if (!(s instanceof InviteeSessionState)) continue;
if (!f.getId().equals(s.getForumId())) continue;
InviteeSessionState state = (InviteeSessionState) s; if (map.size() > 1 && LOG.isLoggable(WARNING)) {
if (state.getState() == LOG.warning(
InviteeSessionState.State.AWAIT_LOCAL_RESPONSE) { "More than one session state found for forum with ID " +
// Note that there should always be only one session Arrays.hashCode(f.getId().getBytes()) +
// in this state for the same forum " in state AWAIT_LOCAL_RESPONSE for contact " +
return state; c.getAuthor().getName());
}
} catch (FormatException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
} }
throw new DbException(); if (map.isEmpty()) {
if (LOG.isLoggable(WARNING)) {
LOG.warning(
"No session state found for forum with ID " +
Arrays.hashCode(f.getId().getBytes()) +
" in state AWAIT_LOCAL_RESPONSE");
}
throw new DbException();
}
return (InviteeSessionState) fromBdfDictionary(
map.values().iterator().next());
} }
private ForumSharingSessionState getSessionStateForLeaving(Transaction txn, private ForumSharingSessionState getSessionStateForLeaving(Transaction txn,
Forum f, ContactId c) throws DbException, FormatException { Forum f, ContactId c) throws DbException, FormatException {
BdfDictionary query = BdfDictionary.of(
new BdfEntry(CONTACT_ID, c.getInt()),
new BdfEntry(FORUM_ID, f.getId())
);
Map<MessageId, BdfDictionary> map = clientHelper Map<MessageId, BdfDictionary> map = clientHelper
.getMessageMetadataAsDictionary(txn, localGroup.getId()); .getMessageMetadataAsDictionary(txn, localGroup.getId(), query);
for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) { for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
BdfDictionary d = m.getValue(); BdfDictionary d = m.getValue();
try { try {
ForumSharingSessionState s = fromBdfDictionary(d); ForumSharingSessionState s = fromBdfDictionary(d);
// check that this session is with the right contact
if (!c.equals(s.getContactId())) continue;
// check that this state actually concerns this forum
if (!s.getForumName().equals(f.getName()) ||
!Arrays.equals(s.getForumSalt(), f.getSalt())) {
continue;
}
// check that a forum get be left in current session // check that a forum get be left in current session
if (s instanceof SharerSessionState) { if (s instanceof SharerSessionState) {
SharerSessionState state = (SharerSessionState) s; SharerSessionState state = (SharerSessionState) s;