From 0fce224d88472778b96eac7092ecd9d2c4a7ef29 Mon Sep 17 00:00:00 2001
From: akwizgran <michael@briarproject.org>
Date: Fri, 24 Aug 2018 16:18:38 +0100
Subject: [PATCH] Add method for getting cooked message from DB.

---
 .../bramble/api/db/DatabaseComponent.java     |  9 +++++++
 .../org/briarproject/bramble/db/Database.java |  9 +++++++
 .../bramble/db/DatabaseComponentImpl.java     |  9 +++++++
 .../briarproject/bramble/db/JdbcDatabase.java | 26 +++++++++++++++++++
 .../bramble/db/DatabaseComponentImplTest.java | 16 +++++++++---
 .../bramble/db/JdbcDatabaseTest.java          | 15 +++++++++++
 6 files changed, 81 insertions(+), 3 deletions(-)

diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
index 6de023cba1..e86153d78d 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
@@ -263,6 +263,15 @@ public interface DatabaseComponent {
 	 */
 	Collection<LocalAuthor> getLocalAuthors(Transaction txn) throws DbException;
 
+	/**
+	 * Returns the message with the given ID.
+	 * <p/>
+	 * Read-only.
+	 *
+	 * @throws MessageDeletedException if the message has been deleted
+	 */
+	Message getMessage(Transaction txn, MessageId m) throws DbException;
+
 	/**
 	 * Returns the IDs of all delivered messages in the given group.
 	 * <p/>
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
index 93a573f85e..1ad2525841 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
@@ -298,6 +298,15 @@ interface Database<T> {
 	 */
 	Collection<LocalAuthor> getLocalAuthors(T txn) throws DbException;
 
+	/**
+	 * Returns the message with the given ID.
+	 * <p/>
+	 * Read-only.
+	 *
+	 * @throws MessageDeletedException if the message has been deleted
+	 */
+	Message getMessage(T txn, MessageId m) throws DbException;
+
 	/**
 	 * Returns the IDs and states of all dependencies of the given message.
 	 * For missing dependencies and dependencies in other groups, the state
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
index 38e31f58cd..4023c4c969 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
@@ -457,6 +457,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		return db.getLocalAuthors(txn);
 	}
 
+	@Override
+	public Message getMessage(Transaction transaction, MessageId m)
+			throws DbException {
+		T txn = unbox(transaction);
+		if (!db.containsMessage(txn, m))
+			throw new NoSuchMessageException();
+		return db.getMessage(txn, m);
+	}
+
 	@Override
 	public Collection<MessageId> getMessageIds(Transaction transaction,
 			GroupId g) throws DbException {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
index b88b24e412..36087b2ffd 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
@@ -1483,6 +1483,32 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
+	@Override
+	public Message getMessage(Connection txn, MessageId m) throws DbException {
+		PreparedStatement ps = null;
+		ResultSet rs = null;
+		try {
+			String sql = "SELECT groupId, timestamp, raw FROM messages"
+					+ " WHERE messageId = ?";
+			ps = txn.prepareStatement(sql);
+			ps.setBytes(1, m.getBytes());
+			rs = ps.executeQuery();
+			if (!rs.next()) throw new DbStateException();
+			GroupId g = new GroupId(rs.getBytes(1));
+			long timestamp = rs.getLong(2);
+			byte[] raw = rs.getBytes(3);
+			if (rs.next()) throw new DbStateException();
+			rs.close();
+			ps.close();
+			if (raw == null) throw new MessageDeletedException();
+			return new Message(m, g, timestamp, raw);
+		} catch (SQLException e) {
+			tryToClose(rs);
+			tryToClose(ps);
+			throw new DbException(e);
+		}
+	}
+
 	@Override
 	public Collection<MessageId> getMessageIds(Connection txn, GroupId g)
 			throws DbException {
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
index 3eec4d9793..743e963213 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
@@ -613,11 +613,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
 			throws Exception {
 		context.checking(new Expectations() {{
 			// Check whether the message is in the DB (which it's not)
-			exactly(11).of(database).startTransaction();
+			exactly(12).of(database).startTransaction();
 			will(returnValue(txn));
-			exactly(11).of(database).containsMessage(txn, messageId);
+			exactly(12).of(database).containsMessage(txn, messageId);
 			will(returnValue(false));
-			exactly(11).of(database).abortTransaction(txn);
+			exactly(12).of(database).abortTransaction(txn);
 			// This is needed for getMessageStatus() to proceed
 			exactly(1).of(database).containsContact(txn, contactId);
 			will(returnValue(true));
@@ -645,6 +645,16 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
 			db.endTransaction(transaction);
 		}
 
+		transaction = db.startTransaction(false);
+		try {
+			db.getMessage(transaction, messageId);
+			fail();
+		} catch (NoSuchMessageException expected) {
+			// Expected
+		} finally {
+			db.endTransaction(transaction);
+		}
+
 		transaction = db.startTransaction(false);
 		try {
 			db.getRawMessage(transaction, messageId);
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java
index f6d091dd61..57825b3eeb 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java
@@ -1638,6 +1638,13 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
 		ids = db.getMessagesToOffer(txn, contactId, 100);
 		assertEquals(singletonList(messageId), ids);
 
+		// The message should be available
+		Message m = db.getMessage(txn, messageId);
+		assertEquals(messageId, m.getId());
+		assertEquals(groupId, m.getGroupId());
+		assertEquals(message.getTimestamp(), m.getTimestamp());
+		assertArrayEquals(message.getRaw(), m.getRaw());
+
 		// The raw message should be available
 		assertArrayEquals(message.getRaw(), db.getRawMessage(txn, messageId));
 
@@ -1653,6 +1660,14 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
 		ids = db.getMessagesToOffer(txn, contactId, 100);
 		assertTrue(ids.isEmpty());
 
+		// Requesting the message should throw an exception
+		try {
+			db.getMessage(txn, messageId);
+			fail();
+		} catch (MessageDeletedException expected) {
+			// Expected
+		}
+
 		// Requesting the raw message should throw an exception
 		try {
 			db.getRawMessage(txn, messageId);
-- 
GitLab