From 6ede7d0409fa48f6f2e5d0691e43baa227ee6d7f Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Wed, 30 Sep 2015 10:29:01 +0200 Subject: [PATCH] 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. --- .../org/jivesoftware/smack/roster/Roster.java | 16 +++++++++++++++- .../roster/rosterstore/DirectoryRosterStore.java | 15 +++++++++++---- .../smack/roster/rosterstore/RosterStore.java | 6 ++++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java index cf9ad0415..ca2fb0389 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java @@ -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 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); } diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStore.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStore.java index aa0be4df1..816d87890 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStore.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStore.java @@ -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.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); } + } diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/RosterStore.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/RosterStore.java index ab7e39649..068c31c3f 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/RosterStore.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/RosterStore.java @@ -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(); }