Throw an exception if a raw message has been deleted.

This commit is contained in:
akwizgran
2018-08-23 14:51:56 +01:00
parent d84e176bb4
commit fbd38dbb94
18 changed files with 37 additions and 53 deletions

View File

@@ -16,8 +16,6 @@ import org.briarproject.bramble.api.sync.MessageId;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
public interface ClientHelper { public interface ClientHelper {
@@ -32,16 +30,12 @@ public interface ClientHelper {
Message createMessageForStoringMetadata(GroupId g); Message createMessageForStoringMetadata(GroupId g);
@Nullable
Message getMessage(MessageId m) throws DbException; Message getMessage(MessageId m) throws DbException;
@Nullable
Message getMessage(Transaction txn, MessageId m) throws DbException; Message getMessage(Transaction txn, MessageId m) throws DbException;
@Nullable
BdfList getMessageAsList(MessageId m) throws DbException, FormatException; BdfList getMessageAsList(MessageId m) throws DbException, FormatException;
@Nullable
BdfList getMessageAsList(Transaction txn, MessageId m) throws DbException, BdfList getMessageAsList(Transaction txn, MessageId m) throws DbException,
FormatException; FormatException;

View File

@@ -298,12 +298,12 @@ public interface DatabaseComponent {
throws DbException; throws DbException;
/** /**
* Returns the message with the given ID, in serialised form, or null if * Returns the message with the given ID, in serialised form.
* the message has been deleted.
* <p/> * <p/>
* Read-only. * Read-only.
*
* @throws MessageDeletedException if the message has been deleted
*/ */
@Nullable
byte[] getRawMessage(Transaction txn, MessageId m) throws DbException; byte[] getRawMessage(Transaction txn, MessageId m) throws DbException;
/** /**

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api.db;
/**
* Thrown when a message that has been deleted is requested from the database.
* This exception may occur due to concurrent updates and does not indicate a
* database error.
*/
public class MessageDeletedException extends DbException {
}

View File

@@ -127,9 +127,7 @@ class ClientHelperImpl implements ClientHelper {
@Override @Override
public Message getMessage(Transaction txn, MessageId m) throws DbException { public Message getMessage(Transaction txn, MessageId m) throws DbException {
byte[] raw = db.getRawMessage(txn, m); return messageFactory.createMessage(m, db.getRawMessage(txn, m));
if (raw == null) return null;
return messageFactory.createMessage(m, raw);
} }
@Override @Override
@@ -150,7 +148,6 @@ class ClientHelperImpl implements ClientHelper {
public BdfList getMessageAsList(Transaction txn, MessageId m) public BdfList getMessageAsList(Transaction txn, MessageId m)
throws DbException, FormatException { throws DbException, FormatException {
byte[] raw = db.getRawMessage(txn, m); byte[] raw = db.getRawMessage(txn, m);
if (raw == null) return null;
return toList(raw, MESSAGE_HEADER_LENGTH, return toList(raw, MESSAGE_HEADER_LENGTH,
raw.length - MESSAGE_HEADER_LENGTH); raw.length - MESSAGE_HEADER_LENGTH);
} }

View File

@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooNewException;
import org.briarproject.bramble.api.db.DataTooOldException; import org.briarproject.bramble.api.db.DataTooOldException;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.MessageDeletedException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
@@ -465,12 +466,12 @@ interface Database<T> {
long getNextSendTime(T txn, ContactId c) throws DbException; long getNextSendTime(T txn, ContactId c) throws DbException;
/** /**
* Returns the message with the given ID, in serialised form, or null if * Returns the message with the given ID, in serialised form.
* the message has been deleted.
* <p/> * <p/>
* Read-only. * Read-only.
*
* @throws MessageDeletedException if the message has been deleted
*/ */
@Nullable
byte[] getRawMessage(T txn, MessageId m) throws DbException; byte[] getRawMessage(T txn, MessageId m) throws DbException;
/** /**

View File

@@ -487,7 +487,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getMessagesToShare(txn); return db.getMessagesToShare(txn);
} }
@Nullable
@Override @Override
public byte[] getRawMessage(Transaction transaction, MessageId m) public byte[] getRawMessage(Transaction transaction, MessageId m)
throws DbException { throws DbException {

View File

@@ -7,6 +7,7 @@ import org.briarproject.bramble.api.db.DataTooNewException;
import org.briarproject.bramble.api.db.DataTooOldException; import org.briarproject.bramble.api.db.DataTooOldException;
import org.briarproject.bramble.api.db.DbClosedException; import org.briarproject.bramble.api.db.DbClosedException;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.MessageDeletedException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
@@ -2019,7 +2020,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
@Override @Override
@Nullable
public byte[] getRawMessage(Connection txn, MessageId m) public byte[] getRawMessage(Connection txn, MessageId m)
throws DbException { throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
@@ -2034,6 +2034,7 @@ abstract class JdbcDatabase implements Database<Connection> {
if (rs.next()) throw new DbStateException(); if (rs.next()) throw new DbStateException();
rs.close(); rs.close();
ps.close(); ps.close();
if (raw == null) throw new MessageDeletedException();
return raw; return raw;
} catch (SQLException e) { } catch (SQLException e) {
tryToClose(rs); tryToClose(rs);

View File

@@ -164,7 +164,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) { for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) {
BdfList message = clientHelper.getMessageAsList(txn, BdfList message = clientHelper.getMessageAsList(txn,
e.getValue().messageId); e.getValue().messageId);
if (message == null) throw new DbException();
local.put(e.getKey(), parseProperties(message)); local.put(e.getKey(), parseProperties(message));
} }
return local; return local;
@@ -187,7 +186,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
// Retrieve and parse the latest local properties // Retrieve and parse the latest local properties
BdfList message = clientHelper.getMessageAsList(txn, BdfList message = clientHelper.getMessageAsList(txn,
latest.messageId); latest.messageId);
if (message == null) throw new DbException();
p = parseProperties(message); p = parseProperties(message);
} }
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -227,7 +225,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
// Retrieve and parse the latest remote properties // Retrieve and parse the latest remote properties
BdfList message = BdfList message =
clientHelper.getMessageAsList(txn, latest.messageId); clientHelper.getMessageAsList(txn, latest.messageId);
if (message == null) throw new DbException();
return parseProperties(message); return parseProperties(message);
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
@@ -265,7 +262,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
} else { } else {
BdfList message = clientHelper.getMessageAsList(txn, BdfList message = clientHelper.getMessageAsList(txn,
latest.messageId); latest.messageId);
if (message == null) throw new DbException();
TransportProperties old = parseProperties(message); TransportProperties old = parseProperties(message);
merged = new TransportProperties(old); merged = new TransportProperties(old);
merged.putAll(p); merged.putAll(p);

View File

@@ -129,7 +129,6 @@ class ValidationManagerImpl implements ValidationManager, Service,
try { try {
MessageId id = unvalidated.poll(); MessageId id = unvalidated.poll();
byte[] raw = db.getRawMessage(txn, id); byte[] raw = db.getRawMessage(txn, id);
if (raw == null) throw new DbException();
m = messageFactory.createMessage(id, raw); m = messageFactory.createMessage(id, raw);
g = db.getGroup(txn, m.getGroupId()); g = db.getGroup(txn, m.getGroupId());
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -198,7 +197,6 @@ class ValidationManagerImpl implements ValidationManager, Service,
invalidate = getDependentsToInvalidate(txn, id); invalidate = getDependentsToInvalidate(txn, id);
} else if (allDelivered) { } else if (allDelivered) {
byte[] raw = db.getRawMessage(txn, id); byte[] raw = db.getRawMessage(txn, id);
if (raw == null) throw new DbException();
Message m = messageFactory.createMessage(id, raw); Message m = messageFactory.createMessage(id, raw);
Group g = db.getGroup(txn, m.getGroupId()); Group g = db.getGroup(txn, m.getGroupId());
ClientId c = g.getClientId(); ClientId c = g.getClientId();

View File

@@ -139,7 +139,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
} }
@Override @Override
public void stopService() throws ServiceException { public void stopService() {
} }
@Override @Override
@@ -274,9 +274,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
private List<ClientVersion> loadClientVersions(Transaction txn, private List<ClientVersion> loadClientVersions(Transaction txn,
MessageId m) throws DbException { MessageId m) throws DbException {
try { try {
BdfList body = clientHelper.getMessageAsList(txn, m); return parseClientVersions(clientHelper.getMessageAsList(txn, m));
if (body == null) throw new DbException();
return parseClientVersions(body);
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }
@@ -359,9 +357,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
private Update loadUpdate(Transaction txn, MessageId m) throws DbException { private Update loadUpdate(Transaction txn, MessageId m) throws DbException {
try { try {
BdfList body = clientHelper.getMessageAsList(txn, m); return parseUpdate(clientHelper.getMessageAsList(txn, m));
if (body == null) throw new DbException();
return parseUpdate(body);
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }

View File

@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.MessageDeletedException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
@@ -1654,8 +1655,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
ids = db.getMessagesToOffer(txn, contactId, 100); ids = db.getMessagesToOffer(txn, contactId, 100);
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
// The raw message should not be null // The raw message should be available
assertNotNull(db.getRawMessage(txn, messageId)); assertArrayEquals(raw, db.getRawMessage(txn, messageId));
// Delete the message // Delete the message
db.deleteMessage(txn, messageId); db.deleteMessage(txn, messageId);
@@ -1669,8 +1670,13 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
ids = db.getMessagesToOffer(txn, contactId, 100); ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
// The raw message should be null // Requesting the raw message should throw an exception
assertNull(db.getRawMessage(txn, messageId)); try {
db.getRawMessage(txn, messageId);
fail();
} catch (MessageDeletedException expected) {
// Expected
}
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();

View File

@@ -94,7 +94,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
} }
@Override @Override
public void addingContact(Transaction txn, Contact c) throws DbException { public void addingContact(Transaction txn, Contact c) {
} }
@Override @Override
@@ -311,7 +311,6 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
// Get body of message to be wrapped // Get body of message to be wrapped
BdfList body = clientHelper.getMessageAsList(txn, header.getId()); BdfList body = clientHelper.getMessageAsList(txn, header.getId());
if (body == null) throw new DbException();
long timestamp = header.getTimestamp(); long timestamp = header.getTimestamp();
Message wrappedMessage; Message wrappedMessage;
@@ -459,9 +458,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
@Override @Override
public String getPostBody(MessageId m) throws DbException { public String getPostBody(MessageId m) throws DbException {
try { try {
BdfList message = clientHelper.getMessageAsList(m); return getPostBody(clientHelper.getMessageAsList(m));
if (message == null) throw new DbException();
return getPostBody(message);
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }

View File

@@ -204,10 +204,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
@Override @Override
public String getPostBody(MessageId m) throws DbException { public String getPostBody(MessageId m) throws DbException {
try { try {
// Parent ID, author, forum post body, signature return getPostBody(clientHelper.getMessageAsList(m));
BdfList body = clientHelper.getMessageAsList(m);
if (body == null) throw new DbException();
return getPostBody(body);
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }

View File

@@ -463,7 +463,6 @@ class IntroductionManagerImpl extends ConversationClientImpl
author = session.getRemote().author; author = session.getRemote().author;
} else throw new AssertionError(); } else throw new AssertionError();
Message msg = clientHelper.getMessage(txn, m); Message msg = clientHelper.getMessage(txn, m);
if (msg == null) throw new AssertionError();
BdfList body = clientHelper.toList(msg); BdfList body = clientHelper.toList(msg);
RequestMessage rm = messageParser.parseRequestMessage(msg, body); RequestMessage rm = messageParser.parseRequestMessage(msg, body);
String message = rm.getMessage(); String message = rm.getMessage();

View File

@@ -217,9 +217,7 @@ class MessagingManagerImpl extends ConversationClientImpl
public String getMessageBody(MessageId m) throws DbException { public String getMessageBody(MessageId m) throws DbException {
try { try {
// 0: private message body // 0: private message body
BdfList message = clientHelper.getMessageAsList(m); return clientHelper.getMessageAsList(m).getString(0);
if (message == null) throw new DbException();
return message.getString(0);
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }

View File

@@ -301,9 +301,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
@Override @Override
public String getMessageBody(MessageId m) throws DbException { public String getMessageBody(MessageId m) throws DbException {
try { try {
BdfList body = clientHelper.getMessageAsList(m); return getMessageBody(clientHelper.getMessageAsList(m));
if (body == null) throw new DbException();
return getMessageBody(body);
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }

View File

@@ -91,7 +91,6 @@ class MessageParserImpl implements MessageParser {
public InviteMessage getInviteMessage(Transaction txn, MessageId m) public InviteMessage getInviteMessage(Transaction txn, MessageId m)
throws DbException, FormatException { throws DbException, FormatException {
Message message = clientHelper.getMessage(txn, m); Message message = clientHelper.getMessage(txn, m);
if (message == null) throw new DbException();
BdfList body = clientHelper.toList(message); BdfList body = clientHelper.toList(message);
return parseInviteMessage(message, body); return parseInviteMessage(message, body);
} }

View File

@@ -78,7 +78,6 @@ abstract class MessageParserImpl<S extends Shareable>
public InviteMessage<S> getInviteMessage(Transaction txn, MessageId m) public InviteMessage<S> getInviteMessage(Transaction txn, MessageId m)
throws DbException, FormatException { throws DbException, FormatException {
Message message = clientHelper.getMessage(txn, m); Message message = clientHelper.getMessage(txn, m);
if (message == null) throw new DbException();
BdfList body = clientHelper.toList(message); BdfList body = clientHelper.toList(message);
return parseInviteMessage(message, body); return parseInviteMessage(message, body);
} }