summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Young <consult.awy@gmail.com>2014-11-13 06:42:37 (GMT)
committerAlan Young <consult.awy@gmail.com>2015-04-10 06:50:58 (GMT)
commit7d2101b93b6253c3ea15b663f7f3dc385cb21364 (patch)
treed81338baf0d117e83cdc07f882cbedd9471e834d /src/com/isode/stroke/roster
parenta20ca7ba40d837abe228462be0aba5d32d6831e3 (diff)
downloadstroke-7d2101b93b6253c3ea15b663f7f3dc385cb21364.zip
stroke-7d2101b93b6253c3ea15b663f7f3dc385cb21364.tar.bz2
Checkpoint - A bunch of initial stuff for Android
MemoryStorages, Storages NickManager, NickResolver CryptoProvider, Hash, SafeByteArray, JavaCryptoProvider CapsInfoGenerator, CapsManager, CapsMemoryStorage, CapsProvider, CapsStorage, CapsInfo CapsInfoSerializer, CapsInfoParser ClientDiscoManager, DiscoInfoResponder, EntityCapsManager, EntityCapsProvider GetDiscoInfoRequest ChatState, Idle Presence, PayloadAddingPresenceSender, PresenceOracle, SubscriptionManager StatusSerializer, StatusShowSerializer, StatusParser, StatusShowParser, Replace, ReplaceParser, ReplaceSerializer SecurityLabel, SecurityLabelsCatalog, GetSecurityLabelsCatalogRequest VCard, GetVCardRequest, SetVCardRequest, VCardManager, VCardMemoryStorage, VCardStorage RosterMemoryStorage, RosterPushResponder, RosterStorage, SetRosterRequest XMPPRoster, XMPPRosterController, XMPPRosterImpl, XMPPRosterItem GetRosterRequest, SetResponder Add parsers and serializers for Idle, VCard, PrivateStorage & Stroage. Add parser for Subject. Add impromptu flag to MUCInvitation. Update copyrights. Change-Id: I9949f506b70e60b3a64f1dadde8f9b235b322e1d
Diffstat (limited to 'src/com/isode/stroke/roster')
-rw-r--r--src/com/isode/stroke/roster/GetRosterRequest.java32
-rw-r--r--src/com/isode/stroke/roster/RosterMemoryStorage.java22
-rw-r--r--src/com/isode/stroke/roster/RosterPushResponder.java34
-rw-r--r--src/com/isode/stroke/roster/RosterStorage.java13
-rw-r--r--src/com/isode/stroke/roster/SetRosterRequest.java36
-rw-r--r--src/com/isode/stroke/roster/XMPPRoster.java80
-rw-r--r--src/com/isode/stroke/roster/XMPPRosterController.java116
-rw-r--r--src/com/isode/stroke/roster/XMPPRosterImpl.java95
-rw-r--r--src/com/isode/stroke/roster/XMPPRosterItem.java48
9 files changed, 476 insertions, 0 deletions
diff --git a/src/com/isode/stroke/roster/GetRosterRequest.java b/src/com/isode/stroke/roster/GetRosterRequest.java
new file mode 100644
index 0000000..18e885b
--- /dev/null
+++ b/src/com/isode/stroke/roster/GetRosterRequest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010-2015, Isode Limited, London, England.
+ * All rights reserved.
+ */
+
+package com.isode.stroke.roster;
+
+import com.isode.stroke.elements.IQ.Type;
+import com.isode.stroke.elements.RosterPayload;
+import com.isode.stroke.jid.JID;
+import com.isode.stroke.queries.GenericRequest;
+import com.isode.stroke.queries.IQRouter;
+
+public class GetRosterRequest extends GenericRequest<RosterPayload> {
+ public GetRosterRequest(JID target, IQRouter iqRouter) {
+ super(Type.Get, target, new RosterPayload(), iqRouter);
+ }
+
+ public GetRosterRequest(IQRouter iqRouter) {
+ super(Type.Get, new JID(), new RosterPayload(), iqRouter);
+ }
+
+ public static GetRosterRequest create(IQRouter router) {
+ return new GetRosterRequest(router);
+ }
+
+ public static GetRosterRequest create(IQRouter router, String version) {
+ GetRosterRequest request = new GetRosterRequest(router);
+ request.getPayloadGeneric().setVersion(version);
+ return request;
+ }
+}
diff --git a/src/com/isode/stroke/roster/RosterMemoryStorage.java b/src/com/isode/stroke/roster/RosterMemoryStorage.java
new file mode 100644
index 0000000..9c6d55f
--- /dev/null
+++ b/src/com/isode/stroke/roster/RosterMemoryStorage.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2011-2015, Isode Limited, London, England.
+ * All rights reserved.
+ */
+package com.isode.stroke.roster;
+
+import com.isode.stroke.elements.RosterPayload;
+
+public class RosterMemoryStorage implements RosterStorage {
+ private RosterPayload roster = new RosterPayload();
+
+ @Override
+ public RosterPayload getRoster() {
+ return roster;
+ }
+
+ @Override
+ public void setRoster(RosterPayload r) {
+ roster = r;
+ }
+
+}
diff --git a/src/com/isode/stroke/roster/RosterPushResponder.java b/src/com/isode/stroke/roster/RosterPushResponder.java
new file mode 100644
index 0000000..18b20b5
--- /dev/null
+++ b/src/com/isode/stroke/roster/RosterPushResponder.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010-2015, Isode Limited, London, England.
+ * All rights reserved.
+ */
+package com.isode.stroke.roster;
+
+import com.isode.stroke.elements.ErrorPayload;
+import com.isode.stroke.elements.RosterPayload;
+import com.isode.stroke.jid.JID;
+import com.isode.stroke.queries.IQRouter;
+import com.isode.stroke.queries.SetResponder;
+import com.isode.stroke.signals.Signal1;
+
+public class RosterPushResponder extends SetResponder<RosterPayload> {
+
+ final Signal1<RosterPayload> onRosterReceived = new Signal1<RosterPayload>();
+
+ public RosterPushResponder(IQRouter router) {
+ super(new RosterPayload(), router);
+ }
+
+ @Override
+ protected boolean handleSetRequest(JID from, JID to, String id, RosterPayload payload) {
+ if (getIQRouter().isAccountJID(from)) {
+ onRosterReceived.emit(payload);
+ sendResponse(from, id, new RosterPayload());
+ } else {
+ sendError(from, id, ErrorPayload.Condition.NotAuthorized, ErrorPayload.Type.Cancel);
+ }
+ return true;
+ }
+
+
+}
diff --git a/src/com/isode/stroke/roster/RosterStorage.java b/src/com/isode/stroke/roster/RosterStorage.java
new file mode 100644
index 0000000..df048cc
--- /dev/null
+++ b/src/com/isode/stroke/roster/RosterStorage.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011-2015, Isode Limited, London, England.
+ * All rights reserved.
+ */
+package com.isode.stroke.roster;
+
+import com.isode.stroke.elements.RosterPayload;
+
+public interface RosterStorage {
+
+ RosterPayload getRoster();
+ void setRoster(RosterPayload roster);
+}
diff --git a/src/com/isode/stroke/roster/SetRosterRequest.java b/src/com/isode/stroke/roster/SetRosterRequest.java
new file mode 100644
index 0000000..4d52676
--- /dev/null
+++ b/src/com/isode/stroke/roster/SetRosterRequest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010-2015, Isode Limited, London, England.
+ * All rights reserved.
+ */
+package com.isode.stroke.roster;
+
+import com.isode.stroke.elements.ErrorPayload;
+import com.isode.stroke.elements.IQ;
+import com.isode.stroke.elements.Payload;
+import com.isode.stroke.elements.RosterPayload;
+import com.isode.stroke.jid.JID;
+import com.isode.stroke.queries.IQRouter;
+import com.isode.stroke.queries.Request;
+import com.isode.stroke.signals.Signal1;
+
+public class SetRosterRequest extends Request {
+
+ static SetRosterRequest create(RosterPayload payload, IQRouter router) {
+ return new SetRosterRequest(new JID(), payload, router);
+ }
+
+ static SetRosterRequest create(RosterPayload payload, final JID to, IQRouter router) {
+ return new SetRosterRequest(to, payload, router);
+ }
+
+ private SetRosterRequest(final JID to, RosterPayload payload, IQRouter router) {
+ super(IQ.Type.Set, to, payload, router);
+ }
+
+ public void handleResponse(Payload payload, ErrorPayload error) {
+ onResponse.emit(error);
+ }
+
+ final Signal1<ErrorPayload> onResponse = new Signal1<ErrorPayload>();
+
+}
diff --git a/src/com/isode/stroke/roster/XMPPRoster.java b/src/com/isode/stroke/roster/XMPPRoster.java
new file mode 100644
index 0000000..a2c3cd3
--- /dev/null
+++ b/src/com/isode/stroke/roster/XMPPRoster.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010-2015, Isode Limited, London, England.
+ * All rights reserved.
+ */
+package com.isode.stroke.roster;
+
+import java.util.Set;
+import java.util.Collection;
+
+import com.isode.stroke.elements.RosterItemPayload;
+import com.isode.stroke.jid.JID;
+import com.isode.stroke.signals.Signal;
+import com.isode.stroke.signals.Signal1;
+import com.isode.stroke.signals.Signal3;
+
+public abstract class XMPPRoster {
+ /**
+ * Checks whether the bare jid of the given jid is in the roster.
+ */
+ public abstract boolean containsJID(final JID jid);
+
+ /**
+ * Retrieves the subscription state for the given jid.
+ */
+ public abstract RosterItemPayload.Subscription getSubscriptionStateForJID(final JID jid);
+
+ /**
+ * Retrieves the stored roster name for the given jid.
+ */
+ public abstract String getNameForJID(final JID jid);
+
+ /**
+ * Returns the list of groups for the given JID.
+ */
+ public abstract Collection<String> getGroupsForJID(final JID jid);
+
+ /**
+ * Retrieve the items in the roster.
+ */
+ public abstract Collection<XMPPRosterItem> getItems();
+
+ /**
+ * Retrieve the item with the given JID.
+ */
+ public abstract XMPPRosterItem getItem(final JID jid);
+
+ /**
+ * Retrieve the list of (existing) groups.
+ */
+ public abstract Set<String> getGroups();
+
+ /**
+ * Emitted when the given JID is added to the roster.
+ */
+ public final Signal1<JID> onJIDAdded = new Signal1<JID>();
+
+ /**
+ * Emitted when the given JID is removed from the roster.
+ */
+ public final Signal1<JID> onJIDRemoved = new Signal1<JID>();
+
+ /**
+ * Emitted when the name or the groups of the roster item with the
+ * given JID changes.
+ */
+ public final Signal3<JID, String, Collection<String>> onJIDUpdated = new Signal3<JID, String, Collection<String>>();
+
+ /**
+ * Emitted when the roster is reset (e.g. due to logging in/logging out).
+ * After this signal is emitted, the roster is empty. It will be repopulated through
+ * onJIDAdded and onJIDRemoved events.
+ */
+ public final Signal onRosterCleared = new Signal();
+
+ /**
+ * Emitted after the last contact of the initial roster request response
+ * was added.
+ */
+ public final Signal onInitialRosterPopulated = new Signal();
+}
diff --git a/src/com/isode/stroke/roster/XMPPRosterController.java b/src/com/isode/stroke/roster/XMPPRosterController.java
new file mode 100644
index 0000000..6ad03f2
--- /dev/null
+++ b/src/com/isode/stroke/roster/XMPPRosterController.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2010-2015, Isode Limited, London, England.
+ * All rights reserved.
+ */
+package com.isode.stroke.roster;
+
+import java.util.Collection;
+
+import com.isode.stroke.elements.ErrorPayload;
+import com.isode.stroke.elements.RosterItemPayload;
+import com.isode.stroke.elements.RosterPayload;
+import com.isode.stroke.roster.GetRosterRequest;
+import com.isode.stroke.queries.IQRouter;
+import com.isode.stroke.signals.Slot1;
+import com.isode.stroke.signals.Slot2;
+
+public class XMPPRosterController {
+ private IQRouter iqRouter_;
+ private RosterPushResponder rosterPushResponder_;
+ private XMPPRosterImpl xmppRoster_;
+ private RosterStorage rosterStorage_;
+ private boolean useVersioning;
+
+
+ /**
+ * The controller does not gain ownership of these parameters.
+ */
+ public XMPPRosterController(IQRouter iqRouter, XMPPRosterImpl xmppRoster, RosterStorage rosterStorage) {
+ iqRouter_ = iqRouter;
+ rosterPushResponder_ = new RosterPushResponder(iqRouter);
+ xmppRoster_ = xmppRoster;
+ rosterStorage_ = rosterStorage;
+ useVersioning = false;
+
+ rosterPushResponder_.onRosterReceived.connect(new Slot1<RosterPayload>() {
+ @Override
+ public void call(RosterPayload p1) {
+ handleRosterReceived(p1, false, new RosterPayload());
+ }
+ });
+ rosterPushResponder_.start();
+ }
+
+ public void delete() {
+ rosterPushResponder_.stop();
+ }
+
+ public void requestRoster() {
+ xmppRoster_.clear();
+
+ final RosterPayload storedRoster = rosterStorage_.getRoster();
+ GetRosterRequest rosterRequest;
+ if (useVersioning) {
+ String version = "";
+ if (storedRoster != null && storedRoster.getVersion() != null) {
+ version = storedRoster.getVersion();
+ }
+ rosterRequest = GetRosterRequest.create(iqRouter_, version);
+ }
+ else {
+ rosterRequest = GetRosterRequest.create(iqRouter_);
+ }
+
+ rosterRequest.onResponse.connect(new Slot2<RosterPayload, ErrorPayload>() {
+ @Override
+ public void call(RosterPayload p1, ErrorPayload p2) {
+ handleRosterReceived(p1, true, storedRoster);
+ }
+ });
+ rosterRequest.send();
+ }
+
+ void handleRosterReceived(RosterPayload rosterPayload, boolean initial, RosterPayload previousRoster) {
+ if (rosterPayload != null) {
+ for (final RosterItemPayload item : rosterPayload.getItems()) {
+ //Don't worry about the updated case, the XMPPRoster sorts that out.
+ if (item.getSubscription() == RosterItemPayload.Subscription.Remove) {
+ xmppRoster_.removeContact(item.getJID());
+ } else {
+ xmppRoster_.addContact(item.getJID(), item.getName(), item.getGroups(), item.getSubscription());
+ }
+ }
+ }
+ else if (previousRoster != null) {
+ // The cached version hasn't changed; emit all items
+ for (final RosterItemPayload item : previousRoster.getItems()) {
+ if (item.getSubscription() != RosterItemPayload.Subscription.Remove) {
+ xmppRoster_.addContact(item.getJID(), item.getName(), item.getGroups(), item.getSubscription());
+ }
+ else {
+ System.err.println("ERROR: Stored invalid roster item");
+ }
+ }
+ }
+ if (initial) {
+ xmppRoster_.onInitialRosterPopulated.emit();
+ }
+ if (rosterPayload != null && rosterPayload.getVersion() != null && useVersioning) {
+ saveRoster(rosterPayload.getVersion());
+ }
+ }
+
+ void saveRoster(final String version) {
+ Collection<XMPPRosterItem> items = xmppRoster_.getItems();
+ RosterPayload roster = new RosterPayload();
+ roster.setVersion(version);
+ for (final XMPPRosterItem item : items) {
+ roster.addItem(new RosterItemPayload(item.getJID(), item.getName(), item.getSubscription(), item.getGroups()));
+ }
+ rosterStorage_.setRoster(roster);
+ }
+
+ public void setUseVersioning(boolean b) {
+ useVersioning = b;
+ }
+}
diff --git a/src/com/isode/stroke/roster/XMPPRosterImpl.java b/src/com/isode/stroke/roster/XMPPRosterImpl.java
new file mode 100644
index 0000000..61d0bc3
--- /dev/null
+++ b/src/com/isode/stroke/roster/XMPPRosterImpl.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2010-2015, Isode Limited, London, England.
+ * All rights reserved.
+ */
+package com.isode.stroke.roster;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.isode.stroke.elements.RosterItemPayload;
+import com.isode.stroke.elements.RosterItemPayload.Subscription;
+import com.isode.stroke.jid.JID;
+
+public class XMPPRosterImpl extends XMPPRoster {
+
+ private Map<JID, XMPPRosterItem> entries_ = new HashMap<JID, XMPPRosterItem>();
+
+ void addContact(final JID jid, final String name, final Collection<String> groups, RosterItemPayload.Subscription subscription) {
+ JID bareJID = jid.toBare();
+ XMPPRosterItem item = entries_.get(bareJID);
+
+ if (item != null) {
+ String oldName = item.getName();
+ Collection<String> oldGroups = item.getGroups();
+ entries_.put(bareJID, new XMPPRosterItem(jid, name, groups, subscription));
+ onJIDUpdated.emit(bareJID, oldName, oldGroups);
+ }
+ else {
+ entries_.put(bareJID, new XMPPRosterItem(jid, name, groups, subscription));
+ onJIDAdded.emit(bareJID);
+ }
+ }
+
+ void removeContact(final JID jid) {
+ entries_.remove(jid.toBare());
+ onJIDRemoved.emit(jid);
+ }
+
+ void clear() {
+ entries_.clear();
+ onRosterCleared.emit();
+ }
+
+ @Override
+ public boolean containsJID(JID jid) {
+ return entries_.containsKey(jid);
+ }
+
+ @Override
+ public Subscription getSubscriptionStateForJID(JID jid) {
+ XMPPRosterItem item = entries_.get(jid.toBare());
+ if (item != null) return item.getSubscription();
+ return RosterItemPayload.Subscription.None;
+ }
+
+ @Override
+ public String getNameForJID(JID jid) {
+ XMPPRosterItem item = entries_.get(jid.toBare());
+ if (item != null) return item.getName();
+ return "";
+ }
+
+ @Override
+ public Collection<String> getGroupsForJID(JID jid) {
+ XMPPRosterItem item = entries_.get(jid.toBare());
+ if (item != null) return item.getGroups();
+ return new ArrayList<String>();
+ }
+
+ @Override
+ public Collection<XMPPRosterItem> getItems() {
+ return entries_.values();
+ }
+
+ @Override
+ public XMPPRosterItem getItem(JID jid) {
+ XMPPRosterItem item = entries_.get(jid.toBare());
+ if (item != null) return item;
+
+ return null;
+ }
+
+ @Override
+ public Set<String> getGroups() {
+ Set<String> groups = new HashSet<String>();
+ for (XMPPRosterItem item : entries_.values())
+ groups.addAll(item.getGroups());
+ return groups;
+ }
+
+}
diff --git a/src/com/isode/stroke/roster/XMPPRosterItem.java b/src/com/isode/stroke/roster/XMPPRosterItem.java
new file mode 100644
index 0000000..1412f83
--- /dev/null
+++ b/src/com/isode/stroke/roster/XMPPRosterItem.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010-2015, Isode Limited, London, England.
+ * All rights reserved.
+ */
+package com.isode.stroke.roster;
+
+import java.util.Collection;
+
+import com.isode.stroke.elements.RosterItemPayload;
+import com.isode.stroke.jid.JID;
+
+public class XMPPRosterItem {
+ private JID jid;
+ private String name;
+ private Collection<String> groups;
+ private RosterItemPayload.Subscription subscription;
+
+ public XMPPRosterItem(final JID jid, final String name, final Collection<String> groups, RosterItemPayload.Subscription subscription) {
+ this.jid = jid;
+ this.name = name;
+ this.groups = groups;
+ this.subscription = subscription;
+ }
+
+ public final JID getJID() {
+ return jid;
+ }
+
+ public final String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public final Collection<String> getGroups() {
+ return groups;
+ }
+
+ public void setGroups(final Collection<String> groups) {
+ this.groups = groups;
+ }
+
+ public RosterItemPayload.Subscription getSubscription() {
+ return subscription;
+ }
+}