From 0d90e6535e7d9a240562b9589dcf79284acbe5c3 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sat, 8 Feb 2020 17:56:24 +0100 Subject: [PATCH] Initial commit --- settings.gradle | 2 + smack-messenger-android/build.gradle | 7 ++ .../messenger/android/AndroidCsiManager.java | 71 ++++++++++++ .../AbstractActivityLifecycleCallbacks.java | 45 ++++++++ smack-messenger/build.gradle | 7 ++ .../smackx/messenger/AccountRecord.java | 34 ++++++ .../smackx/messenger/Messenger.java | 100 +++++++++++++++++ .../smackx/messenger/XmppAccount.java | 36 ++++++ .../connection/ConnectionFactory.java | 10 ++ .../connection/XmppTcpConnectionFactory.java | 22 ++++ .../messenger/csi/ClientStateListener.java | 7 ++ .../store/FilebasedMessengerStore.java | 105 ++++++++++++++++++ .../messenger/store/MessengerStore.java | 9 ++ .../messenger/store/account/AccountStore.java | 13 +++ .../store/roster/GlobalRosterStore.java | 26 +++++ .../store/roster/RosterStoreAdapter.java | 57 ++++++++++ 16 files changed, 551 insertions(+) create mode 100644 smack-messenger-android/build.gradle create mode 100644 smack-messenger-android/src/main/java/org/jivesoftware/smacks/messenger/android/AndroidCsiManager.java create mode 100644 smack-messenger-android/src/main/java/org/jivesoftware/smacks/messenger/android/csi/util/AbstractActivityLifecycleCallbacks.java create mode 100644 smack-messenger/build.gradle create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/AccountRecord.java create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/Messenger.java create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/XmppAccount.java create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/connection/ConnectionFactory.java create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/connection/XmppTcpConnectionFactory.java create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/csi/ClientStateListener.java create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/FilebasedMessengerStore.java create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/MessengerStore.java create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/account/AccountStore.java create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/roster/GlobalRosterStore.java create mode 100644 smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/roster/RosterStoreAdapter.java diff --git a/settings.gradle b/settings.gradle index d3b53d80e..c0d0f8528 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,6 +29,8 @@ include 'smack-core', 'smack-omemo-signal-integration-test', 'smack-repl', 'smack-openpgp', + 'smack-messenger', + 'smack-messenger-android', 'smack-xmlparser', 'smack-xmlparser-stax', 'smack-xmlparser-xpp3' diff --git a/smack-messenger-android/build.gradle b/smack-messenger-android/build.gradle new file mode 100644 index 000000000..7797548ef --- /dev/null +++ b/smack-messenger-android/build.gradle @@ -0,0 +1,7 @@ +dependencies { + implementation project(":smack-messenger") + implementation project(":smack-android-extensions") + + // Add the Android jar to the Eclipse .classpath. + compileOnly files(androidBootClasspath) +} diff --git a/smack-messenger-android/src/main/java/org/jivesoftware/smacks/messenger/android/AndroidCsiManager.java b/smack-messenger-android/src/main/java/org/jivesoftware/smacks/messenger/android/AndroidCsiManager.java new file mode 100644 index 000000000..d265a0e96 --- /dev/null +++ b/smack-messenger-android/src/main/java/org/jivesoftware/smacks/messenger/android/AndroidCsiManager.java @@ -0,0 +1,71 @@ +package org.jivesoftware.smacks.messenger.android; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import org.jivesoftware.smacks.messenger.android.csi.util.AbstractActivityLifecycleCallbacks; +import org.jivesoftware.smackx.messenger.csi.ClientStateListener; + +import android.app.Activity; +import android.app.Application; + +/** + * Android Utility class that observes the current state of the application. + * If the application currently displays at least one active Activity, then registered + * {@link ClientStateListener ClientStateListeners} will be notified via {@link ClientStateListener#onClientInForeground()}. + * If the application goes into the background, {@link ClientStateListener#onClientInBackground()} will be fired. + * + * Setup: During application startup, call {@link android.app.Application#registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks)} + * and pass an instance of {@link AndroidCsiManager} as argument. + * + * Remember to also register a {@link ClientStateListener} implementation (eg. the Messenger class from smack-messenger). + */ +public final class AndroidCsiManager extends AbstractActivityLifecycleCallbacks { + + private static AndroidCsiManager INSTANCE; + + private AtomicInteger activityReferences = new AtomicInteger(0); + private AtomicBoolean isActivityChangingConfiguration = new AtomicBoolean(false); + + private final List listeners = new ArrayList<>(); + + private AndroidCsiManager() { + + } + + public AndroidCsiManager getInstance() { + if (INSTANCE == null) { + INSTANCE = new AndroidCsiManager(); + } + return INSTANCE; + } + + @Override + public void onActivityStarted(Activity activity) { + if (activityReferences.incrementAndGet() == 1 && !isActivityChangingConfiguration.get()) { + for (ClientStateListener listener : listeners) { + listener.onClientInForeground(); + } + } + } + + @Override + public void onActivityStopped(Activity activity) { + isActivityChangingConfiguration.set(activity.isChangingConfigurations()); + if (activityReferences.decrementAndGet() == 0 && !isActivityChangingConfiguration.get()) { + for (ClientStateListener listener : listeners) { + listener.onClientInBackground(); + } + } + } + + public void addClientStateListener(ClientStateListener listener) { + this.listeners.add(listener); + } + + public void removeClientStateListener(ClientStateListener listener) { + this.listeners.remove(listener); + } +} diff --git a/smack-messenger-android/src/main/java/org/jivesoftware/smacks/messenger/android/csi/util/AbstractActivityLifecycleCallbacks.java b/smack-messenger-android/src/main/java/org/jivesoftware/smacks/messenger/android/csi/util/AbstractActivityLifecycleCallbacks.java new file mode 100644 index 000000000..ca8607bdc --- /dev/null +++ b/smack-messenger-android/src/main/java/org/jivesoftware/smacks/messenger/android/csi/util/AbstractActivityLifecycleCallbacks.java @@ -0,0 +1,45 @@ +package org.jivesoftware.smacks.messenger.android.csi.util; + +import android.app.Activity; +import android.app.Application; +import android.os.Bundle; + +/** + * Abstract class providing empty implementations of {@link Application.ActivityLifecycleCallbacks}. + */ +public abstract class AbstractActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks { + @Override + public void onActivityCreated(Activity activity, Bundle bundle) { + + } + + @Override + public void onActivityStarted(Activity activity) { + + } + + @Override + public void onActivityResumed(Activity activity) { + + } + + @Override + public void onActivityPaused(Activity activity) { + + } + + @Override + public void onActivityStopped(Activity activity) { + + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { + + } + + @Override + public void onActivityDestroyed(Activity activity) { + + } +} \ No newline at end of file diff --git a/smack-messenger/build.gradle b/smack-messenger/build.gradle new file mode 100644 index 000000000..fc44f14b6 --- /dev/null +++ b/smack-messenger/build.gradle @@ -0,0 +1,7 @@ +dependencies { + implementation project(":smack-core") + implementation project(":smack-tcp") + implementation project(":smack-im") + implementation project(":smack-extensions") + implementation project(":smack-experimental") +} \ No newline at end of file diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/AccountRecord.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/AccountRecord.java new file mode 100644 index 000000000..a457bb67d --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/AccountRecord.java @@ -0,0 +1,34 @@ +package org.jivesoftware.smackx.messenger; + +import java.util.UUID; + +public class AccountRecord { + + private final UUID accountId; + private final String username; + private final String password; + private final String serviceName; + + public AccountRecord(UUID accountId, String username, String password, String serviceName) { + this.accountId = accountId; + this.username = username; + this.password = password; + this.serviceName = serviceName; + } + + public UUID getAccountId() { + return accountId; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getServiceName() { + return serviceName; + } +} diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/Messenger.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/Messenger.java new file mode 100644 index 000000000..1fc04ee81 --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/Messenger.java @@ -0,0 +1,100 @@ +package org.jivesoftware.smackx.messenger; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import org.jivesoftware.smack.ReconnectionManager; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smackx.caps.EntityCapsManager; +import org.jivesoftware.smackx.carbons.CarbonManager; +import org.jivesoftware.smackx.csi.ClientStateIndicationManager; +import org.jivesoftware.smackx.iqversion.VersionManager; +import org.jivesoftware.smackx.messenger.connection.ConnectionFactory; +import org.jivesoftware.smackx.messenger.connection.XmppTcpConnectionFactory; +import org.jivesoftware.smackx.messenger.csi.ClientStateListener; +import org.jivesoftware.smackx.messenger.store.MessengerStore; +import org.jivesoftware.smackx.messenger.store.roster.RosterStoreAdapter; +import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager; + +import org.jxmpp.stringprep.XmppStringprepException; + +public class Messenger implements ClientStateListener { + + private final Map accounts = new ConcurrentHashMap<>(); + private final MessengerStore messengerStore; + + private ConnectionFactory connectionFactory = new XmppTcpConnectionFactory(); + + public Messenger(MessengerStore store) { + this.messengerStore = store; + EntityCapsManager.setPersistentCache(store); + + setGlobalDefaults(); + } + + private void setGlobalDefaults() { + ReconnectionManager.setEnabledPerDefault(true); + StableUniqueStanzaIdManager.setEnabledByDefault(true); + VersionManager.setAutoAppendSmackVersion(false); + } + + public XmppAccount addAccount(UUID accountId, String username, String password, String serviceName) + throws XmppStringprepException { + XMPPConnection connection = connectionFactory.createConnection(username, password, serviceName); + + XmppAccount xmppAccount = new XmppAccount(accountId, connection); + accounts.put(accountId, xmppAccount); + + offlineAccountSetup(xmppAccount); + + return xmppAccount; + } + + private void offlineAccountSetup(XmppAccount account) { + Roster.getInstanceFor(account.getConnection()).setRosterStore( + new RosterStoreAdapter(account.getAccountId(), messengerStore)); + } + + private void onlineAccountSetup(XmppAccount account) + throws InterruptedException, XMPPException, SmackException { + if (CarbonManager.getInstanceFor(account.getConnection()).isSupportedByServer()) { + CarbonManager.getInstanceFor(account.getConnection()).enableCarbons(); + } + + + } + + @Override + public synchronized void onClientInForeground() { + for (XmppAccount connection : accounts.values()) { + trySetCsiActive(connection); + } + } + + private void trySetCsiActive(XmppAccount connection) { + try { + ClientStateIndicationManager.active(connection.getConnection()); + } catch (SmackException.NotConnectedException | InterruptedException e) { + e.printStackTrace(); + } + } + + @Override + public synchronized void onClientInBackground() { + for (XmppAccount connection : accounts.values()) { + trySetCsiInactive(connection); + } + } + + private void trySetCsiInactive(XmppAccount connection) { + try { + ClientStateIndicationManager.inactive(connection.getConnection()); + } catch (SmackException.NotConnectedException | InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/XmppAccount.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/XmppAccount.java new file mode 100644 index 000000000..353a0ff30 --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/XmppAccount.java @@ -0,0 +1,36 @@ +package org.jivesoftware.smackx.messenger; + +import java.io.IOException; +import java.util.UUID; + +import org.jivesoftware.smack.AbstractXMPPConnection; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; + +public class XmppAccount { + + private final UUID accountId; + private final XMPPConnection connection; + + public XmppAccount(UUID accountId, XMPPConnection connection) { + this.connection = connection; + this.accountId = accountId; + } + + public XMPPConnection getConnection() { + return connection; + } + + public UUID getAccountId() { + return accountId; + } + + public void login() throws InterruptedException, XMPPException, SmackException, IOException { + ((AbstractXMPPConnection) getConnection()).connect().login(); + } + + public boolean isLoggedIn() { + return getConnection().isAuthenticated(); + } +} diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/connection/ConnectionFactory.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/connection/ConnectionFactory.java new file mode 100644 index 000000000..c90bc97ee --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/connection/ConnectionFactory.java @@ -0,0 +1,10 @@ +package org.jivesoftware.smackx.messenger.connection; + +import org.jivesoftware.smack.XMPPConnection; + +import org.jxmpp.stringprep.XmppStringprepException; + +public interface ConnectionFactory { + + XMPPConnection createConnection(String username, String password, String serviceName) throws XmppStringprepException; +} diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/connection/XmppTcpConnectionFactory.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/connection/XmppTcpConnectionFactory.java new file mode 100644 index 000000000..c76708265 --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/connection/XmppTcpConnectionFactory.java @@ -0,0 +1,22 @@ +package org.jivesoftware.smackx.messenger.connection; + +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; +import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; + +import org.jxmpp.stringprep.XmppStringprepException; + +public class XmppTcpConnectionFactory implements ConnectionFactory { + + @Override + public XMPPConnection createConnection(String username, String password, String serviceName) throws XmppStringprepException { + XMPPTCPConnectionConfiguration configuration = XMPPTCPConnectionConfiguration.builder() + .setConnectTimeout(60 * 1000) + .setHost(serviceName) + .setUsernameAndPassword(username, password) + .build(); + XMPPTCPConnection connection = new XMPPTCPConnection(configuration); + + return connection; + } +} diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/csi/ClientStateListener.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/csi/ClientStateListener.java new file mode 100644 index 000000000..b04e68a84 --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/csi/ClientStateListener.java @@ -0,0 +1,7 @@ +package org.jivesoftware.smackx.messenger.csi; + +public interface ClientStateListener { + void onClientInForeground(); + + void onClientInBackground(); +} diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/FilebasedMessengerStore.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/FilebasedMessengerStore.java new file mode 100644 index 000000000..6665a4ebf --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/FilebasedMessengerStore.java @@ -0,0 +1,105 @@ +package org.jivesoftware.smackx.messenger.store; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import org.jivesoftware.smack.roster.packet.RosterPacket; +import org.jivesoftware.smack.roster.rosterstore.DirectoryRosterStore; +import org.jivesoftware.smackx.caps.cache.SimpleDirectoryPersistentCache; +import org.jivesoftware.smackx.disco.packet.DiscoverInfo; +import org.jivesoftware.smackx.messenger.AccountRecord; + +import org.jxmpp.jid.Jid; + +public class FilebasedMessengerStore implements MessengerStore { + + private final File storeBaseDir; + private final Map rosterStoreMap = new ConcurrentHashMap<>(); + private final SimpleDirectoryPersistentCache entityCapsCache; + private final Map accounts = new ConcurrentHashMap<>(); + + public FilebasedMessengerStore(File storeBaseDir) { + this.storeBaseDir = storeBaseDir; + entityCapsCache = new SimpleDirectoryPersistentCache(new File(storeBaseDir, "entityCaps")); + } + + private DirectoryRosterStore getRosterStore(UUID accountId) { + DirectoryRosterStore store = rosterStoreMap.get(accountId); + if (store == null) { + File accountDir = new File(storeBaseDir, accountId.toString()); + File rosterDir = new File(accountDir, "roster"); + store = DirectoryRosterStore.open(rosterDir); + if (store == null) { + store = DirectoryRosterStore.init(rosterDir); + } + rosterStoreMap.put(accountId, store); + } + return store; + } + + + @Override + public void addDiscoverInfoByNodePersistent(String nodeVer, DiscoverInfo info) { + entityCapsCache.addDiscoverInfoByNodePersistent(nodeVer, info); + } + + @Override + public DiscoverInfo lookup(String nodeVer) { + return entityCapsCache.lookup(nodeVer); + } + + @Override + public void emptyCache() { + entityCapsCache.emptyCache(); + } + + @Override + public List getAllAccounts() { + return new ArrayList<>(accounts.values()); + } + + @Override + public AccountRecord getAccount(UUID accountId) { + return accounts.get(accountId); + } + + @Override + public List getEntries(UUID accountId) { + return getRosterStore(accountId).getEntries(); + } + + @Override + public RosterPacket.Item getEntry(UUID accountId, Jid bareJid) { + return getRosterStore(accountId).getEntry(bareJid); + } + + @Override + public String getRosterVersion(UUID accountId) { + return getRosterStore(accountId).getRosterVersion(); + } + + @Override + public boolean addEntry(UUID accountId, RosterPacket.Item item, String version) { + return getRosterStore(accountId).addEntry(item, version); + } + + @Override + public boolean resetEntries(UUID accountId, Collection items, String version) { + return getRosterStore(accountId).resetEntries(items, version); + } + + @Override + public boolean removeEntry(UUID accountId, Jid bareJid, String version) { + return getRosterStore(accountId).removeEntry(bareJid, version); + } + + @Override + public void resetStore(UUID accountId) { + getRosterStore(accountId).resetStore(); + } +} diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/MessengerStore.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/MessengerStore.java new file mode 100644 index 000000000..01791d0bd --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/MessengerStore.java @@ -0,0 +1,9 @@ +package org.jivesoftware.smackx.messenger.store; + +import org.jivesoftware.smackx.caps.cache.EntityCapsPersistentCache; +import org.jivesoftware.smackx.messenger.store.account.AccountStore; +import org.jivesoftware.smackx.messenger.store.roster.GlobalRosterStore; + +public interface MessengerStore extends EntityCapsPersistentCache, AccountStore, GlobalRosterStore { + +} diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/account/AccountStore.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/account/AccountStore.java new file mode 100644 index 000000000..8bb6be196 --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/account/AccountStore.java @@ -0,0 +1,13 @@ +package org.jivesoftware.smackx.messenger.store.account; + +import java.util.List; +import java.util.UUID; + +import org.jivesoftware.smackx.messenger.AccountRecord; + +public interface AccountStore { + + List getAllAccounts(); + AccountRecord getAccount(UUID accountId); + +} diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/roster/GlobalRosterStore.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/roster/GlobalRosterStore.java new file mode 100644 index 000000000..2f8cf34b5 --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/roster/GlobalRosterStore.java @@ -0,0 +1,26 @@ +package org.jivesoftware.smackx.messenger.store.roster; + +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +import org.jivesoftware.smack.roster.packet.RosterPacket; + +import org.jxmpp.jid.Jid; + +public interface GlobalRosterStore { + + List getEntries(UUID accountId); + + RosterPacket.Item getEntry(UUID accountId, Jid bareJid); + + String getRosterVersion(UUID accountId); + + boolean addEntry(UUID accountId, RosterPacket.Item item, String version); + + boolean resetEntries(UUID accountId, Collection items, String version); + + boolean removeEntry(UUID accountId, Jid bareJid, String version); + + void resetStore(UUID accountId); +} diff --git a/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/roster/RosterStoreAdapter.java b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/roster/RosterStoreAdapter.java new file mode 100644 index 000000000..a5bb07900 --- /dev/null +++ b/smack-messenger/src/main/java/org/jivesoftware/smackx/messenger/store/roster/RosterStoreAdapter.java @@ -0,0 +1,57 @@ +package org.jivesoftware.smackx.messenger.store.roster; + +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +import org.jivesoftware.smack.roster.packet.RosterPacket; +import org.jivesoftware.smack.roster.rosterstore.RosterStore; +import org.jivesoftware.smackx.messenger.store.roster.GlobalRosterStore; + +import org.jxmpp.jid.Jid; + +public class RosterStoreAdapter implements RosterStore { + + private final GlobalRosterStore store; + private final UUID accountId; + + public RosterStoreAdapter(UUID accountId, GlobalRosterStore globalRosterStore) { + this.store = globalRosterStore; + this.accountId = accountId; + } + + @Override + public List getEntries() { + return store.getEntries(accountId); + } + + @Override + public RosterPacket.Item getEntry(Jid bareJid) { + return store.getEntry(accountId, bareJid); + } + + @Override + public String getRosterVersion() { + return store.getRosterVersion(accountId); + } + + @Override + public boolean addEntry(RosterPacket.Item item, String version) { + return store.addEntry(accountId, item, version); + } + + @Override + public boolean resetEntries(Collection items, String version) { + return store.resetEntries(accountId, items, version); + } + + @Override + public boolean removeEntry(Jid bareJid, String version) { + return store.removeEntry(accountId, bareJid, version); + } + + @Override + public void resetStore() { + store.resetStore(accountId); + } +}