diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java
index 16761d28d..9aa8889f1 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java
@@ -87,6 +87,12 @@ public interface ContactManager {
PendingContact addPendingContact(String link, String alias)
throws DbException, FormatException;
+ /**
+ * Returns the pending contact with the given ID.
+ */
+ PendingContact getPendingContact(Transaction txn, PendingContactId p)
+ throws DbException;
+
/**
* Returns a list of {@link PendingContact PendingContacts} and their
* {@link PendingContactState states}.
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 2112beb2b..a953d7095 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
@@ -411,6 +411,14 @@ public interface DatabaseComponent extends TransactionManager {
*/
long getNextSendTime(Transaction txn, ContactId c) throws DbException;
+ /**
+ * Returns the pending contact with the given ID.
+ *
+ * Read-only.
+ */
+ PendingContact getPendingContact(Transaction txn, PendingContactId p)
+ throws DbException;
+
/**
* Returns all pending contacts.
*
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java
index 24c09cef2..7bea2930e 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java
@@ -127,6 +127,12 @@ class ContactManagerImpl implements ContactManager {
return p;
}
+ @Override
+ public PendingContact getPendingContact(Transaction txn, PendingContactId p)
+ throws DbException {
+ return db.getPendingContact(txn, p);
+ }
+
@Override
public Collection> getPendingContacts()
throws DbException {
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 4a61a9360..47ef5e0b3 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
@@ -496,6 +496,14 @@ interface Database {
*/
long getNextSendTime(T txn, ContactId c) throws DbException;
+ /**
+ * Returns the pending contact with the given ID.
+ *
+ * Read-only.
+ */
+ PendingContact getPendingContact(T txn, PendingContactId p)
+ throws DbException;
+
/**
* Returns all pending contacts.
*
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 2d90894f3..876d419b2 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
@@ -712,6 +712,15 @@ class DatabaseComponentImpl implements DatabaseComponent {
return db.getNextSendTime(txn, c);
}
+ @Override
+ public PendingContact getPendingContact(Transaction transaction,
+ PendingContactId p) throws DbException {
+ T txn = unbox(transaction);
+ if (!db.containsPendingContact(txn, p))
+ throw new NoSuchPendingContactException();
+ return db.getPendingContact(txn, p);
+ }
+
@Override
public Collection getPendingContacts(
Transaction transaction) 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 536eaf4e8..f3d80a8e5 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
@@ -2205,6 +2205,30 @@ abstract class JdbcDatabase implements Database {
}
}
+ @Override
+ public PendingContact getPendingContact(Connection txn, PendingContactId p)
+ throws DbException {
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+ try {
+ String sql = "SELECT publicKey, alias, timestamp"
+ + " FROM pendingContacts"
+ + " WHERE pendingContactId = ?";
+ ps = txn.prepareStatement(sql);
+ ps.setBytes(1, p.getBytes());
+ rs = ps.executeQuery();
+ if (!rs.next()) throw new DbStateException();
+ PublicKey publicKey = new AgreementPublicKey(rs.getBytes(1));
+ String alias = rs.getString(2);
+ long timestamp = rs.getLong(3);
+ return new PendingContact(p, publicKey, alias, timestamp);
+ } catch (SQLException e) {
+ tryToClose(rs, LOG, WARNING);
+ tryToClose(ps, LOG, WARNING);
+ throw new DbException(e);
+ }
+ }
+
@Override
public Collection getPendingContacts(Connection txn)
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 ab634d036..9afc37b18 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
@@ -763,12 +763,12 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
throws Exception {
context.checking(new Expectations() {{
// Check whether the pending contact is in the DB (which it's not)
- exactly(3).of(database).startTransaction();
+ exactly(4).of(database).startTransaction();
will(returnValue(txn));
- exactly(3).of(database).containsPendingContact(txn,
+ exactly(4).of(database).containsPendingContact(txn,
pendingContactId);
will(returnValue(false));
- exactly(3).of(database).abortTransaction(txn);
+ exactly(4).of(database).abortTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, eventBus,
eventExecutor, shutdownManager);
@@ -791,6 +791,14 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
// Expected
}
+ try {
+ db.transaction(false, transaction ->
+ db.getPendingContact(transaction, pendingContactId));
+ fail();
+ } catch (NoSuchPendingContactException expected) {
+ // Expected
+ }
+
try {
db.transaction(false, transaction ->
db.removePendingContact(transaction, pendingContactId));
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 4bb66f114..bdbe53240 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
@@ -2204,14 +2204,14 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(emptyList(), db.getPendingContacts(txn));
db.addPendingContact(txn, pendingContact);
+ PendingContact retrieved =
+ db.getPendingContact(txn, pendingContact.getId());
+ assertPendingContactEquals(pendingContact, retrieved);
+
Collection pendingContacts = db.getPendingContacts(txn);
assertEquals(1, pendingContacts.size());
- PendingContact retrieved = pendingContacts.iterator().next();
- assertEquals(pendingContact.getId(), retrieved.getId());
- assertEquals(pendingContact.getAlias(), retrieved.getAlias());
- assertArrayEquals(pendingContact.getPublicKey().getEncoded(),
- retrieved.getPublicKey().getEncoded());
- assertEquals(pendingContact.getTimestamp(), retrieved.getTimestamp());
+ retrieved = pendingContacts.iterator().next();
+ assertPendingContactEquals(pendingContact, retrieved);
db.removePendingContact(txn, pendingContact.getId());
assertEquals(emptyList(), db.getPendingContacts(txn));
@@ -2220,6 +2220,15 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.close();
}
+ private void assertPendingContactEquals(PendingContact expected,
+ PendingContact actual) {
+ assertEquals(expected.getId(), actual.getId());
+ assertArrayEquals(expected.getPublicKey().getEncoded(),
+ actual.getPublicKey().getEncoded());
+ assertEquals(expected.getAlias(), actual.getAlias());
+ assertEquals(expected.getTimestamp(), actual.getTimestamp());
+ }
+
@Test
public void testTransferKeys() throws Exception {
boolean alice = random.nextBoolean();