diff --git a/briar-api/src/org/briarproject/api/db/MessageHeader.java b/briar-api/src/org/briarproject/api/db/MessageHeader.java index 4a1b2054b348290dad7343714001d6fb33bcc3bc..6fa1e223f979091b3fdb1e384e82444e40b6facc 100644 --- a/briar-api/src/org/briarproject/api/db/MessageHeader.java +++ b/briar-api/src/org/briarproject/api/db/MessageHeader.java @@ -12,11 +12,11 @@ public class MessageHeader { private final Author.Status authorStatus; private final String contentType; private final long timestamp; - private final boolean read; + private final boolean local, read; public MessageHeader(MessageId id, MessageId parent, GroupId groupId, Author author, Author.Status authorStatus, String contentType, - long timestamp, boolean read) { + long timestamp, boolean local, boolean read) { this.id = id; this.parent = parent; this.groupId = groupId; @@ -24,6 +24,7 @@ public class MessageHeader { this.authorStatus = authorStatus; this.contentType = contentType; this.timestamp = timestamp; + this.local = local; this.read = read; } @@ -69,6 +70,11 @@ public class MessageHeader { return timestamp; } + /** Returns true if the message was locally generated. */ + public boolean isLocal() { + return local; + } + /** Returns true if the message has been read. */ public boolean isRead() { return read; diff --git a/briar-core/src/org/briarproject/db/Database.java b/briar-core/src/org/briarproject/db/Database.java index 255a5af2ebeee5a4a8a95234ed57c44acfdfd6de..130c4f1c3f09ecc4f3da410b448b599f384cd646 100644 --- a/briar-core/src/org/briarproject/db/Database.java +++ b/briar-core/src/org/briarproject/db/Database.java @@ -124,7 +124,7 @@ interface Database<T> { * <p> * Locking: message write. */ - void addMessage(T txn, Message m, boolean incoming) throws DbException; + void addMessage(T txn, Message m, boolean local) throws DbException; /** * Records that a message has been offered by the given contact. diff --git a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java index 106e8cab018b516fd7106ab32ae9ae11ee89476c..2ae0579b0147ca065ee7de748b98f33c03f53487 100644 --- a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java +++ b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java @@ -383,8 +383,12 @@ DatabaseCleaner.Callback { */ private void addMessage(T txn, Message m, ContactId sender) throws DbException { - db.addMessage(txn, m, sender != null); - if(sender == null) db.setReadFlag(txn, m.getId(), true); + if(sender == null) { + db.addMessage(txn, m, true); + db.setReadFlag(txn, m.getId(), true); + } else { + db.addMessage(txn, m, false); + } Group g = m.getGroup(); Collection<ContactId> visibility = db.getVisibility(txn, g.getId()); visibility = new HashSet<ContactId>(visibility); diff --git a/briar-core/src/org/briarproject/db/JdbcDatabase.java b/briar-core/src/org/briarproject/db/JdbcDatabase.java index a2dd5ac86db2aa541d7bafe21e2cd6d10d744ada..9c660107971540f371306ec42f105a0c7ff3884a 100644 --- a/briar-core/src/org/briarproject/db/JdbcDatabase.java +++ b/briar-core/src/org/briarproject/db/JdbcDatabase.java @@ -60,8 +60,8 @@ import org.briarproject.api.transport.TemporarySecret; */ abstract class JdbcDatabase implements Database<Connection> { - private static final int SCHEMA_VERSION = 3; - private static final int MIN_SCHEMA_VERSION = 3; + private static final int SCHEMA_VERSION = 4; + private static final int MIN_SCHEMA_VERSION = 4; private static final String CREATE_SETTINGS = "CREATE TABLE settings" @@ -160,7 +160,7 @@ abstract class JdbcDatabase implements Database<Connection> { + " bodyStart INT NOT NULL," + " bodyLength INT NOT NULL," + " raw BLOB NOT NULL," - + " incoming BOOLEAN NOT NULL," + + " local BOOLEAN NOT NULL," + " read BOOLEAN NOT NULL," + " PRIMARY KEY (messageId)," + " FOREIGN KEY (groupId)" @@ -805,14 +805,14 @@ abstract class JdbcDatabase implements Database<Connection> { } } - public void addMessage(Connection txn, Message m, boolean incoming) + public void addMessage(Connection txn, Message m, boolean local) throws DbException { PreparedStatement ps = null; try { String sql = "INSERT INTO messages (messageId, parentId, groupId," + " authorId, authorName, authorKey, contentType," + " timestamp, length, bodyStart, bodyLength, raw," - + " incoming, read)" + + " local, read)" + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, FALSE)"; ps = txn.prepareStatement(sql); ps.setBytes(1, m.getId().getBytes()); @@ -836,7 +836,7 @@ abstract class JdbcDatabase implements Database<Connection> { ps.setInt(10, m.getBodyStart()); ps.setInt(11, m.getBodyLength()); ps.setBytes(12, raw); - ps.setBoolean(13, incoming); + ps.setBoolean(13, local); int affected = ps.executeUpdate(); if(affected != 1) throw new DbStateException(); ps.close(); @@ -1517,7 +1517,7 @@ abstract class JdbcDatabase implements Database<Connection> { if(rs.next()) throw new DbException(); // Get the message headers sql = "SELECT messageId, parentId, m.groupId, contentType," - + " timestamp, incoming, read" + + " timestamp, local, read" + " FROM messages AS m" + " JOIN groups AS g" + " ON m.groupId = g.groupId" @@ -1536,16 +1536,16 @@ abstract class JdbcDatabase implements Database<Connection> { GroupId groupId = new GroupId(rs.getBytes(3)); String contentType = rs.getString(4); long timestamp = rs.getLong(5); - boolean incoming = rs.getBoolean(6); + boolean local = rs.getBoolean(6); boolean read = rs.getBoolean(7); - if(incoming) { + if(local) { headers.add(new MessageHeader(id, parent, groupId, - remoteAuthor, VERIFIED, contentType, timestamp, - read)); + localAuthor, VERIFIED, contentType, timestamp, + true, read)); } else { headers.add(new MessageHeader(id, parent, groupId, - localAuthor, VERIFIED, contentType, timestamp, - read)); + remoteAuthor, VERIFIED, contentType, timestamp, + false, read)); } } rs.close(); @@ -1719,7 +1719,7 @@ abstract class JdbcDatabase implements Database<Connection> { ResultSet rs = null; try { String sql = "SELECT messageId, parentId, m.authorId, authorName," - + " authorKey, contentType, timestamp, read," + + " authorKey, contentType, timestamp, local, read," + " la.authorId IS NOT NULL, c.authorId IS NOT NULL" + " FROM messages AS m" + " LEFT OUTER JOIN localAuthors AS la" @@ -1747,15 +1747,16 @@ abstract class JdbcDatabase implements Database<Connection> { } String contentType = rs.getString(6); long timestamp = rs.getLong(7); - boolean read = rs.getBoolean(8); - boolean isSelf = rs.getBoolean(9); - boolean isContact = rs.getBoolean(10); + boolean local = rs.getBoolean(8); + boolean read = rs.getBoolean(9); + boolean isSelf = rs.getBoolean(10); + boolean isContact = rs.getBoolean(11); Author.Status authorStatus; if(author == null) authorStatus = ANONYMOUS; else if(isSelf || isContact) authorStatus = VERIFIED; else authorStatus = UNKNOWN; headers.add(new MessageHeader(id, parent, g, author, - authorStatus, contentType, timestamp, read)); + authorStatus, contentType, timestamp, local, read)); } rs.close(); ps.close(); diff --git a/briar-tests/src/org/briarproject/db/DatabaseComponentTest.java b/briar-tests/src/org/briarproject/db/DatabaseComponentTest.java index 65431b633b6ef4176dfa3ec756c703478408034c..44bca26f2f4b276519eac41fd09eecad2946054f 100644 --- a/briar-tests/src/org/briarproject/db/DatabaseComponentTest.java +++ b/briar-tests/src/org/briarproject/db/DatabaseComponentTest.java @@ -286,7 +286,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase { will(returnValue(false)); oneOf(database).containsGroup(txn, groupId); will(returnValue(true)); - oneOf(database).addMessage(txn, message, false); + oneOf(database).addMessage(txn, message, true); oneOf(database).setReadFlag(txn, messageId, true); oneOf(database).getVisibility(txn, groupId); will(returnValue(Arrays.asList(contactId))); @@ -1000,7 +1000,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase { will(returnValue(false)); oneOf(database).containsVisibleGroup(txn, contactId, groupId); will(returnValue(true)); - oneOf(database).addMessage(txn, message, true); + oneOf(database).addMessage(txn, message, false); oneOf(database).getVisibility(txn, groupId); will(returnValue(Arrays.asList(contactId))); oneOf(database).getContactIds(txn); diff --git a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java index 37a4c944f2d572ffb16dde52ef5fb2a1722d6928..103d12e252665d0bf9984ed96198280f555cc2ed 100644 --- a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java +++ b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java @@ -145,7 +145,7 @@ public class H2DatabaseTest extends BriarTestCase { // Subscribe to a group and store a message db.addGroup(txn, group); - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); // Unsubscribing from the group should remove the message assertTrue(db.containsMessage(txn, messageId)); @@ -167,7 +167,7 @@ public class H2DatabaseTest extends BriarTestCase { db.addGroup(txn, group); db.addVisibility(txn, contactId, groupId); db.setGroups(txn, contactId, Arrays.asList(group), 1); - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); // The message has no status yet, so it should not be sendable Collection<MessageId> ids = db.getMessagesToSend(txn, contactId, @@ -202,7 +202,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, author, localAuthorId)); db.addGroup(txn, group); db.addVisibility(txn, contactId, groupId); - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); db.addStatus(txn, contactId, messageId, false, false); // The contact is not subscribed, so the message should not be sendable @@ -239,7 +239,7 @@ public class H2DatabaseTest extends BriarTestCase { db.addGroup(txn, group); db.addVisibility(txn, contactId, groupId); db.setGroups(txn, contactId, Arrays.asList(group), 1); - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); db.addStatus(txn, contactId, messageId, false, false); // The message is sendable, but too large to send @@ -269,7 +269,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, author, localAuthorId)); db.addGroup(txn, group); db.setGroups(txn, contactId, Arrays.asList(group), 1); - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); db.addStatus(txn, contactId, messageId, false, false); // The subscription is not visible to the contact, so the message @@ -306,10 +306,10 @@ public class H2DatabaseTest extends BriarTestCase { MessageId messageId1 = new MessageId(TestUtils.getRandomId()); Message message1 = new TestMessage(messageId1, null, group, author, contentType, subject, timestamp, raw); - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); db.addStatus(txn, contactId, messageId, false, true); db.raiseAckFlag(txn, contactId, messageId); - db.addMessage(txn, message1, false); + db.addMessage(txn, message1, true); db.addStatus(txn, contactId, messageId1, false, true); db.raiseAckFlag(txn, contactId, messageId1); @@ -340,7 +340,7 @@ public class H2DatabaseTest extends BriarTestCase { db.setGroups(txn, contactId, Arrays.asList(group), 1); // Receive the same message twice - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); db.addStatus(txn, contactId, messageId, false, true); db.raiseAckFlag(txn, contactId, messageId); db.raiseAckFlag(txn, contactId, messageId); @@ -371,7 +371,7 @@ public class H2DatabaseTest extends BriarTestCase { db.addGroup(txn, group); db.addVisibility(txn, contactId, groupId); db.setGroups(txn, contactId, Arrays.asList(group), 1); - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); db.addStatus(txn, contactId, messageId, false, false); // Retrieve the message from the database and mark it as sent @@ -407,8 +407,8 @@ public class H2DatabaseTest extends BriarTestCase { // Subscribe to a group and store two messages db.addGroup(txn, group); - db.addMessage(txn, message, false); - db.addMessage(txn, message1, false); + db.addMessage(txn, message, true); + db.addMessage(txn, message1, true); // Allowing enough capacity for one message should return the older one Iterator<MessageId> it = db.getOldMessages(txn, size).iterator(); @@ -446,7 +446,7 @@ public class H2DatabaseTest extends BriarTestCase { // Storing a message should reduce the free space Connection txn = db.startTransaction(); db.addGroup(txn, group); - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); db.commitTransaction(txn); assertTrue(db.getFreeSpace() < free); @@ -705,7 +705,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, author, localAuthorId)); db.addGroup(txn, group); db.setGroups(txn, contactId, Arrays.asList(group), 1); - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); db.addStatus(txn, contactId, messageId, false, false); // The subscription is not visible @@ -752,7 +752,7 @@ public class H2DatabaseTest extends BriarTestCase { MessageId childId = new MessageId(TestUtils.getRandomId()); Message child = new TestMessage(childId, null, group, null, contentType, subject, timestamp, raw); - db.addMessage(txn, child, false); + db.addMessage(txn, child, true); assertTrue(db.containsMessage(txn, childId)); assertNull(db.getParent(txn, childId)); @@ -773,7 +773,7 @@ public class H2DatabaseTest extends BriarTestCase { MessageId parentId = new MessageId(TestUtils.getRandomId()); Message child = new TestMessage(childId, parentId, group, null, contentType, subject, timestamp, raw); - db.addMessage(txn, child, false); + db.addMessage(txn, child, true); assertTrue(db.containsMessage(txn, childId)); assertFalse(db.containsMessage(txn, parentId)); assertNull(db.getParent(txn, childId)); @@ -801,8 +801,8 @@ public class H2DatabaseTest extends BriarTestCase { contentType, subject, timestamp, raw); Message parent = new TestMessage(parentId, null, group1, null, contentType, subject, timestamp, raw); - db.addMessage(txn, child, false); - db.addMessage(txn, parent, false); + db.addMessage(txn, child, true); + db.addMessage(txn, parent, true); assertTrue(db.containsMessage(txn, childId)); assertTrue(db.containsMessage(txn, parentId)); assertNull(db.getParent(txn, childId)); @@ -826,8 +826,8 @@ public class H2DatabaseTest extends BriarTestCase { contentType, subject, timestamp, raw); Message parent = new TestMessage(parentId, null, group, null, contentType, subject, timestamp, raw); - db.addMessage(txn, child, false); - db.addMessage(txn, parent, false); + db.addMessage(txn, child, true); + db.addMessage(txn, parent, true); assertTrue(db.containsMessage(txn, childId)); assertTrue(db.containsMessage(txn, parentId)); assertEquals(parentId, db.getParent(txn, childId)); @@ -853,8 +853,8 @@ public class H2DatabaseTest extends BriarTestCase { MessageId messageId1 = new MessageId(TestUtils.getRandomId()); Message message1 = new TestMessage(messageId1, null, group, null, contentType, subject, timestamp, raw, 10, bodyLength); - db.addMessage(txn, message, false); - db.addMessage(txn, message1, false); + db.addMessage(txn, message, true); + db.addMessage(txn, message1, true); // Calculate the expected message bodies byte[] expectedBody = new byte[bodyLength]; @@ -887,13 +887,13 @@ public class H2DatabaseTest extends BriarTestCase { db.addGroup(txn, group); // Store a couple of messages - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId parentId = new MessageId(TestUtils.getRandomId()); long timestamp1 = System.currentTimeMillis(); Message message1 = new TestMessage(messageId1, parentId, group, author, contentType, subject, timestamp1, raw); - db.addMessage(txn, message1, false); + db.addMessage(txn, message1, true); // Mark one of the messages read db.setReadFlag(txn, messageId, true); @@ -944,7 +944,7 @@ public class H2DatabaseTest extends BriarTestCase { db.addGroup(txn, group); // Store a message from the contact - status VERIFIED - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); AuthorId authorId1 = new AuthorId(TestUtils.getRandomId()); // Store a message from an unknown author - status UNKNOWN Author author1 = new Author(authorId1, "Bob", @@ -952,12 +952,12 @@ public class H2DatabaseTest extends BriarTestCase { MessageId messageId1 = new MessageId(TestUtils.getRandomId()); Message message1 = new TestMessage(messageId1, null, group, author1, contentType, subject, timestamp, raw); - db.addMessage(txn, message1, false); + db.addMessage(txn, message1, true); // Store an anonymous message - status ANONYMOUS MessageId messageId2 = new MessageId(TestUtils.getRandomId()); Message message2 = new TestMessage(messageId2, null, group, null, contentType, subject, timestamp, raw); - db.addMessage(txn, message2, false); + db.addMessage(txn, message2, true); // Retrieve the message headers (order is undefined) Collection<MessageHeader> headers = db.getMessageHeaders(txn, groupId); @@ -996,7 +996,7 @@ public class H2DatabaseTest extends BriarTestCase { // Subscribe to a group and store a message db.addGroup(txn, group); - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); // The message should be unread by default assertFalse(db.getReadFlag(txn, messageId)); @@ -1026,17 +1026,17 @@ public class H2DatabaseTest extends BriarTestCase { db.addGroup(txn, group1); // Store two messages in the first group - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); MessageId messageId1 = new MessageId(TestUtils.getRandomId()); Message message1 = new TestMessage(messageId1, null, group, author, contentType, subject, timestamp, raw); - db.addMessage(txn, message1, false); + db.addMessage(txn, message1, true); // Store one message in the second group MessageId messageId2 = new MessageId(TestUtils.getRandomId()); Message message2 = new TestMessage(messageId2, null, group1, author, contentType, subject, timestamp, raw); - db.addMessage(txn, message2, false); + db.addMessage(txn, message2, true); // Mark one of the messages in the first group read db.setReadFlag(txn, messageId, true); @@ -1531,7 +1531,7 @@ public class H2DatabaseTest extends BriarTestCase { db.getInboxMessageHeaders(txn, contactId)); // Add a message to the inbox group - the header should be returned - db.addMessage(txn, message, false); + db.addMessage(txn, message, true); Collection<MessageHeader> headers = db.getInboxMessageHeaders(txn, contactId); assertEquals(1, headers.size());