Make RosterStore handle corrupted stores.

This can happen for example if the store schema changes across Smack
version.

Previously Smack would simply ignore the entry, which would lead to an
inconsistent view of the Roster.
This commit is contained in:
Florian Schmaus 2015-09-30 10:29:01 +02:00
parent d7ac9481c7
commit 6ede7d0409
3 changed files with 32 additions and 5 deletions

View File

@ -1424,7 +1424,21 @@ public final class Roster extends Manager {
// means that rosterver was used and the roster hasn't changed (much) since the
// version we presented the server. So we simply load the roster from the store and
// await possible further roster pushes.
for (RosterPacket.Item item : rosterStore.getEntries()) {
List<RosterPacket.Item> storedItems = rosterStore.getEntries();
if (storedItems == null) {
// The roster store was corrupted. Reset the store and reload the roster without using a roster version.
rosterStore.resetStore();
try {
reload();
} catch (NotLoggedInException | NotConnectedException
| InterruptedException e) {
LOGGER.log(Level.FINE,
"Exception while trying to load the roster after the roster store was corrupted",
e);
}
return;
}
for (RosterPacket.Item item : storedItems) {
RosterEntry entry = new RosterEntry(item, Roster.this, connection);
addUpdateEntry(addedEntries, updatedEntries, unchangedEntries, item, entry);
}

View File

@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -124,11 +125,10 @@ public final class DirectoryRosterStore implements RosterStore {
for (File file : fileDir.listFiles(rosterDirFilter)) {
Item entry = readEntry(file);
if (entry == null) {
LOGGER.severe("Roster store file '" + file + "' is invalid.");
}
else {
entries.add(entry);
// Roster directory store corrupt. Abort and signal this by returning null.
return null;
}
entries.add(entry);
}
return entries;
@ -179,6 +179,12 @@ public final class DirectoryRosterStore implements RosterStore {
return setRosterVersion(version);
}
@Override
public void resetStore() {
resetEntries(Collections.<Item>emptyList(), "");
}
private static Item readEntry(File file) {
Reader reader;
try {
@ -212,4 +218,5 @@ public final class DirectoryRosterStore implements RosterStore {
String encodedJid = Base32.encode(bareJid.toString());
return new File(fileDir, ENTRY_PREFIX + encodedJid);
}
}

View File

@ -70,4 +70,10 @@ public interface RosterStore {
*/
public boolean removeEntry(Jid bareJid, String version);
/**
* Reset the store by removing all entries and setting the version to the empty String.
*
* @since 4.2
*/
public void resetStore();
}