Make PubSub elements namespace aware

Also fixes SMACK-814.
This commit is contained in:
Florian Schmaus 2018-04-19 11:05:43 +02:00
parent acc64ffc2d
commit 31244ae982
25 changed files with 354 additions and 173 deletions

View File

@ -18,6 +18,7 @@ package org.jivesoftware.smackx.pubsub;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.XmlStringBuilder;
@ -38,10 +39,30 @@ import org.jxmpp.jid.BareJid;
public class Affiliation implements ExtensionElement {
public static final String ELEMENT = "affiliation";
public enum AffiliationNamespace {
basic(PubSubElementType.AFFILIATIONS),
owner(PubSubElementType.AFFILIATIONS_OWNER),
;
public final PubSubElementType type;
AffiliationNamespace(PubSubElementType type) {
this.type = type;
}
public static AffiliationNamespace fromXmlns(String xmlns) {
for (AffiliationNamespace affiliationsNamespace : AffiliationNamespace.values()) {
if (affiliationsNamespace.type.getNamespace().getXmlns().equals(xmlns)) {
return affiliationsNamespace;
}
}
throw new IllegalArgumentException("Invalid affiliations namespace: " + xmlns);
}
}
private final BareJid jid;
private final String node;
private final Type affiliation;
private final PubSubNamespace namespace;
private final AffiliationNamespace namespace;
public enum Type {
member, none, outcast, owner, publisher
@ -54,14 +75,21 @@ public class Affiliation implements ExtensionElement {
* @param affiliation the optional affiliation.
*/
public Affiliation(String node, Type affiliation) {
this(node, affiliation, affiliation == null ? AffiliationNamespace.basic : AffiliationNamespace.owner);
}
/**
* Constructs an affiliation.
*
* @param node The node the user is affiliated with.
* @param affiliation the optional affiliation.
* @param namespace the affiliation's namespace.
*/
public Affiliation(String node, Type affiliation, AffiliationNamespace namespace) {
this.node = StringUtils.requireNotNullOrEmpty(node, "node must not be null or empty");
this.affiliation = affiliation;
this.jid = null;
if (affiliation != null) {
namespace = PubSubNamespace.BASIC;
} else {
namespace = PubSubNamespace.OWNER;
}
this.namespace = Objects.requireNonNull(namespace);
}
/**
@ -71,10 +99,10 @@ public class Affiliation implements ExtensionElement {
* @param affiliation
*/
public Affiliation(BareJid jid, Type affiliation) {
this(jid, affiliation, PubSubNamespace.OWNER);
this(jid, affiliation, AffiliationNamespace.owner);
}
public Affiliation(BareJid jid, Type affiliation, PubSubNamespace namespace) {
public Affiliation(BareJid jid, Type affiliation, AffiliationNamespace namespace) {
this.jid = jid;
this.affiliation = affiliation;
this.node = null;
@ -124,11 +152,11 @@ public class Affiliation implements ExtensionElement {
@Override
public String getNamespace() {
return namespace.getXmlns();
return getPubSubNamespace().getXmlns();
}
public PubSubNamespace getPubSubNamespace() {
return namespace;
return namespace.type.getNamespace();
}
/**
@ -139,7 +167,7 @@ public class Affiliation implements ExtensionElement {
*/
public boolean isAffiliationModification() {
if (jid != null && affiliation != null) {
assert (node == null && namespace == PubSubNamespace.OWNER);
assert (node == null && namespace == AffiliationNamespace.owner);
return true;
}
return false;

View File

@ -21,6 +21,8 @@ import java.util.List;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.pubsub.Affiliation.AffiliationNamespace;
/**
* Represents the <b>affiliations</b> element of the reply to a request for affiliations.
* It is defined in the specification in section <a href="http://xmpp.org/extensions/xep-0060.html#entity-affiliations">5.7 Retrieve Affiliations</a> and
@ -33,15 +35,23 @@ public class AffiliationsExtension extends NodeExtension {
private final String node;
public AffiliationsExtension() {
this(null, null);
this(null);
}
public AffiliationsExtension(List<Affiliation> subList) {
this(subList, null);
}
public AffiliationsExtension(AffiliationNamespace affiliationsNamespace, List<Affiliation> subList) {
this(affiliationsNamespace, subList, null);
}
public AffiliationsExtension(List<Affiliation> subList, String node) {
super(PubSubElementType.AFFILIATIONS);
this(AffiliationNamespace.basic, subList, node);
}
public AffiliationsExtension(AffiliationNamespace affiliationsNamespace, List<Affiliation> subList, String node) {
super(affiliationsNamespace.type);
items = subList;
this.node = node;
}

View File

@ -42,7 +42,7 @@ public class EventElement implements EmbeddedPacketExtension {
/**
* The constant String "http://jabber.org/protocol/pubsub#event".
*/
public static final String NAMESPACE = PubSubNamespace.EVENT.getXmlns();
public static final String NAMESPACE = PubSubNamespace.event.getXmlns();
private final EventElementType type;
private final NodeExtension ext;
@ -72,7 +72,7 @@ public class EventElement implements EmbeddedPacketExtension {
@Override
public String getNamespace() {
return PubSubNamespace.EVENT.getXmlns();
return PubSubNamespace.event.getXmlns();
}
@Override

View File

@ -43,7 +43,7 @@ public enum FormNodeType {
}
public static FormNodeType valueOfFromElementName(String elem, String configNamespace) {
if ("configure".equals(elem) && PubSubNamespace.OWNER.getXmlns().equals(configNamespace)) {
if ("configure".equals(elem) && PubSubNamespace.owner.getXmlns().equals(configNamespace)) {
return CONFIGURE_OWNER;
}
return valueOf(elem.toUpperCase(Locale.US));

View File

@ -17,6 +17,7 @@
package org.jivesoftware.smackx.pubsub;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
@ -50,7 +51,27 @@ import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
* @author Robin Collier
*/
public class Item extends NodeExtension {
private String id;
public enum ItemNamespace {
pubsub(PubSubElementType.ITEM),
event(PubSubElementType.ITEM_EVENT),
;
private final PubSubElementType type;
ItemNamespace(PubSubElementType type) {
this.type = type;
}
public static ItemNamespace fromXmlns(String xmlns) {
for (ItemNamespace itemNamespace : ItemNamespace.values()) {
if (itemNamespace.type.getNamespace().getXmlns().equals(xmlns)) {
return itemNamespace;
}
}
throw new IllegalArgumentException("Invalid item namespace: " + xmlns);
}
}
private final String itemId;
/**
* Create an empty <tt>Item</tt> with no id. This is a valid item for nodes which are configured
@ -60,7 +81,7 @@ public class Item extends NodeExtension {
* method in this case.
*/
public Item() {
super(PubSubElementType.ITEM);
this(ItemNamespace.pubsub, null, null);
}
/**
@ -71,9 +92,18 @@ public class Item extends NodeExtension {
* Passing null is the equivalent of calling {@link #Item()}.
*/
public Item(String itemId) {
// The element type is actually irrelevant since we override getNamespace() to return null
super(PubSubElementType.ITEM);
id = itemId;
this(ItemNamespace.pubsub, itemId, null);
}
/**
* Create an <tt>Item</tt> with an id but no payload. This is a valid item for nodes which are configured
* so that {@link ConfigureForm#isDeliverPayloads()} is false.
*
* @param itemId The id if the item. It must be unique within the node unless overwriting and existing item.
* Passing null is the equivalent of calling {@link #Item()}.
*/
public Item(ItemNamespace itemNamespace, String itemId) {
this(itemNamespace, itemId, null);
}
/**
@ -88,8 +118,23 @@ public class Item extends NodeExtension {
* @param nodeId The id of the node which the item was published to.
*/
public Item(String itemId, String nodeId) {
super(PubSubElementType.ITEM_EVENT, nodeId);
id = itemId;
this(ItemNamespace.pubsub, itemId, nodeId);
}
/**
* Create an <tt>Item</tt> with an id and a node id.
* <p>
* <b>Note:</b> This is not valid for publishing an item to a node, only receiving from
* one as part of {@link Message}. If used to create an Item to publish
* (via {@link LeafNode#publish(Item)}, the server <i>may</i> return an
* error for an invalid packet.
*
* @param itemId The id of the item.
* @param nodeId The id of the node which the item was published to.
*/
public Item(ItemNamespace itemNamespace, String itemId, String nodeId) {
super(itemNamespace.type, nodeId);
this.itemId = itemId;
}
/**
@ -98,36 +143,30 @@ public class Item extends NodeExtension {
* @return The id
*/
public String getId() {
return id;
return itemId;
}
@Override
public String getNamespace() {
return null;
public XmlStringBuilder toXML() {
XmlStringBuilder xml = getCommonXml();
xml.closeEmptyElement();
return xml;
}
@Override
public String toXML() {
StringBuilder builder = new StringBuilder("<item");
protected final XmlStringBuilder getCommonXml() {
XmlStringBuilder xml = new XmlStringBuilder(this);
if (id != null) {
builder.append(" id='");
builder.append(id);
builder.append('\'');
}
xml.optAttribute("id", getId());
xml.optAttribute("node", getNode());
if (getNode() != null) {
builder.append(" node='");
builder.append(getNode());
builder.append('\'');
}
builder.append("/>");
return builder.toString();
return xml;
}
@Override
public String toString() {
return getClass().getName() + " | Content [" + toXML() + "]";
}
}

View File

@ -19,6 +19,7 @@ package org.jivesoftware.smackx.pubsub;
import java.util.List;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.NamedElement;
/**
* This class is used for multiple purposes.
@ -37,7 +38,7 @@ import org.jivesoftware.smack.packet.ExtensionElement;
public class ItemsExtension extends NodeExtension implements EmbeddedPacketExtension {
protected ItemsElementType type;
protected Boolean notify;
protected List<? extends ExtensionElement> items;
protected List<? extends NamedElement> items;
public enum ItemsElementType {
/** An items element, which has an optional <b>max_items</b> attribute when requesting items. */
@ -82,7 +83,7 @@ public class ItemsExtension extends NodeExtension implements EmbeddedPacketExten
* @param nodeId The node to which the items are being sent or deleted
* @param items The list of {@link Item} or {@link RetractItem}
*/
public ItemsExtension(ItemsElementType itemsType, String nodeId, List<? extends ExtensionElement> items) {
public ItemsExtension(ItemsElementType itemsType, String nodeId, List<? extends NamedElement> items) {
super(itemsType.getNodeElement(), nodeId);
type = itemsType;
this.items = items;
@ -134,7 +135,7 @@ public class ItemsExtension extends NodeExtension implements EmbeddedPacketExten
*
* @return List of {@link Item}, {@link RetractItem}, or null
*/
public List<? extends ExtensionElement> getItems() {
public List<? extends NamedElement> getItems() {
return items;
}
@ -167,7 +168,7 @@ public class ItemsExtension extends NodeExtension implements EmbeddedPacketExten
}
else {
builder.append("'>");
for (ExtensionElement item : items) {
for (NamedElement item : items) {
builder.append(item.toXML());
}
}

View File

@ -341,7 +341,7 @@ public class LeafNode extends Node {
* @throws InterruptedException
*/
public void deleteAllItems() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
PubSub request = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PURGE_OWNER, getId()), PubSubElementType.PURGE_OWNER.getNamespace());
PubSub request = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PURGE_OWNER, getId()));
pubSubManager.getConnection().createStanzaCollectorAndSend(request).nextResultOrThrow();
}

View File

@ -34,6 +34,8 @@ import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smackx.delay.DelayInformationManager;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
import org.jivesoftware.smackx.pubsub.Affiliation.AffiliationNamespace;
import org.jivesoftware.smackx.pubsub.SubscriptionsExtension.SubscriptionsNamespace;
import org.jivesoftware.smackx.pubsub.listener.ItemDeleteListener;
import org.jivesoftware.smackx.pubsub.listener.ItemEventListener;
import org.jivesoftware.smackx.pubsub.listener.NodeConfigListener;
@ -84,7 +86,7 @@ public abstract class Node {
*/
public ConfigureForm getNodeConfiguration() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
PubSub pubSub = createPubsubPacket(Type.get, new NodeExtension(
PubSubElementType.CONFIGURE_OWNER, getId()), PubSubNamespace.OWNER);
PubSubElementType.CONFIGURE_OWNER, getId()));
Stanza reply = sendPubsubPacket(pubSub);
return NodeUtils.getFormFromPacket(reply, PubSubElementType.CONFIGURE_OWNER);
}
@ -100,7 +102,7 @@ public abstract class Node {
*/
public void sendConfigurationForm(Form submitForm) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
PubSub packet = createPubsubPacket(Type.set, new FormNode(FormNodeType.CONFIGURE_OWNER,
getId(), submitForm), PubSubNamespace.OWNER);
getId(), submitForm));
pubSubManager.getConnection().createStanzaCollectorAndSend(packet).nextResultOrThrow();
}
@ -152,7 +154,7 @@ public abstract class Node {
*/
public List<Subscription> getSubscriptions(List<ExtensionElement> additionalExtensions, Collection<ExtensionElement> returnedExtensions)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
return getSubscriptions(additionalExtensions, returnedExtensions, null);
return getSubscriptions(SubscriptionsNamespace.basic, additionalExtensions, returnedExtensions);
}
/**
@ -197,13 +199,15 @@ public abstract class Node {
public List<Subscription> getSubscriptionsAsOwner(List<ExtensionElement> additionalExtensions,
Collection<ExtensionElement> returnedExtensions) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException {
return getSubscriptions(additionalExtensions, returnedExtensions, PubSubNamespace.OWNER);
return getSubscriptions(SubscriptionsNamespace.owner, additionalExtensions, returnedExtensions);
}
private List<Subscription> getSubscriptions(List<ExtensionElement> additionalExtensions,
Collection<ExtensionElement> returnedExtensions, PubSubNamespace pubSubNamespace)
private List<Subscription> getSubscriptions(SubscriptionsNamespace subscriptionsNamespace, List<ExtensionElement> additionalExtensions,
Collection<ExtensionElement> returnedExtensions)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
PubSub pubSub = createPubsubPacket(Type.get, new NodeExtension(PubSubElementType.SUBSCRIPTIONS, getId()), pubSubNamespace);
PubSubElementType pubSubElementType = subscriptionsNamespace.type;
PubSub pubSub = createPubsubPacket(Type.get, new NodeExtension(pubSubElementType, getId()));
if (additionalExtensions != null) {
for (ExtensionElement pe : additionalExtensions) {
pubSub.addExtension(pe);
@ -213,7 +217,7 @@ public abstract class Node {
if (returnedExtensions != null) {
returnedExtensions.addAll(reply.getExtensions());
}
SubscriptionsExtension subElem = reply.getExtension(PubSubElementType.SUBSCRIPTIONS);
SubscriptionsExtension subElem = reply.getExtension(pubSubElementType);
return subElem.getSubscriptions();
}
@ -237,8 +241,7 @@ public abstract class Node {
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
PubSub pubSub = createPubsubPacket(Type.set,
new SubscriptionsExtension(getId(), changedSubs),
PubSubNamespace.OWNER);
new SubscriptionsExtension(SubscriptionsNamespace.owner, getId(), changedSubs));
return sendPubsubPacket(pubSub);
}
@ -275,7 +278,7 @@ public abstract class Node {
public List<Affiliation> getAffiliations(List<ExtensionElement> additionalExtensions, Collection<ExtensionElement> returnedExtensions)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
return getAffiliations(PubSubNamespace.BASIC, additionalExtensions, returnedExtensions);
return getAffiliations(AffiliationNamespace.basic, additionalExtensions, returnedExtensions);
}
/**
@ -315,14 +318,15 @@ public abstract class Node {
public List<Affiliation> getAffiliationsAsOwner(List<ExtensionElement> additionalExtensions, Collection<ExtensionElement> returnedExtensions)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
return getAffiliations(PubSubNamespace.OWNER, additionalExtensions, returnedExtensions);
return getAffiliations(AffiliationNamespace.owner, additionalExtensions, returnedExtensions);
}
private List<Affiliation> getAffiliations(PubSubNamespace namespace, List<ExtensionElement> additionalExtensions,
private List<Affiliation> getAffiliations(AffiliationNamespace affiliationsNamespace, List<ExtensionElement> additionalExtensions,
Collection<ExtensionElement> returnedExtensions) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException {
PubSubElementType pubSubElementType = affiliationsNamespace.type;
PubSub pubSub = createPubsubPacket(Type.get, new NodeExtension(PubSubElementType.AFFILIATIONS, getId()), namespace);
PubSub pubSub = createPubsubPacket(Type.get, new NodeExtension(pubSubElementType, getId()));
if (additionalExtensions != null) {
for (ExtensionElement pe : additionalExtensions) {
pubSub.addExtension(pe);
@ -332,7 +336,7 @@ public abstract class Node {
if (returnedExtensions != null) {
returnedExtensions.addAll(reply.getExtensions());
}
AffiliationsExtension affilElem = reply.getExtension(PubSubElementType.AFFILIATIONS);
AffiliationsExtension affilElem = reply.getExtension(pubSubElementType);
return affilElem.getAffiliations();
}
@ -355,13 +359,12 @@ public abstract class Node {
public PubSub modifyAffiliationAsOwner(List<Affiliation> affiliations) throws NoResponseException,
XMPPErrorException, NotConnectedException, InterruptedException {
for (Affiliation affiliation : affiliations) {
if (affiliation.getPubSubNamespace() != PubSubNamespace.OWNER) {
if (affiliation.getPubSubNamespace() != PubSubNamespace.owner) {
throw new IllegalArgumentException("Must use Affiliation(BareJid, Type) affiliations");
}
}
PubSub pubSub = createPubsubPacket(Type.set, new AffiliationsExtension(affiliations, getId()),
PubSubNamespace.OWNER);
PubSub pubSub = createPubsubPacket(Type.set, new AffiliationsExtension(AffiliationNamespace.owner, affiliations, getId()));
return sendPubsubPacket(pubSub);
}
@ -567,12 +570,8 @@ public abstract class Node {
return super.toString() + " " + getClass().getName() + " id: " + id;
}
protected PubSub createPubsubPacket(Type type, ExtensionElement ext) {
return createPubsubPacket(type, ext, null);
}
protected PubSub createPubsubPacket(Type type, ExtensionElement ext, PubSubNamespace ns) {
return PubSub.createPubsubPacket(pubSubManager.getServiceJid(), type, ext, ns);
protected PubSub createPubsubPacket(Type type, NodeExtension ext) {
return PubSub.createPubsubPacket(pubSubManager.getServiceJid(), type, ext);
}
protected PubSub sendPubsubPacket(PubSub packet) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
@ -611,7 +610,7 @@ public abstract class Node {
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public void processStanza(Stanza packet) {
EventElement event = packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
EventElement event = packet.getExtension("event", PubSubNamespace.event.getXmlns());
ItemsExtension itemsElem = (ItemsExtension) event.getEvent();
ItemPublishEvent eventItems = new ItemPublishEvent(itemsElem.getNode(), itemsElem.getItems(), getSubscriptionIds(packet), DelayInformationManager.getDelayTimestamp(packet));
// TODO: Use AsyncButOrdered (with Node as Key?)
@ -635,7 +634,7 @@ public abstract class Node {
@Override
public void processStanza(Stanza packet) {
// CHECKSTYLE:OFF
EventElement event = packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
EventElement event = packet.getExtension("event", PubSubNamespace.event.getXmlns());
List<ExtensionElement> extList = event.getExtensions();
@ -674,7 +673,7 @@ public abstract class Node {
@Override
public void processStanza(Stanza packet) {
EventElement event = packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
EventElement event = packet.getExtension("event", PubSubNamespace.event.getXmlns());
ConfigurationEvent config = (ConfigurationEvent) event.getEvent();
// TODO: Use AsyncButOrdered (with Node as Key?)

View File

@ -18,6 +18,8 @@ package org.jivesoftware.smackx.pubsub;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
/**
* A class which represents a common element within the pubsub defined
* schemas. One which has a <b>node</b> as an attribute. This class is
@ -66,9 +68,13 @@ public class NodeExtension implements ExtensionElement {
return element.getElementName();
}
public PubSubNamespace getPubSubNamespace() {
return element.getNamespace();
}
@Override
public String getNamespace() {
return element.getNamespace().getXmlns();
public final String getNamespace() {
return getPubSubNamespace().getXmlns();
}
@Override

View File

@ -18,6 +18,7 @@ package org.jivesoftware.smackx.pubsub;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
@ -93,7 +94,25 @@ public class PayloadItem<E extends ExtensionElement> extends Item {
* @param payloadExt A {@link ExtensionElement} which represents the payload data.
*/
public PayloadItem(String itemId, String nodeId, E payloadExt) {
super(itemId, nodeId);
this(ItemNamespace.pubsub, itemId, nodeId, payloadExt);
}
/**
* Create an <tt>Item</tt> with an id, node id and payload.
*
* <p>
* <b>Note:</b> This is not valid for publishing an item to a node, only receiving from
* one as part of {@link Message}. If used to create an Item to publish
* (via {@link LeafNode#publish(Item)}, the server <i>may</i> return an
* error for an invalid packet.
* </p>
*
* @param itemId The id of this item.
* @param nodeId The id of the node the item was published to.
* @param payloadExt A {@link ExtensionElement} which represents the payload data.
*/
public PayloadItem(ItemNamespace itemNamespace, String itemId, String nodeId, E payloadExt) {
super(itemNamespace, itemId, nodeId);
if (payloadExt == null)
throw new IllegalArgumentException("payload cannot be 'null'");
@ -111,25 +130,14 @@ public class PayloadItem<E extends ExtensionElement> extends Item {
}
@Override
public String toXML() {
StringBuilder builder = new StringBuilder("<item");
public XmlStringBuilder toXML() {
XmlStringBuilder xml = getCommonXml();
if (getId() != null) {
builder.append(" id='");
builder.append(getId());
builder.append('\'');
}
xml.rightAngleBracket();
xml.append(payload.toXML());
xml.closeElement(this);
if (getNode() != null) {
builder.append(" node='");
builder.append(getNode());
builder.append('\'');
}
builder.append('>');
builder.append(payload.toXML());
builder.append("</item>");
return builder.toString();
return xml;
}
@Override

View File

@ -27,28 +27,30 @@ import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
* @author Robin Collier
*/
public enum PubSubElementType {
CREATE("create", PubSubNamespace.BASIC),
DELETE("delete", PubSubNamespace.OWNER),
DELETE_EVENT("delete", PubSubNamespace.EVENT),
CONFIGURE("configure", PubSubNamespace.BASIC),
CONFIGURE_OWNER("configure", PubSubNamespace.OWNER),
CONFIGURATION("configuration", PubSubNamespace.EVENT),
OPTIONS("options", PubSubNamespace.BASIC),
DEFAULT("default", PubSubNamespace.OWNER),
ITEMS("items", PubSubNamespace.BASIC),
ITEMS_EVENT("items", PubSubNamespace.EVENT),
ITEM("item", PubSubNamespace.BASIC),
ITEM_EVENT("item", PubSubNamespace.EVENT),
PUBLISH("publish", PubSubNamespace.BASIC),
PUBLISH_OPTIONS("publish-options", PubSubNamespace.BASIC),
PURGE_OWNER("purge", PubSubNamespace.OWNER),
PURGE_EVENT("purge", PubSubNamespace.EVENT),
RETRACT("retract", PubSubNamespace.BASIC),
AFFILIATIONS("affiliations", PubSubNamespace.BASIC),
SUBSCRIBE("subscribe", PubSubNamespace.BASIC),
SUBSCRIPTION("subscription", PubSubNamespace.BASIC),
SUBSCRIPTIONS("subscriptions", PubSubNamespace.BASIC),
UNSUBSCRIBE("unsubscribe", PubSubNamespace.BASIC);
CREATE("create", PubSubNamespace.basic),
DELETE("delete", PubSubNamespace.owner),
DELETE_EVENT("delete", PubSubNamespace.event),
CONFIGURE("configure", PubSubNamespace.basic),
CONFIGURE_OWNER("configure", PubSubNamespace.owner),
CONFIGURATION("configuration", PubSubNamespace.event),
OPTIONS("options", PubSubNamespace.basic),
DEFAULT("default", PubSubNamespace.owner),
ITEMS("items", PubSubNamespace.basic),
ITEMS_EVENT("items", PubSubNamespace.event),
ITEM("item", PubSubNamespace.basic),
ITEM_EVENT("item", PubSubNamespace.event),
PUBLISH("publish", PubSubNamespace.basic),
PUBLISH_OPTIONS("publish-options", PubSubNamespace.basic),
PURGE_OWNER("purge", PubSubNamespace.owner),
PURGE_EVENT("purge", PubSubNamespace.event),
RETRACT("retract", PubSubNamespace.basic),
AFFILIATIONS("affiliations", PubSubNamespace.basic),
AFFILIATIONS_OWNER("affiliations", PubSubNamespace.owner),
SUBSCRIBE("subscribe", PubSubNamespace.basic),
SUBSCRIPTION("subscription", PubSubNamespace.basic),
SUBSCRIPTIONS("subscriptions", PubSubNamespace.basic),
SUBSCRIPTIONS_OWNER("subscriptions", PubSubNamespace.owner),
UNSUBSCRIBE("unsubscribe", PubSubNamespace.basic);
private final String eName;
private final PubSubNamespace nSpace;

View File

@ -157,7 +157,7 @@ public final class PubSubManager extends Manager {
*/
public LeafNode createNode() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
PubSub reply = sendPubsubPacket(Type.set, new NodeExtension(PubSubElementType.CREATE), null);
NodeExtension elem = reply.getExtension("create", PubSubNamespace.BASIC.getXmlns());
NodeExtension elem = reply.getExtension("create", PubSubNamespace.basic.getXmlns());
LeafNode newNode = new LeafNode(this, elem.getNode());
nodeMap.put(newNode.getId(), newNode);
@ -195,7 +195,7 @@ public final class PubSubManager extends Manager {
* @throws InterruptedException
*/
public Node createNode(String nodeId, Form config) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
PubSub request = PubSub.createPubsubPacket(pubSubService, Type.set, new NodeExtension(PubSubElementType.CREATE, nodeId), null);
PubSub request = PubSub.createPubsubPacket(pubSubService, Type.set, new NodeExtension(PubSubElementType.CREATE, nodeId));
boolean isLeafNode = true;
if (config != null) {

View File

@ -50,7 +50,7 @@ public class RetractItem implements ExtensionElement {
@Override
public String getNamespace() {
return PubSubNamespace.EVENT.getXmlns();
return PubSubNamespace.event.getXmlns();
}
@Override

View File

@ -25,6 +25,26 @@ import java.util.List;
* @author Robin Collier
*/
public class SubscriptionsExtension extends NodeExtension {
public enum SubscriptionsNamespace {
basic(PubSubElementType.SUBSCRIPTIONS),
owner(PubSubElementType.SUBSCRIPTIONS_OWNER),
;
public final PubSubElementType type;
SubscriptionsNamespace(PubSubElementType type) {
this.type = type;
}
public static SubscriptionsNamespace fromXmlns(String xmlns) {
for (SubscriptionsNamespace subscriptionsNamespace : SubscriptionsNamespace.values()) {
if (subscriptionsNamespace.type.getNamespace().getXmlns().equals(xmlns)) {
return subscriptionsNamespace;
}
}
throw new IllegalArgumentException("Invalid Subscription namespace: " + xmlns);
}
}
protected List<Subscription> items = Collections.emptyList();
/**
@ -33,10 +53,7 @@ public class SubscriptionsExtension extends NodeExtension {
* @param subList The list of subscriptions
*/
public SubscriptionsExtension(List<Subscription> subList) {
super(PubSubElementType.SUBSCRIPTIONS);
if (subList != null)
items = subList;
this(SubscriptionsNamespace.basic, null, subList);
}
/**
@ -46,7 +63,19 @@ public class SubscriptionsExtension extends NodeExtension {
* @param subList The list of subscriptions
*/
public SubscriptionsExtension(String nodeId, List<Subscription> subList) {
super(PubSubElementType.SUBSCRIPTIONS, nodeId);
this(SubscriptionsNamespace.basic, nodeId, subList);
}
/**
* Subscriptions to the specified node.
*
* @param subscriptionsNamespace the namespace used by this element
* @param nodeId The node subscribed to
* @param subList The list of subscriptions
* @since 4.3
*/
public SubscriptionsExtension(SubscriptionsNamespace subscriptionsNamespace, String nodeId, List<Subscription> subList) {
super(subscriptionsNamespace.type, nodeId);
if (subList != null)
items = subList;

View File

@ -19,6 +19,7 @@ package org.jivesoftware.smackx.pubsub.packet;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.pubsub.NodeExtension;
import org.jivesoftware.smackx.pubsub.PubSubElementType;
import org.jxmpp.jid.Jid;
@ -43,7 +44,7 @@ public class PubSub extends IQ {
}
public PubSub(Jid to, Type type, PubSubNamespace ns) {
super(ELEMENT, (ns == null ? PubSubNamespace.BASIC : ns).getXmlns());
super(ELEMENT, (ns == null ? PubSubNamespace.basic : ns).getXmlns());
setTo(to);
setType(type);
}
@ -78,8 +79,8 @@ public class PubSub extends IQ {
return xml;
}
public static PubSub createPubsubPacket(Jid to, Type type, ExtensionElement extension, PubSubNamespace ns) {
PubSub pubSub = new PubSub(to, type, ns);
public static PubSub createPubsubPacket(Jid to, Type type, NodeExtension extension) {
PubSub pubSub = new PubSub(to, type, extension.getPubSubNamespace());
pubSub.addExtension(extension);
return pubSub;
}

View File

@ -16,8 +16,6 @@
*/
package org.jivesoftware.smackx.pubsub.packet;
import java.util.Locale;
/**
* Defines all the valid namespaces that are used with the {@link PubSub} packet
* as defined by the specification.
@ -25,10 +23,10 @@ import java.util.Locale;
* @author Robin Collier
*/
public enum PubSubNamespace {
BASIC(null),
ERROR("errors"),
EVENT("event"),
OWNER("owner");
basic(null),
error("errors"),
event("event"),
owner("owner");
private final String fragment;
private final String fullNamespace;
@ -54,10 +52,17 @@ public enum PubSubNamespace {
int index = ns.lastIndexOf('#');
if (index != -1) {
String suffix = ns.substring(ns.lastIndexOf('#') + 1);
return valueOf(suffix.toUpperCase(Locale.US));
// We found an extended namespace.
if (index > ns.length()) {
throw new IllegalArgumentException(ns + " is not a valid PubSub namespace");
}
String suffix = ns.substring(index + 1);
return valueOf(suffix);
}
else
return BASIC;
if (!PubSub.NAMESPACE.equals(ns)) {
throw new IllegalArgumentException(ns + " is not a valid PubSub namespace");
}
return basic;
}
}

View File

@ -21,7 +21,7 @@ import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smackx.pubsub.Affiliation;
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
import org.jivesoftware.smackx.pubsub.Affiliation.AffiliationNamespace;
import org.jxmpp.jid.BareJid;
import org.xmlpull.v1.XmlPullParser;
@ -39,6 +39,8 @@ public class AffiliationProvider extends ExtensionElementProvider<Affiliation> {
throws Exception {
String node = parser.getAttributeValue(null, "node");
BareJid jid = ParserUtils.getBareJidAttribute(parser);
String namespaceString = parser.getNamespace();
AffiliationNamespace namespace = AffiliationNamespace.fromXmlns(namespaceString);
String affiliationString = parser.getAttributeValue(null, "affiliation");
Affiliation.Type affiliationType = null;
@ -48,10 +50,9 @@ public class AffiliationProvider extends ExtensionElementProvider<Affiliation> {
Affiliation affiliation;
if (node != null && jid == null) {
// affiliationType may be empty
affiliation = new Affiliation(node, affiliationType);
affiliation = new Affiliation(node, affiliationType, namespace);
}
else if (node == null && jid != null) {
PubSubNamespace namespace = null; // TODO
affiliation = new Affiliation(jid, affiliationType, namespace);
}
else {

View File

@ -23,6 +23,7 @@ import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.provider.EmbeddedExtensionProvider;
import org.jivesoftware.smackx.pubsub.Affiliation;
import org.jivesoftware.smackx.pubsub.Affiliation.AffiliationNamespace;
import org.jivesoftware.smackx.pubsub.AffiliationsExtension;
/**
@ -34,7 +35,8 @@ import org.jivesoftware.smackx.pubsub.AffiliationsExtension;
@SuppressWarnings("unchecked")
@Override
protected AffiliationsExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends ExtensionElement> content) {
return new AffiliationsExtension((List<Affiliation>) content);
AffiliationNamespace affiliationsNamespace = AffiliationNamespace.fromXmlns(currentNamespace);
return new AffiliationsExtension(affiliationsNamespace, (List<Affiliation>) content);
}
}

View File

@ -35,6 +35,7 @@ import org.jivesoftware.smackx.pubsub.NodeExtension;
public class EventProvider extends EmbeddedExtensionProvider<EventElement> {
@Override
protected EventElement createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attMap, List<? extends ExtensionElement> content) {
// TODO: Shouldn't be an embedded extension provider.
return new EventElement(EventElementType.valueOf(content.get(0).getElementName()), (NodeExtension) content.get(0));
}
}

View File

@ -22,6 +22,7 @@ import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smackx.pubsub.Item;
import org.jivesoftware.smackx.pubsub.Item.ItemNamespace;
import org.jivesoftware.smackx.pubsub.PayloadItem;
import org.jivesoftware.smackx.pubsub.SimplePayload;
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
@ -29,8 +30,8 @@ import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
import org.xmlpull.v1.XmlPullParser;
/**
* Parses an <b>item</b> element as is defined in both the {@link PubSubNamespace#BASIC} and
* {@link PubSubNamespace#EVENT} namespaces. To parse the item contents, it will use whatever
* Parses an <b>item</b> element as is defined in both the {@link PubSubNamespace#basic} and
* {@link PubSubNamespace#event} namespaces. To parse the item contents, it will use whatever
* {@link ExtensionElementProvider} is registered in <b>smack.providers</b> for its element name and namespace. If no
* provider is registered, it will return a {@link SimplePayload}.
*
@ -42,11 +43,13 @@ public class ItemProvider extends ExtensionElementProvider<Item> {
throws Exception {
String id = parser.getAttributeValue(null, "id");
String node = parser.getAttributeValue(null, "node");
String xmlns = parser.getNamespace();
ItemNamespace itemNamespace = ItemNamespace.fromXmlns(xmlns);
int tag = parser.next();
if (tag == XmlPullParser.END_TAG) {
return new Item(id, node);
return new Item(itemNamespace, id, node);
}
else {
String payloadElemName = parser.getName();
@ -54,11 +57,12 @@ public class ItemProvider extends ExtensionElementProvider<Item> {
final ExtensionElementProvider<ExtensionElement> extensionProvider = ProviderManager.getExtensionProvider(payloadElemName, payloadNS);
if (extensionProvider == null) {
// TODO: Should we use StandardExtensionElement in this case? And probably remove SimplePayload all together.
CharSequence payloadText = PacketParserUtils.parseElement(parser, true);
return new PayloadItem<>(id, node, new SimplePayload(payloadElemName, payloadNS, payloadText));
return new PayloadItem<>(itemNamespace, id, node, new SimplePayload(payloadElemName, payloadNS, payloadText));
}
else {
return new PayloadItem<>(id, node, extensionProvider.parse(parser));
return new PayloadItem<>(itemNamespace, id, node, extensionProvider.parse(parser));
}
}
}

View File

@ -24,6 +24,7 @@ import org.jivesoftware.smack.provider.EmbeddedExtensionProvider;
import org.jivesoftware.smackx.pubsub.Subscription;
import org.jivesoftware.smackx.pubsub.SubscriptionsExtension;
import org.jivesoftware.smackx.pubsub.SubscriptionsExtension.SubscriptionsNamespace;
/**
* Parses the <b>subscriptions</b> element out of the PubSub IQ message from
@ -35,7 +36,9 @@ public class SubscriptionsProvider extends EmbeddedExtensionProvider<Subscriptio
@SuppressWarnings("unchecked")
@Override
protected SubscriptionsExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends ExtensionElement> content) {
return new SubscriptionsExtension(attributeMap.get("node"), (List<Subscription>) content);
SubscriptionsNamespace subscriptionsNamespace = SubscriptionsNamespace.fromXmlns(currentNamespace);
String nodeId = attributeMap.get("node");
return new SubscriptionsExtension(subscriptionsNamespace, nodeId, (List<Subscription>) content);
}
}

View File

@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue;
import org.jivesoftware.smack.ThreadedDummyConnection;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.util.PacketParserUtils;
@ -60,16 +61,16 @@ public class ItemValidationTest extends InitExtensions {
@Test
public void verifyBasicItem() throws Exception {
Item simpleItem = new Item();
String simpleCtrl = "<item />";
assertXMLEqual(simpleCtrl, simpleItem.toXML());
String simpleCtrl = "<item xmlns='http://jabber.org/protocol/pubsub' />";
assertXMLEqual(simpleCtrl, simpleItem.toXML().toString());
Item idItem = new Item("uniqueid");
String idCtrl = "<item id='uniqueid'/>";
assertXMLEqual(idCtrl, idItem.toXML());
String idCtrl = "<item xmlns='http://jabber.org/protocol/pubsub' id='uniqueid'/>";
assertXMLEqual(idCtrl, idItem.toXML().toString());
Item itemWithNodeId = new Item("testId", "testNode");
String nodeIdCtrl = "<item id='testId' node='testNode' />";
assertXMLEqual(nodeIdCtrl, itemWithNodeId.toXML());
String nodeIdCtrl = "<item xmlns='http://jabber.org/protocol/pubsub' id='testId' node='testNode' />";
assertXMLEqual(nodeIdCtrl, itemWithNodeId.toXML().toString());
}
@Test
@ -77,16 +78,16 @@ public class ItemValidationTest extends InitExtensions {
SimplePayload payload = new SimplePayload(null, null, "<data>This is the payload</data>");
PayloadItem<SimplePayload> simpleItem = new PayloadItem<>(payload);
String simpleCtrl = "<item>" + payload.toXML() + "</item>";
assertXMLEqual(simpleCtrl, simpleItem.toXML());
String simpleCtrl = "<item xmlns='http://jabber.org/protocol/pubsub'>" + payload.toXML() + "</item>";
assertXMLEqual(simpleCtrl, simpleItem.toXML().toString());
PayloadItem<SimplePayload> idItem = new PayloadItem<>("uniqueid", payload);
String idCtrl = "<item id='uniqueid'>" + payload.toXML() + "</item>";
assertXMLEqual(idCtrl, idItem.toXML());
String idCtrl = "<item xmlns='http://jabber.org/protocol/pubsub' id='uniqueid'>" + payload.toXML() + "</item>";
assertXMLEqual(idCtrl, idItem.toXML().toString());
PayloadItem<SimplePayload> itemWithNodeId = new PayloadItem<>("testId", "testNode", payload);
String nodeIdCtrl = "<item id='testId' node='testNode'>" + payload.toXML() + "</item>";
assertXMLEqual(nodeIdCtrl, itemWithNodeId.toXML());
String nodeIdCtrl = "<item xmlns='http://jabber.org/protocol/pubsub' id='testId' node='testNode'>" + payload.toXML() + "</item>";
assertXMLEqual(nodeIdCtrl, itemWithNodeId.toXML().toString());
}
@Test
@ -101,7 +102,7 @@ public class ItemValidationTest extends InitExtensions {
"</message>");
Stanza message = PacketParserUtils.parseMessage(parser);
ExtensionElement eventExt = message.getExtension(PubSubNamespace.EVENT.getXmlns());
ExtensionElement eventExt = message.getExtension(PubSubNamespace.event.getXmlns());
assertTrue(eventExt instanceof EventElement);
EventElement event = (EventElement) eventExt;
@ -110,7 +111,7 @@ public class ItemValidationTest extends InitExtensions {
assertTrue(event.getExtensions().get(0) instanceof ItemsExtension);
assertEquals(1, ((ItemsExtension) event.getExtensions().get(0)).items.size());
ExtensionElement itemExt = ((ItemsExtension) event.getExtensions().get(0)).items.get(0);
NamedElement itemExt = ((ItemsExtension) event.getExtensions().get(0)).items.get(0);
assertTrue(itemExt instanceof Item);
assertEquals("testid1", ((Item) itemExt).getId());
}
@ -131,9 +132,9 @@ public class ItemValidationTest extends InitExtensions {
"</message>");
Stanza message = PacketParserUtils.parseMessage(parser);
ExtensionElement eventExt = message.getExtension(PubSubNamespace.EVENT.getXmlns());
ExtensionElement eventExt = message.getExtension(PubSubNamespace.event.getXmlns());
EventElement event = (EventElement) eventExt;
ExtensionElement itemExt = ((ItemsExtension) event.getExtensions().get(0)).items.get(0);
NamedElement itemExt = ((ItemsExtension) event.getExtensions().get(0)).items.get(0);
assertTrue(itemExt instanceof PayloadItem<?>);
PayloadItem<?> item = (PayloadItem<?>) itemExt;
@ -177,9 +178,9 @@ public class ItemValidationTest extends InitExtensions {
"</message>");
Stanza message = PacketParserUtils.parseMessage(parser);
ExtensionElement eventExt = message.getExtension(PubSubNamespace.EVENT.getXmlns());
ExtensionElement eventExt = message.getExtension(PubSubNamespace.event.getXmlns());
EventElement event = (EventElement) eventExt;
ExtensionElement itemExt = ((ItemsExtension) event.getExtensions().get(0)).items.get(0);
NamedElement itemExt = ((ItemsExtension) event.getExtensions().get(0)).items.get(0);
assertTrue(itemExt instanceof PayloadItem<?>);
PayloadItem<?> item = (PayloadItem<?>) itemExt;
@ -209,7 +210,7 @@ public class ItemValidationTest extends InitExtensions {
"</message>");
Stanza message = PacketParserUtils.parseMessage(parser);
ExtensionElement eventExt = message.getExtension(PubSubNamespace.EVENT.getXmlns());
ExtensionElement eventExt = message.getExtension(PubSubNamespace.event.getXmlns());
assertTrue(eventExt instanceof EventElement);
EventElement event = (EventElement) eventExt;
@ -218,7 +219,7 @@ public class ItemValidationTest extends InitExtensions {
assertTrue(event.getExtensions().get(0) instanceof ItemsExtension);
assertEquals(1, ((ItemsExtension) event.getExtensions().get(0)).items.size());
ExtensionElement itemExt = ((ItemsExtension) event.getExtensions().get(0)).items.get(0);
NamedElement itemExt = ((ItemsExtension) event.getExtensions().get(0)).items.get(0);
assertTrue(itemExt instanceof PayloadItem<?>);
PayloadItem<?> item = (PayloadItem<?>) itemExt;

View File

@ -1,6 +1,6 @@
/**
*
* Copyright 2018 Timothy Pitt
* Copyright 2018 Timothy Pitt, Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -24,17 +24,25 @@ import java.util.List;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.ThreadedDummyConnection;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smackx.pubsub.packet.PubSub;
import org.jivesoftware.smackx.pubsub.Affiliation.AffiliationNamespace;
import org.jivesoftware.smackx.pubsub.packet.PubSub;
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
import org.jivesoftware.util.ConnectionUtils;
import org.jivesoftware.util.Protocol;
import org.junit.Test;
import org.jxmpp.jid.JidTestUtil;
import org.jxmpp.jid.impl.JidCreate;
import org.xmlpull.v1.XmlPullParser;
public class PubSubNodeTest {
public class PubSubNodeTest extends SmackTestSuite {
@Test
public void modifySubscriptionsAsOwnerTest() throws InterruptedException, SmackException, IOException, XMPPException, Exception {
@ -55,7 +63,7 @@ public class PubSubNodeTest {
XmlPullParser parser = TestUtils.getIQParser(request.toXML().toString());
PubSub pubsubResult = (PubSub) PacketParserUtils.parseIQ(parser);
SubscriptionsExtension subElem = pubsubResult.getExtension(PubSubElementType.SUBSCRIPTIONS);
SubscriptionsExtension subElem = pubsubResult.getExtension(PubSubElementType.SUBSCRIPTIONS_OWNER);
List<Subscription> subscriptions = subElem.getSubscriptions();
assertEquals(2, subscriptions.size());
@ -67,4 +75,36 @@ public class PubSubNodeTest {
assertEquals("juliet@capulet.org", sub2.getJid().toString());
assertEquals(Subscription.State.none, sub2.getState());
}
@Test
public void getAffiliationsAsOwnerTest() throws InterruptedException, SmackException, IOException, XMPPException, Exception {
Protocol protocol = new Protocol();
XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, JidTestUtil.FULL_JID_1_RESOURCE_1);
PubSubManager mgr = new PubSubManager(connection, JidTestUtil.PUBSUB_EXAMPLE_ORG);
Node testNode = new LeafNode(mgr, "princely_musings");
List<Affiliation> affiliations = Arrays.asList(
new Affiliation(JidTestUtil.BARE_JID_1, Affiliation.Type.member),
new Affiliation(JidTestUtil.BARE_JID_2, Affiliation.Type.publisher)
);
AffiliationsExtension affiliationsExtension = new AffiliationsExtension(AffiliationNamespace.owner, affiliations);
PubSub response = new PubSub(JidTestUtil.PUBSUB_EXAMPLE_ORG, Type.result, PubSubNamespace.owner);
response.addExtension(affiliationsExtension);
protocol.addResponse(response);
List<Affiliation> returnedAffiliations = testNode.getAffiliationsAsOwner();
PubSub request = (PubSub) protocol.getRequests().get(0);
assertEquals("http://jabber.org/protocol/pubsub#owner", request.getChildElementNamespace());
assertEquals("pubsub", request.getChildElementName());
Affiliation affiliationOne = returnedAffiliations.get(0);
assertEquals(affiliationOne.getJid(), JidTestUtil.BARE_JID_1);
assertEquals(affiliationOne.getAffiliation(), Affiliation.Type.member);
Affiliation affiliationTwo = returnedAffiliations.get(1);
assertEquals(affiliationTwo.getJid(), JidTestUtil.BARE_JID_2);
assertEquals(affiliationTwo.getAffiliation(), Affiliation.Type.publisher);
}
}

View File

@ -50,7 +50,7 @@ public class PubSubProviderTest {
// @formatter:on
XmlPullParser parser = TestUtils.getIQParser(resultStanza);
PubSub pubsubResult = (PubSub) PacketParserUtils.parseIQ(parser);
SubscriptionsExtension subElem = pubsubResult.getExtension(PubSubElementType.SUBSCRIPTIONS);
SubscriptionsExtension subElem = pubsubResult.getExtension(PubSubElementType.SUBSCRIPTIONS_OWNER);
List<Subscription> subscriptions = subElem.getSubscriptions();
assertEquals(2, subscriptions.size());

View File

@ -39,6 +39,7 @@ import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.util.Async;
import org.jivesoftware.smackx.carbons.CarbonManager;
@ -776,7 +777,7 @@ public final class OmemoManager extends Manager {
continue;
}
for (ExtensionElement item : ((ItemsExtension) items).getItems()) {
for (NamedElement item : ((ItemsExtension) items).getItems()) {
if (!(item instanceof PayloadItem<?>)) {
continue;
}