diff --git a/api/net/sf/briar/api/protocol/MessageHeaderFactory.java b/api/net/sf/briar/api/protocol/MessageHeaderFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..a9f51a46c559a428cee24a639112703b5b321e49 --- /dev/null +++ b/api/net/sf/briar/api/protocol/MessageHeaderFactory.java @@ -0,0 +1,7 @@ +package net.sf.briar.api.protocol; + +public interface MessageHeaderFactory { + + MessageHeader createMessageHeader(MessageId id, MessageId parent, + GroupId group, AuthorId author, String subject, long timestamp); +} diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java index 9a7eaf6beafec274381dfdfeade182f1fc31a91e..796c163c619b5ca531d140e0dffb983c849d221d 100644 --- a/components/net/sf/briar/db/Database.java +++ b/components/net/sf/briar/db/Database.java @@ -16,6 +16,7 @@ import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.Group; import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.Message; +import net.sf.briar.api.protocol.MessageHeader; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.transport.ConnectionWindow; @@ -252,6 +253,14 @@ interface Database<T> { */ byte[] getMessageBody(T txn, MessageId m) throws DbException; + /** + * Returns the headers of all messages in the given group. + * <p> + * Locking: messages read. + */ + Collection<MessageHeader> getMessageHeaders(T txn, GroupId g) + throws DbException; + /** * Returns the message identified by the given ID, in raw format, or null * if the message is not present in the database or is not sendable to the diff --git a/components/net/sf/briar/db/DatabaseModule.java b/components/net/sf/briar/db/DatabaseModule.java index 903fb43458772d61ca785b05757753a4412554a0..d6ec12810da252d6ebe2d0291b9cd55fc02619fc 100644 --- a/components/net/sf/briar/db/DatabaseModule.java +++ b/components/net/sf/briar/db/DatabaseModule.java @@ -9,6 +9,7 @@ import net.sf.briar.api.db.DatabaseDirectory; import net.sf.briar.api.db.DatabaseMaxSize; import net.sf.briar.api.db.DatabasePassword; import net.sf.briar.api.protocol.GroupFactory; +import net.sf.briar.api.protocol.MessageHeaderFactory; import net.sf.briar.api.transport.ConnectionWindowFactory; import com.google.inject.AbstractModule; @@ -26,9 +27,10 @@ public class DatabaseModule extends AbstractModule { Database<Connection> getDatabase(@DatabaseDirectory File dir, @DatabasePassword Password password, @DatabaseMaxSize long maxSize, ConnectionWindowFactory connectionWindowFactory, - GroupFactory groupFactory) { + GroupFactory groupFactory, + MessageHeaderFactory messageHeaderFactory) { return new H2Database(dir, password, maxSize, connectionWindowFactory, - groupFactory); + groupFactory, messageHeaderFactory); } @Provides @Singleton diff --git a/components/net/sf/briar/db/H2Database.java b/components/net/sf/briar/db/H2Database.java index 18aff631c6e31920983fce34d1f7f7973d3eae07..4b116ee32364a9f8280d599418ec65b0e1b3a766 100644 --- a/components/net/sf/briar/db/H2Database.java +++ b/components/net/sf/briar/db/H2Database.java @@ -16,6 +16,7 @@ import net.sf.briar.api.db.DatabaseMaxSize; import net.sf.briar.api.db.DatabasePassword; import net.sf.briar.api.db.DbException; import net.sf.briar.api.protocol.GroupFactory; +import net.sf.briar.api.protocol.MessageHeaderFactory; import net.sf.briar.api.transport.ConnectionWindowFactory; import org.apache.commons.io.FileSystemUtils; @@ -37,9 +38,10 @@ class H2Database extends JdbcDatabase { H2Database(@DatabaseDirectory File dir, @DatabasePassword Password password, @DatabaseMaxSize long maxSize, ConnectionWindowFactory connectionWindowFactory, - GroupFactory groupFactory) { - super(connectionWindowFactory, groupFactory, "BINARY(32)", "BINARY", - "INT NOT NULL AUTO_INCREMENT"); + GroupFactory groupFactory, + MessageHeaderFactory messageHeaderFactory) { + super(connectionWindowFactory, groupFactory, messageHeaderFactory, + "BINARY(32)", "BINARY", "INT NOT NULL AUTO_INCREMENT"); home = new File(dir, "db"); this.password = password; url = "jdbc:h2:split:" + home.getPath() diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java index 64c3ba450bc92a8d6ca1c0083a1b7a2e49c38c1e..07b244a77cc745d7c32ea4acab57696643e278c0 100644 --- a/components/net/sf/briar/db/JdbcDatabase.java +++ b/components/net/sf/briar/db/JdbcDatabase.java @@ -30,6 +30,8 @@ import net.sf.briar.api.protocol.Group; import net.sf.briar.api.protocol.GroupFactory; import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.Message; +import net.sf.briar.api.protocol.MessageHeader; +import net.sf.briar.api.protocol.MessageHeaderFactory; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.transport.ConnectionWindow; import net.sf.briar.api.transport.ConnectionWindowFactory; @@ -230,6 +232,7 @@ abstract class JdbcDatabase implements Database<Connection> { private final String hashType, binaryType, counterType; private final ConnectionWindowFactory connectionWindowFactory; private final GroupFactory groupFactory; + private final MessageHeaderFactory messageHeaderFactory; private final LinkedList<Connection> connections = new LinkedList<Connection>(); // Locking: self @@ -239,10 +242,12 @@ abstract class JdbcDatabase implements Database<Connection> { protected abstract Connection createConnection() throws SQLException; JdbcDatabase(ConnectionWindowFactory connectionWindowFactory, - GroupFactory groupFactory, String hashType, String binaryType, - String counterType) { + GroupFactory groupFactory, + MessageHeaderFactory messageHeaderFactory, + String hashType, String binaryType, String counterType) { this.connectionWindowFactory = connectionWindowFactory; this.groupFactory = groupFactory; + this.messageHeaderFactory = messageHeaderFactory; this.hashType = hashType; this.binaryType = binaryType; this.counterType = counterType; @@ -1094,6 +1099,37 @@ abstract class JdbcDatabase implements Database<Connection> { } } + public Collection<MessageHeader> getMessageHeaders(Connection txn, + GroupId g) throws DbException { + PreparedStatement ps = null; + ResultSet rs = null; + try { + String sql = "SELECT messageId, parentId, authorId, subject," + + " timestamp FROM messages" + + " WHERE groupId = ?"; + ps = txn.prepareStatement(sql); + ps.setBytes(1, g.getBytes()); + rs = ps.executeQuery(); + Collection<MessageHeader> headers = new ArrayList<MessageHeader>(); + while(rs.next()) { + MessageId id = new MessageId(rs.getBytes(1)); + MessageId parent = new MessageId(rs.getBytes(2)); + AuthorId author = new AuthorId(rs.getBytes(3)); + String subject = rs.getString(4); + long timestamp = rs.getLong(5); + headers.add(messageHeaderFactory.createMessageHeader(id, parent, + g, author, subject, timestamp)); + } + rs.close(); + ps.close(); + return headers; + } catch(SQLException e) { + tryToClose(rs); + tryToClose(ps); + throw new DbException(e); + } + } + public byte[] getMessageIfSendable(Connection txn, ContactId c, MessageId m) throws DbException { PreparedStatement ps = null; diff --git a/components/net/sf/briar/protocol/MessageHeaderFactoryImpl.java b/components/net/sf/briar/protocol/MessageHeaderFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..dbe2abadf15268ce7cd1c6571cf7b36d4282528f --- /dev/null +++ b/components/net/sf/briar/protocol/MessageHeaderFactoryImpl.java @@ -0,0 +1,16 @@ +package net.sf.briar.protocol; + +import net.sf.briar.api.protocol.AuthorId; +import net.sf.briar.api.protocol.GroupId; +import net.sf.briar.api.protocol.MessageHeader; +import net.sf.briar.api.protocol.MessageHeaderFactory; +import net.sf.briar.api.protocol.MessageId; + +class MessageHeaderFactoryImpl implements MessageHeaderFactory { + + public MessageHeader createMessageHeader(MessageId id, MessageId parent, + GroupId group, AuthorId author, String subject, long timestamp) { + return new MessageHeaderImpl(id, parent, group, author, subject, + timestamp); + } +} diff --git a/components/net/sf/briar/protocol/MessageHeaderImpl.java b/components/net/sf/briar/protocol/MessageHeaderImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..b173c4f4e44f6c498cc8ce08552f065e4cd3b05a --- /dev/null +++ b/components/net/sf/briar/protocol/MessageHeaderImpl.java @@ -0,0 +1,49 @@ +package net.sf.briar.protocol; + +import net.sf.briar.api.protocol.AuthorId; +import net.sf.briar.api.protocol.GroupId; +import net.sf.briar.api.protocol.MessageHeader; +import net.sf.briar.api.protocol.MessageId; + +class MessageHeaderImpl implements MessageHeader { + + private final MessageId id, parent; + private final GroupId group; + private final AuthorId author; + private final String subject; + private final long timestamp; + + MessageHeaderImpl(MessageId id, MessageId parent, GroupId group, + AuthorId author, String subject, long timestamp) { + this.id = id; + this.parent = parent; + this.group = group; + this.author = author; + this.subject = subject; + this.timestamp = timestamp; + } + + public MessageId getId() { + return id; + } + + public MessageId getParent() { + return parent; + } + + public GroupId getGroup() { + return group; + } + + public AuthorId getAuthor() { + return author; + } + + public String getSubject() { + return subject; + } + + public long getTimestamp() { + return timestamp; + } +} diff --git a/components/net/sf/briar/protocol/ProtocolModule.java b/components/net/sf/briar/protocol/ProtocolModule.java index 6d36d8efb38cc18522aa7a1f9d5a7f83dcb95c53..4ced04e08367332466509aab4ea451e54d56dea4 100644 --- a/components/net/sf/briar/protocol/ProtocolModule.java +++ b/components/net/sf/briar/protocol/ProtocolModule.java @@ -10,6 +10,7 @@ import net.sf.briar.api.protocol.Group; import net.sf.briar.api.protocol.GroupFactory; import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.MessageEncoder; +import net.sf.briar.api.protocol.MessageHeaderFactory; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.Offer; import net.sf.briar.api.protocol.ProtocolReaderFactory; @@ -30,6 +31,7 @@ public class ProtocolModule extends AbstractModule { bind(BatchFactory.class).to(BatchFactoryImpl.class); bind(GroupFactory.class).to(GroupFactoryImpl.class); bind(MessageEncoder.class).to(MessageEncoderImpl.class); + bind(MessageHeaderFactory.class).to(MessageHeaderFactoryImpl.class); bind(OfferFactory.class).to(OfferFactoryImpl.class); bind(ProtocolReaderFactory.class).to(ProtocolReaderFactoryImpl.class); bind(RequestFactory.class).to(RequestFactoryImpl.class); diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java index 2e8691ede953e63f1307dd1a41dde83810779490..29792f445181bacd492c7e02ac54e4dc0e161220 100644 --- a/test/net/sf/briar/db/H2DatabaseTest.java +++ b/test/net/sf/briar/db/H2DatabaseTest.java @@ -33,6 +33,7 @@ import net.sf.briar.api.protocol.Group; import net.sf.briar.api.protocol.GroupFactory; import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.Message; +import net.sf.briar.api.protocol.MessageHeaderFactory; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.transport.ConnectionWindow; import net.sf.briar.api.transport.ConnectionWindowFactory; @@ -61,6 +62,7 @@ public class H2DatabaseTest extends TestCase { private final Random random = new Random(); private final ConnectionWindowFactory connectionWindowFactory; private final GroupFactory groupFactory; + private final MessageHeaderFactory messageHeaderFactory; private final AuthorId authorId; private final BatchId batchId; @@ -87,6 +89,7 @@ public class H2DatabaseTest extends TestCase { new TransportModule(), new TestDatabaseModule(testDir)); connectionWindowFactory = i.getInstance(ConnectionWindowFactory.class); groupFactory = i.getInstance(GroupFactory.class); + messageHeaderFactory = i.getInstance(MessageHeaderFactory.class); authorId = new AuthorId(TestUtils.getRandomId()); batchId = new BatchId(TestUtils.getRandomId()); contactId = new ContactId(1); @@ -1665,7 +1668,7 @@ public class H2DatabaseTest extends TestCase { private Database<Connection> open(boolean resume) throws Exception { Database<Connection> db = new H2Database(testDir, password, MAX_SIZE, - connectionWindowFactory, groupFactory); + connectionWindowFactory, groupFactory, messageHeaderFactory); db.open(resume); return db; }