diff --git a/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java b/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java index 67883406cc03e26aedf83ed1bf654008c4db3136..1b3e9bfd6e886539c6d127d6c2e216f9822002cb 100644 --- a/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java +++ b/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java @@ -162,6 +162,12 @@ public interface DatabaseComponent { Collection<TransportUpdate> generateTransportUpdates(ContactId c, long maxLatency) throws DbException; + /** + * Returns any groups that contacts have made visible but to which the user + * does not subscribe. + */ + Collection<Group> getAvailableGroups() throws DbException; + /** Returns the configuration for the given transport. */ TransportConfig getConfig(TransportId t) throws DbException; diff --git a/briar-core/src/net/sf/briar/db/Database.java b/briar-core/src/net/sf/briar/db/Database.java index 05dce999c77cba3b27b7ff14910ca1ee02dec1ad..f1031d7a9214628516aa8e1952473a51c212fea8 100644 --- a/briar-core/src/net/sf/briar/db/Database.java +++ b/briar-core/src/net/sf/briar/db/Database.java @@ -219,6 +219,12 @@ interface Database<T> { boolean containsVisibleSubscription(T txn, ContactId c, GroupId g) throws DbException; + /** + * Returns any groups that contacts have made visible but to which the user + * does not subscribe. + */ + Collection<Group> getAvailableGroups(T txn) throws DbException; + /** * Returns the configuration for the given transport. * <p> diff --git a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java index f830fe233b8f68b861ff6f934d5b5270f6c83c3c..45568d4d61025c374818f49791a207c7c663b74c 100644 --- a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java +++ b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java @@ -883,6 +883,23 @@ DatabaseCleaner.Callback { } } + public Collection<Group> getAvailableGroups() throws DbException { + subscriptionLock.readLock().lock(); + try { + T txn = db.startTransaction(); + try { + Collection<Group> groups = db.getAvailableGroups(txn); + db.commitTransaction(txn); + return groups; + } catch(DbException e) { + db.abortTransaction(txn); + throw e; + } + } finally { + subscriptionLock.readLock().unlock(); + } + } + public TransportConfig getConfig(TransportId t) throws DbException { transportLock.readLock().lock(); try { diff --git a/briar-core/src/net/sf/briar/db/JdbcDatabase.java b/briar-core/src/net/sf/briar/db/JdbcDatabase.java index 8e3033e88c61a3daaf5dc7799399a8a4baa27591..2aa42ee656e1d4622fcc1894563ec0971b06eb06 100644 --- a/briar-core/src/net/sf/briar/db/JdbcDatabase.java +++ b/briar-core/src/net/sf/briar/db/JdbcDatabase.java @@ -1146,6 +1146,36 @@ abstract class JdbcDatabase implements Database<Connection> { } } + public Collection<Group> getAvailableGroups(Connection txn) + throws DbException { + PreparedStatement ps = null; + ResultSet rs = null; + try { + String sql = "SELECT cg.groupId, cg.name, cg.publicKey" + + " FROM contactGroups AS cg" + + " LEFT OUTER JOIN groups AS g" + + " ON cg.groupId = g.groupId" + + " WHERE g.groupId IS NULL" + + " GROUP BY cg.groupId"; + ps = txn.prepareStatement(sql); + rs = ps.executeQuery(); + List<Group> groups = new ArrayList<Group>(); + while(rs.next()) { + GroupId id = new GroupId(rs.getBytes(1)); + String name = rs.getString(2); + byte[] publicKey = rs.getBytes(3); + groups.add(new Group(id, name, publicKey)); + } + rs.close(); + ps.close(); + return Collections.unmodifiableList(groups); + } catch(SQLException e) { + tryToClose(rs); + tryToClose(ps); + throw new DbException(e); + } + } + public TransportConfig getConfig(Connection txn, TransportId t) throws DbException { PreparedStatement ps = null; diff --git a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java index b461ad1e3a9869607a26bcbe9b0d2e9891377c3d..1fae6c77fb45575705a90d1b040c721508d10733 100644 --- a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java +++ b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java @@ -1817,6 +1817,29 @@ public class H2DatabaseTest extends BriarTestCase { db.close(); } + @Test + public void testGetAvailableGroups() throws Exception { + Database<Connection> db = open(false); + Connection txn = db.startTransaction(); + + // Add a contact who subscribes to a group + db.addLocalAuthor(txn, localAuthor); + assertEquals(contactId, db.addContact(txn, author, localAuthorId)); + db.setSubscriptions(txn, contactId, Arrays.asList(group), 1); + + // The group should be available + assertEquals(Collections.emptyList(), db.getSubscriptions(txn)); + assertEquals(Arrays.asList(group), db.getAvailableGroups(txn)); + + // Subscribe to the group - it should no longer be available + db.addSubscription(txn, group); + assertEquals(Arrays.asList(group), db.getSubscriptions(txn)); + assertEquals(Collections.emptyList(), db.getAvailableGroups(txn)); + + db.commitTransaction(txn); + db.close(); + } + @Test public void testExceptionHandling() throws Exception { Database<Connection> db = open(false);