Added activities for managing blog and group subscriptions.

This commit is contained in:
akwizgran
2013-04-18 21:28:04 +01:00
parent 34c3776b06
commit 9e17db5db1
27 changed files with 1535 additions and 212 deletions

View File

@@ -17,6 +17,7 @@ import net.sf.briar.api.db.GroupMessageHeader;
import net.sf.briar.api.db.PrivateMessageHeader;
import net.sf.briar.api.messaging.Group;
import net.sf.briar.api.messaging.GroupId;
import net.sf.briar.api.messaging.GroupStatus;
import net.sf.briar.api.messaging.LocalGroup;
import net.sf.briar.api.messaging.Message;
import net.sf.briar.api.messaging.MessageId;
@@ -191,6 +192,14 @@ interface Database<T> {
*/
boolean containsContact(T txn, ContactId c) throws DbException;
/**
* Returns true if the database contains the given restricted group to
* which the user can post messages.
* <p>
* Locking: identity read.
*/
boolean containsLocalGroup(T txn, GroupId g) throws DbException;
/**
* Returns true if the database contains the given message.
* <p>
@@ -222,10 +231,11 @@ interface Database<T> {
throws DbException;
/**
* Returns any groups that contacts have made visible but to which the user
* does not subscribe.
* Returns the status of all groups to which the user can subscribe.
* <p>
* Locking: subscription read.
*/
Collection<Group> getAvailableGroups(T txn) throws DbException;
Collection<GroupStatus> getAvailableGroups(T txn) throws DbException;
/**
* Returns the configuration for the given transport.
@@ -621,6 +631,13 @@ interface Database<T> {
*/
void removeContact(T txn, ContactId c) throws DbException;
/**
* Removes the given restricted group to which the user can post messages.
* <p>
* Locking: identity write.
*/
void removeLocalGroup(T txn, GroupId g) throws DbException;
/**
* Removes a message (and all associated state) from the database.
* <p>
@@ -797,7 +814,7 @@ interface Database<T> {
* <p>
* Locking: subscription write.
*/
void setVisibleToAll(T txn, GroupId g, boolean visible) throws DbException;
void setVisibleToAll(T txn, GroupId g, boolean all) throws DbException;
/**
* Updates the expiry times of the given messages with respect to the given

View File

@@ -64,6 +64,7 @@ import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.messaging.Ack;
import net.sf.briar.api.messaging.Group;
import net.sf.briar.api.messaging.GroupId;
import net.sf.briar.api.messaging.GroupStatus;
import net.sf.briar.api.messaging.LocalGroup;
import net.sf.briar.api.messaging.Message;
import net.sf.briar.api.messaging.MessageId;
@@ -887,12 +888,12 @@ DatabaseCleaner.Callback {
}
}
public Collection<Group> getAvailableGroups() throws DbException {
public Collection<GroupStatus> getAvailableGroups() throws DbException {
subscriptionLock.readLock().lock();
try {
T txn = db.startTransaction();
try {
Collection<Group> groups = db.getAvailableGroups(txn);
Collection<GroupStatus> groups = db.getAvailableGroups(txn);
db.commitTransaction(txn);
return groups;
} catch(DbException e) {
@@ -2051,7 +2052,7 @@ DatabaseCleaner.Callback {
callListeners(new LocalSubscriptionsUpdatedEvent(affected));
}
public void setVisibleToAll(GroupId g, boolean visible) throws DbException {
public void setVisibleToAll(GroupId g, boolean all) throws DbException {
Collection<ContactId> affected = new ArrayList<ContactId>();
contactLock.readLock().lock();
try {
@@ -2062,8 +2063,8 @@ DatabaseCleaner.Callback {
if(!db.containsSubscription(txn, g))
throw new NoSuchSubscriptionException();
// Make the group visible or invisible to future contacts
db.setVisibleToAll(txn, g, visible);
if(visible) {
db.setVisibleToAll(txn, g, all);
if(all) {
// Make the group visible to all current contacts
Collection<ContactId> before = db.getVisibility(txn, g);
before = new HashSet<ContactId>(before);
@@ -2111,27 +2112,34 @@ DatabaseCleaner.Callback {
public void unsubscribe(Group g) throws DbException {
Collection<ContactId> affected;
messageLock.writeLock().lock();
identityLock.writeLock().lock();
try {
subscriptionLock.writeLock().lock();
messageLock.writeLock().lock();
try {
T txn = db.startTransaction();
subscriptionLock.writeLock().lock();
try {
GroupId id = g.getId();
if(!db.containsSubscription(txn, id))
throw new NoSuchSubscriptionException();
affected = db.getVisibility(txn, id);
db.removeSubscription(txn, id);
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
T txn = db.startTransaction();
try {
GroupId id = g.getId();
if(!db.containsSubscription(txn, id))
throw new NoSuchSubscriptionException();
affected = db.getVisibility(txn, id);
db.removeSubscription(txn, id);
if(db.containsLocalGroup(txn, id))
db.removeLocalGroup(txn, id);
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
subscriptionLock.writeLock().unlock();
}
} finally {
subscriptionLock.writeLock().unlock();
messageLock.writeLock().unlock();
}
} finally {
messageLock.writeLock().unlock();
identityLock.writeLock().unlock();
}
callListeners(new SubscriptionRemovedEvent(g));
callListeners(new LocalSubscriptionsUpdatedEvent(affected));

View File

@@ -75,7 +75,9 @@ class H2Database extends JdbcDatabase {
@Override
protected Connection createConnection() throws SQLException {
char[] password = encodePassword(config.getEncryptionKey());
byte[] key = config.getEncryptionKey();
if(key == null) throw new IllegalStateException();
char[] password = encodePassword(key);
Properties props = new Properties();
props.setProperty("user", "user");
props.put("password", password);

View File

@@ -19,10 +19,12 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;
import net.sf.briar.api.Author;
@@ -40,6 +42,7 @@ import net.sf.briar.api.db.GroupMessageHeader;
import net.sf.briar.api.db.PrivateMessageHeader;
import net.sf.briar.api.messaging.Group;
import net.sf.briar.api.messaging.GroupId;
import net.sf.briar.api.messaging.GroupStatus;
import net.sf.briar.api.messaging.LocalGroup;
import net.sf.briar.api.messaging.Message;
import net.sf.briar.api.messaging.MessageId;
@@ -743,8 +746,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public void addLocalGroup(Connection txn, LocalGroup g)
throws DbException {
public void addLocalGroup(Connection txn, LocalGroup g) throws DbException {
PreparedStatement ps = null;
try {
String sql = "INSERT INTO localGroups"
@@ -1053,6 +1055,27 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public boolean containsLocalGroup(Connection txn, GroupId g)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT NULL FROM localGroups WHERE groupId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getBytes());
rs = ps.executeQuery();
boolean found = rs.next();
if(rs.next()) throw new DbStateException();
rs.close();
ps.close();
return found;
} catch(SQLException e) {
tryToClose(rs);
tryToClose(ps);
throw new DbException(e);
}
}
public boolean containsMessage(Connection txn, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -1139,25 +1162,41 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public Collection<Group> getAvailableGroups(Connection txn)
public Collection<GroupStatus> 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";
// Add all subscribed groups to the list
String sql = "SELECT groupId, name, publicKey, visibleToAll"
+ " FROM groups";
ps = txn.prepareStatement(sql);
rs = ps.executeQuery();
List<Group> groups = new ArrayList<Group>();
List<GroupStatus> groups = new ArrayList<GroupStatus>();
Set<GroupId> subscribed = new HashSet<GroupId>();
while(rs.next()) {
GroupId id = new GroupId(rs.getBytes(1));
subscribed.add(id);
String name = rs.getString(2);
byte[] publicKey = rs.getBytes(3);
groups.add(new Group(id, name, publicKey));
Group group = new Group(id, name, publicKey);
boolean visibleToAll = rs.getBoolean(4);
groups.add(new GroupStatus(group, true, visibleToAll));
}
rs.close();
ps.close();
// Add all contact groups to the list, unless already added
sql = "SELECT DISTINCT groupId, name, publicKey"
+ " FROM contactGroups";
ps = txn.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()) {
GroupId id = new GroupId(rs.getBytes(1));
if(subscribed.contains(id)) continue;
String name = rs.getString(2);
byte[] publicKey = rs.getBytes(3);
Group group = new Group(id, name, publicKey);
groups.add(new GroupStatus(group, false, false));
}
rs.close();
ps.close();
@@ -2765,6 +2804,21 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public void removeLocalGroup(Connection txn, GroupId g) throws DbException {
PreparedStatement ps = null;
try {
String sql = "DELETE FROM localGroups WHERE groupId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getBytes());
int affected = ps.executeUpdate();
if(affected != 1) throw new DbStateException();
ps.close();
} catch(SQLException e) {
tryToClose(ps);
throw new DbException(e);
}
}
public void removeMessage(Connection txn, MessageId m) throws DbException {
PreparedStatement ps = null;
try {
@@ -3406,13 +3460,13 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public void setVisibleToAll(Connection txn, GroupId g, boolean visible)
public void setVisibleToAll(Connection txn, GroupId g, boolean all)
throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE groups SET visibleToAll = ? WHERE groupId = ?";
ps = txn.prepareStatement(sql);
ps.setBoolean(1, visible);
ps.setBoolean(1, all);
ps.setBytes(2, g.getBytes());
int affected = ps.executeUpdate();
if(affected > 1) throw new DbStateException();