From 17bb738e9e47454f2f4d0071854be273c60b6309 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 16 Oct 2014 17:43:44 +0200 Subject: [PATCH] Make PubSubManager.getNode(String) more robust I've got reports from users that in some cases there can be multiple identities. Not just one, and in this case, the node type may not be the first identity. We now iterate over all identities until we either found one of type "leaf" or "collection". For example one user reports an ejabberd with PEP case, where the first identity is of type "pep", the second of type "leaf" and a third one with category "account" and type "registered". Also extend DiscoverInfo API with hasIdentity(String, String) and getIdentities(String, String). --- .../smackx/disco/packet/DiscoverInfo.java | 34 +++++++++++++++++++ .../smackx/pubsub/PubSubManager.java | 23 ++++++++++--- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java index 61b26d082..479f7945b 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java @@ -19,6 +19,7 @@ package org.jivesoftware.smackx.disco.packet; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.util.XmlStringBuilder; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; @@ -129,6 +130,39 @@ public class DiscoverInfo extends IQ implements Cloneable { return Collections.unmodifiableList(identities); } + /** + * Returns true if this DiscoverInfo contains at least one Identity of the given category and type. + * + * @param category the category to look for. + * @param type the type to look for. + * @return true if this DiscoverInfo contains a Identity of the given category and type. + */ + public boolean hasIdentity(String category, String type) { + for (Identity identity : identities) { + if (identity.getCategory().equals(category) && identity.getType().equals(type)) { + return true; + } + } + return false; + } + + /** + * Returns all Identities of the given category and type of this DiscoverInfo. + * + * @param category category the category to look for. + * @param type type the type to look for. + * @return a list of Identites with the given category and type. + */ + public List getIdentities(String category, String type) { + List res = new ArrayList(identities.size()); + for (Identity identity : identities) { + if (identity.getCategory().equals(category) && identity.getType().equals(type)) { + res.add(identity); + } + } + return res; + } + /** * Returns the node attribute that supplements the 'jid' attribute. A node is merely * something that is associated with a JID and for which the JID can provide information.

diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java index 4d1fc7acd..8a13c1262 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java @@ -171,11 +171,24 @@ final public class PubSubManager info.setNode(id); DiscoverInfo infoReply = (DiscoverInfo) con.createPacketCollectorAndSend(info).nextResultOrThrow(); - - if (infoReply.getIdentities().get(0).getType().equals(NodeType.leaf.toString())) - node = new LeafNode(con, id); - else - node = new CollectionNode(con, id); + + if (infoReply.hasIdentity(PubSub.ELEMENT, "leaf")) { + node = new LeafNode(con, id); + } + else if (infoReply.hasIdentity(PubSub.ELEMENT, "collection")) { + node = new CollectionNode(con, id); + } + else { + // XEP-60 5.3 states that + // "The 'disco#info' result MUST include an identity with a category of 'pubsub' and a type of either 'leaf' or 'collection'." + // If this is not the case, then we are dealing with an PubSub implementation that doesn't follow the specification. + throw new AssertionError( + "PubSub service '" + + to + + "' returned disco info result for node '" + + id + + "', but it did not contain an Identity of type 'leaf' or 'collection' (and category 'pubsub'), which is not allowed according to XEP-60 5.3."); + } node.setTo(to); nodeMap.put(id, node); }