mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-26 14:02:06 +01:00
SMACK-272 Add support for XEP-0060 (pubsub)
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@11346 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
92ba2d7f33
commit
f7a1c750ad
73 changed files with 7214 additions and 0 deletions
|
@ -124,6 +124,12 @@
|
||||||
<className>org.jivesoftware.smackx.provider.DelayInformationProvider</className>
|
<className>org.jivesoftware.smackx.provider.DelayInformationProvider</className>
|
||||||
</extensionProvider>
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>delay</elementName>
|
||||||
|
<namespace>urn:xmpp:delay</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.provider.DelayInfoProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
<!-- Version -->
|
<!-- Version -->
|
||||||
<iqProvider>
|
<iqProvider>
|
||||||
<elementName>query</elementName>
|
<elementName>query</elementName>
|
||||||
|
@ -472,4 +478,140 @@
|
||||||
<className>org.jivesoftware.smackx.workgroup.packet.RoomTransfer$Provider</className>
|
<className>org.jivesoftware.smackx.workgroup.packet.RoomTransfer$Provider</className>
|
||||||
</extensionProvider>
|
</extensionProvider>
|
||||||
|
|
||||||
|
<!-- SHIM -->
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>headers</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/shim</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.provider.HeadersProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>header</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/shim</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.provider.HeaderProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<!-- XEP-0060 pubsub -->
|
||||||
|
<iqProvider>
|
||||||
|
<elementName>pubsub</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.PubSubProvider</className>
|
||||||
|
</iqProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>create</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.SimpleNodeProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>items</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.ItemsProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>item</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.ItemProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>subscriptions</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.SubscriptionsProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>subscription</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.SubscriptionProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>affiliations</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.AffiliationsProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>affiliation</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.AffiliationProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>options</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.provider.FormNodeProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<!-- XEP-0060 pubsub#owner -->
|
||||||
|
<iqProvider>
|
||||||
|
<elementName>pubsub</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#owner</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.PubSubProvider</className>
|
||||||
|
</iqProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>configure</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#owner</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.provider.FormNodeProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>default</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#owner</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.provider.FormNodeProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<!-- XEP-0060 pubsub#event -->
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>event</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#event</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.EventProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>configuration</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#event</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.ConfigEventProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>delete</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#event</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.SimpleNodeProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>options</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#event</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.provider.FormNodeProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>items</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#event</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.ItemsProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>item</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#event</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.ItemProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>retract</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#event</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.RetractEventProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
|
<extensionProvider>
|
||||||
|
<elementName>purge</elementName>
|
||||||
|
<namespace>http://jabber.org/protocol/pubsub#event</namespace>
|
||||||
|
<className>org.jivesoftware.smackx.pubsub.provider.SimpleNodeProvider</className>
|
||||||
|
</extensionProvider>
|
||||||
|
|
||||||
</smackProviders>
|
</smackProviders>
|
|
@ -70,6 +70,11 @@
|
||||||
<td><a href="http://www.xmpp.org/extensions/xep-0096.html">XEP-0096</a></td>
|
<td><a href="http://www.xmpp.org/extensions/xep-0096.html">XEP-0096</a></td>
|
||||||
<td>Transfer files between two users over XMPP.</td>
|
<td>Transfer files between two users over XMPP.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="pubsub.html">PubSub</a></td>
|
||||||
|
<td><a href="http://www.xmpp.org/extensions/xep-0060.html">XEP-0060</a></td>
|
||||||
|
<td>Generic publish and subscribe functionality.</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -21,6 +21,7 @@
|
||||||
<a href="invitation.html">Group Chat Invitations</a><br>
|
<a href="invitation.html">Group Chat Invitations</a><br>
|
||||||
<a href="disco.html">Service Discovery</a><br>
|
<a href="disco.html">Service Discovery</a><br>
|
||||||
<a href="filetransfer.html">File Transfer</a><br>
|
<a href="filetransfer.html">File Transfer</a><br>
|
||||||
|
<a href="pubsub.html">PubSub</a><br>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
38
source/org/jivesoftware/smackx/pubsub/AccessModel.java
Normal file
38
source/org/jivesoftware/smackx/pubsub/AccessModel.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This enumeration represents the access models for the pubsub node
|
||||||
|
* as defined in the pubsub specification section <a href="http://xmpp.org/extensions/xep-0060.html#registrar-formtypes-config">16.4.3</a>
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum AccessModel
|
||||||
|
{
|
||||||
|
/** Anyone may subscribe and retrieve items */
|
||||||
|
open,
|
||||||
|
|
||||||
|
/** Subscription request must be approved and only subscribers may retrieve items */
|
||||||
|
authorize,
|
||||||
|
|
||||||
|
/** Anyone with a presence subscription of both or from may subscribe and retrieve items */
|
||||||
|
presence,
|
||||||
|
|
||||||
|
/** Anyone in the specified roster group(s) may subscribe and retrieve items */
|
||||||
|
roster,
|
||||||
|
|
||||||
|
/** Only those on a whitelist may subscribe and retrieve items */
|
||||||
|
whitelist;
|
||||||
|
}
|
90
source/org/jivesoftware/smackx/pubsub/Affiliation.java
Normal file
90
source/org/jivesoftware/smackx/pubsub/Affiliation.java
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a affiliation between a user and a node, where the {@link #type} defines
|
||||||
|
* the type of affiliation.
|
||||||
|
*
|
||||||
|
* Affiliations are retrieved from the {@link PubSubManager#getAffiliations()} method, which
|
||||||
|
* gets affiliations for the calling user, based on the identity that is associated with
|
||||||
|
* the {@link XMPPConnection}.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class Affiliation implements PacketExtension
|
||||||
|
{
|
||||||
|
protected String node;
|
||||||
|
protected Type type;
|
||||||
|
|
||||||
|
public enum Type
|
||||||
|
{
|
||||||
|
member, none, outcast, owner, publisher
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an affiliation.
|
||||||
|
*
|
||||||
|
* @param nodeId The node the user is affiliated with.
|
||||||
|
* @param affiliation The type of affiliation.
|
||||||
|
*/
|
||||||
|
public Affiliation(String nodeId, Type affiliation)
|
||||||
|
{
|
||||||
|
node = nodeId;
|
||||||
|
type = affiliation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNodeId()
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getType()
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElementName()
|
||||||
|
{
|
||||||
|
return "subscription";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespace()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<");
|
||||||
|
builder.append(getElementName());
|
||||||
|
appendAttribute(builder, "node", node);
|
||||||
|
appendAttribute(builder, "affiliation", type.toString());
|
||||||
|
|
||||||
|
builder.append("/>");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendAttribute(StringBuilder builder, String att, String value)
|
||||||
|
{
|
||||||
|
builder.append(" ");
|
||||||
|
builder.append(att);
|
||||||
|
builder.append("='");
|
||||||
|
builder.append(value);
|
||||||
|
builder.append("'");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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>.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class AffiliationsExtension extends NodeExtension
|
||||||
|
{
|
||||||
|
protected List<Affiliation> items = Collections.EMPTY_LIST;
|
||||||
|
|
||||||
|
public AffiliationsExtension()
|
||||||
|
{
|
||||||
|
super(PubSubElementType.AFFILIATIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AffiliationsExtension(List<Affiliation> subList)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.AFFILIATIONS);
|
||||||
|
items = subList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Affiliation> getAffiliations()
|
||||||
|
{
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.size() == 0))
|
||||||
|
{
|
||||||
|
return super.toXML();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<");
|
||||||
|
builder.append(getElementName());
|
||||||
|
builder.append(">");
|
||||||
|
|
||||||
|
for (Affiliation item : items)
|
||||||
|
{
|
||||||
|
builder.append(item.toXML());
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append("</");
|
||||||
|
builder.append(getElementName());
|
||||||
|
builder.append(">");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This enumeration represents the children association policy for associating leaf nodes
|
||||||
|
* with collection nodes as defined in the pubsub specification section <a href="http://xmpp.org/extensions/xep-0060.html#registrar-formtypes-config">16.4.3</a>
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum ChildrenAssociationPolicy
|
||||||
|
{
|
||||||
|
/** Anyone may associate leaf nodes with the collection */
|
||||||
|
all,
|
||||||
|
|
||||||
|
/** Only collection node owners may associate leaf nodes with the collection. */
|
||||||
|
owners,
|
||||||
|
|
||||||
|
/** Only those on a whitelist may associate leaf nodes with the collection. */
|
||||||
|
whitelist;
|
||||||
|
}
|
15
source/org/jivesoftware/smackx/pubsub/CollectionNode.java
Normal file
15
source/org/jivesoftware/smackx/pubsub/CollectionNode.java
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-07-13
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
|
||||||
|
public class CollectionNode extends Node
|
||||||
|
{
|
||||||
|
CollectionNode(XMPPConnection connection, String nodeId)
|
||||||
|
{
|
||||||
|
super(connection, nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the <b>configuration</b> element of a pubsub message event which
|
||||||
|
* associates a configuration form to the node which was configured. The form
|
||||||
|
* contains the current node configuration.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class ConfigurationEvent extends NodeExtension implements EmbeddedPacketExtension
|
||||||
|
{
|
||||||
|
private ConfigureForm form;
|
||||||
|
|
||||||
|
public ConfigurationEvent(String nodeId)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.CONFIGURATION, nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigurationEvent(String nodeId, ConfigureForm configForm)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.CONFIGURATION, nodeId);
|
||||||
|
form = configForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigureForm getConfiguration()
|
||||||
|
{
|
||||||
|
return form;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PacketExtension> getExtensions()
|
||||||
|
{
|
||||||
|
if (getConfiguration() == null)
|
||||||
|
return Collections.EMPTY_LIST;
|
||||||
|
else
|
||||||
|
return Arrays.asList(((PacketExtension)getConfiguration().getDataFormToSend()));
|
||||||
|
}
|
||||||
|
}
|
707
source/org/jivesoftware/smackx/pubsub/ConfigureForm.java
Normal file
707
source/org/jivesoftware/smackx/pubsub/ConfigureForm.java
Normal file
|
@ -0,0 +1,707 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.Form;
|
||||||
|
import org.jivesoftware.smackx.FormField;
|
||||||
|
import org.jivesoftware.smackx.packet.DataForm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A decorator for a {@link Form} to easily enable reading and updating
|
||||||
|
* of node configuration. All operations read or update the underlying {@link DataForm}.
|
||||||
|
*
|
||||||
|
* <p>Unlike the {@link Form}.setAnswer(XXX)} methods, which throw an exception if the field does not
|
||||||
|
* exist, all <b>ConfigureForm.setXXX</b> methods will create the field in the wrapped form
|
||||||
|
* if it does not already exist.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class ConfigureForm extends Form
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a decorator from an existing {@link DataForm} that has been
|
||||||
|
* retrieved from parsing a node configuration request.
|
||||||
|
*
|
||||||
|
* @param configDataForm
|
||||||
|
*/
|
||||||
|
public ConfigureForm(DataForm configDataForm)
|
||||||
|
{
|
||||||
|
super(configDataForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a decorator from an existing {@link Form} for node configuration.
|
||||||
|
* Typically, this can be used to create a decorator for an answer form
|
||||||
|
* by using the result of {@link #createAnswerForm()} as the input parameter.
|
||||||
|
*
|
||||||
|
* @param nodeConfigForm
|
||||||
|
*/
|
||||||
|
public ConfigureForm(Form nodeConfigForm)
|
||||||
|
{
|
||||||
|
super(nodeConfigForm.getDataFormToSend());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new form for configuring a node. This would typically only be used
|
||||||
|
* when creating and configuring a node at the same time via {@link PubSubManager#createNode(String, Form)}, since
|
||||||
|
* configuration of an existing node is typically accomplished by calling {@link LeafNode#getNodeConfiguration()} and
|
||||||
|
* using the resulting form to create a answer form. See {@link #ConfigureForm(Form)}.
|
||||||
|
* @param formType
|
||||||
|
*/
|
||||||
|
public ConfigureForm(FormType formType)
|
||||||
|
{
|
||||||
|
super(formType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the currently configured {@link AccessModel}, null if it is not set.
|
||||||
|
*
|
||||||
|
* @return The current {@link AccessModel}
|
||||||
|
*/
|
||||||
|
public AccessModel getAccessModel()
|
||||||
|
{
|
||||||
|
String value = getFieldValue(ConfigureNodeFields.access_model);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return AccessModel.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of access model.
|
||||||
|
*
|
||||||
|
* @param accessModel
|
||||||
|
*/
|
||||||
|
public void setAccessModel(AccessModel accessModel)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.access_model, FormField.TYPE_LIST_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.access_model.getFieldName(), getListSingle(accessModel.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the URL of an XSL transformation which can be applied to payloads in order to
|
||||||
|
* generate an appropriate message body element.
|
||||||
|
*
|
||||||
|
* @return URL to an XSL
|
||||||
|
*/
|
||||||
|
public String getBodyXSLT()
|
||||||
|
{
|
||||||
|
return getFieldValue(ConfigureNodeFields.body_xslt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the URL of an XSL transformation which can be applied to payloads in order to
|
||||||
|
* generate an appropriate message body element.
|
||||||
|
*
|
||||||
|
* @param bodyXslt The URL of an XSL
|
||||||
|
*/
|
||||||
|
public void setBodyXSLT(String bodyXslt)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.body_xslt, FormField.TYPE_TEXT_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.body_xslt.getFieldName(), bodyXslt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id's of the child nodes associated with a collection node (both leaf and collection).
|
||||||
|
*
|
||||||
|
* @return Iterator over the list of child nodes.
|
||||||
|
*/
|
||||||
|
public Iterator<String> getChildren()
|
||||||
|
{
|
||||||
|
return getFieldValues(ConfigureNodeFields.children);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the list of child node ids that are associated with a collection node.
|
||||||
|
*
|
||||||
|
* @param children
|
||||||
|
*/
|
||||||
|
public void setChildren(List<String> children)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.children, FormField.TYPE_TEXT_MULTI);
|
||||||
|
setAnswer(ConfigureNodeFields.children.getFieldName(), children);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the policy that determines who may associate children with the node.
|
||||||
|
*
|
||||||
|
* @return The current policy
|
||||||
|
*/
|
||||||
|
public ChildrenAssociationPolicy getChildrenAssociationPolicy()
|
||||||
|
{
|
||||||
|
String value = getFieldValue(ConfigureNodeFields.children_association_policy);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return ChildrenAssociationPolicy.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the policy that determines who may associate children with the node.
|
||||||
|
*
|
||||||
|
* @param policy The policy being set
|
||||||
|
*/
|
||||||
|
public void setChildrenAssociationPolicy(ChildrenAssociationPolicy policy)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.children_association_policy, FormField.TYPE_LIST_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.children_association_policy.getFieldName(), policy.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator of JID's that are on the whitelist that determines who can associate child nodes
|
||||||
|
* with the collection node. This is only relevant if {@link #getChildrenAssociationPolicy()} is set to
|
||||||
|
* {@link ChildrenAssociationPolicy#whitelist}.
|
||||||
|
*
|
||||||
|
* @return Iterator over whitelist
|
||||||
|
*/
|
||||||
|
public Iterator<String> getChildrenAssociationWhitelist()
|
||||||
|
{
|
||||||
|
return getFieldValues(ConfigureNodeFields.children_association_whitelist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the JID's in the whitelist of users that can associate child nodes with the collection
|
||||||
|
* node. This is only relevant if {@link #getChildrenAssociationPolicy()} is set to
|
||||||
|
* {@link ChildrenAssociationPolicy#whitelist}.
|
||||||
|
*
|
||||||
|
* @param whitelist The list of JID's
|
||||||
|
*/
|
||||||
|
public void setChildrenAssociationWhitelist(List<String> whitelist)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.children_association_whitelist, FormField.TYPE_JID_MULTI);
|
||||||
|
setAnswer(ConfigureNodeFields.children_association_whitelist.getFieldName(), whitelist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the maximum number of child nodes that can be associated with the collection node.
|
||||||
|
*
|
||||||
|
* @return The maximum number of child nodes
|
||||||
|
*/
|
||||||
|
public int getChildrenMax()
|
||||||
|
{
|
||||||
|
return Integer.parseInt(getFieldValue(ConfigureNodeFields.children_max));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum number of child nodes that can be associated with a collection node.
|
||||||
|
*
|
||||||
|
* @param max The maximum number of child nodes.
|
||||||
|
*/
|
||||||
|
public void setChildrenMax(int max)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.children_max, FormField.TYPE_TEXT_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.children_max.getFieldName(), max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the collection node which the node is affiliated with.
|
||||||
|
*
|
||||||
|
* @return The collection node id
|
||||||
|
*/
|
||||||
|
public String getCollection()
|
||||||
|
{
|
||||||
|
return getFieldValue(ConfigureNodeFields.collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the collection node which the node is affiliated with.
|
||||||
|
*
|
||||||
|
* @param collection The node id of the collection node
|
||||||
|
*/
|
||||||
|
public void setCollection(String collection)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.collection, FormField.TYPE_TEXT_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.collection.getFieldName(), collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the URL of an XSL transformation which can be applied to the payload
|
||||||
|
* format in order to generate a valid Data Forms result that the client could
|
||||||
|
* display using a generic Data Forms rendering engine.
|
||||||
|
*
|
||||||
|
* @return The URL of an XSL transformation
|
||||||
|
*/
|
||||||
|
public String getDataformXSLT()
|
||||||
|
{
|
||||||
|
return getFieldValue(ConfigureNodeFields.dataform_xslt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the URL of an XSL transformation which can be applied to the payload
|
||||||
|
* format in order to generate a valid Data Forms result that the client could
|
||||||
|
* display using a generic Data Forms rendering engine.
|
||||||
|
*
|
||||||
|
* @param url The URL of an XSL transformation
|
||||||
|
*/
|
||||||
|
public void setDataformXSLT(String url)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.dataform_xslt, FormField.TYPE_TEXT_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.dataform_xslt.getFieldName(), url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the node deliver payloads with event notifications.
|
||||||
|
*
|
||||||
|
* @return true if it does, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isDeliverPayloads()
|
||||||
|
{
|
||||||
|
return parseBoolean(getFieldValue(ConfigureNodeFields.deliver_payloads));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the node will deliver payloads with event notifications.
|
||||||
|
*
|
||||||
|
* @param deliver true if the payload will be delivered, false otherwise
|
||||||
|
*/
|
||||||
|
public void setDeliverPayloads(boolean deliver)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.deliver_payloads, FormField.TYPE_BOOLEAN);
|
||||||
|
setAnswer(ConfigureNodeFields.deliver_payloads.getFieldName(), deliver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines who should get replies to items
|
||||||
|
*
|
||||||
|
* @return Who should get the reply
|
||||||
|
*/
|
||||||
|
public ItemReply getItemReply()
|
||||||
|
{
|
||||||
|
String value = getFieldValue(ConfigureNodeFields.itemreply);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return ItemReply.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets who should get the replies to items
|
||||||
|
*
|
||||||
|
* @param reply Defines who should get the reply
|
||||||
|
*/
|
||||||
|
public void setItemReply(ItemReply reply)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.itemreply, FormField.TYPE_LIST_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.itemreply.getFieldName(), getListSingle(reply.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the maximum number of items to persisted to this node if {@link #isPersistItems()} is
|
||||||
|
* true.
|
||||||
|
*
|
||||||
|
* @return The maximum number of items to persist
|
||||||
|
*/
|
||||||
|
public int getMaxItems()
|
||||||
|
{
|
||||||
|
return Integer.parseInt(getFieldValue(ConfigureNodeFields.max_items));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum number of items to persisted to this node if {@link #isPersistItems()} is
|
||||||
|
* true.
|
||||||
|
*
|
||||||
|
* @param max The maximum number of items to persist
|
||||||
|
*/
|
||||||
|
public void setMaxItems(int max)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.max_items, FormField.TYPE_TEXT_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.max_items.getFieldName(), max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the maximum payload size in bytes.
|
||||||
|
*
|
||||||
|
* @return The maximum payload size
|
||||||
|
*/
|
||||||
|
public int getMaxPayloadSize()
|
||||||
|
{
|
||||||
|
return Integer.parseInt(getFieldValue(ConfigureNodeFields.max_payload_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum payload size in bytes
|
||||||
|
*
|
||||||
|
* @param max The maximum payload size
|
||||||
|
*/
|
||||||
|
public void setMaxPayloadSize(int max)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.max_payload_size, FormField.TYPE_TEXT_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.max_payload_size.getFieldName(), max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the node type
|
||||||
|
*
|
||||||
|
* @return The node type
|
||||||
|
*/
|
||||||
|
public NodeType getNodeType()
|
||||||
|
{
|
||||||
|
String value = getFieldValue(ConfigureNodeFields.node_type);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return NodeType.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the node type
|
||||||
|
*
|
||||||
|
* @param type The node type
|
||||||
|
*/
|
||||||
|
public void setNodeType(NodeType type)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.node_type, FormField.TYPE_LIST_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.node_type.getFieldName(), getListSingle(type.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if subscribers should be notified when the configuration changes.
|
||||||
|
*
|
||||||
|
* @return true if they should be notified, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isNotifyConfig()
|
||||||
|
{
|
||||||
|
return parseBoolean(getFieldValue(ConfigureNodeFields.notify_config));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether subscribers should be notified when the configuration changes.
|
||||||
|
*
|
||||||
|
* @param notify true if subscribers should be notified, false otherwise
|
||||||
|
*/
|
||||||
|
public void setNotifyConfig(boolean notify)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.notify_config, FormField.TYPE_BOOLEAN);
|
||||||
|
setAnswer(ConfigureNodeFields.notify_config.getFieldName(), notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether subscribers should be notified when the node is deleted.
|
||||||
|
*
|
||||||
|
* @return true if subscribers should be notified, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isNotifyDelete()
|
||||||
|
{
|
||||||
|
return parseBoolean(getFieldValue(ConfigureNodeFields.notify_delete));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether subscribers should be notified when the node is deleted.
|
||||||
|
*
|
||||||
|
* @param notify true if subscribers should be notified, false otherwise
|
||||||
|
*/
|
||||||
|
public void setNotifyDelete(boolean notify)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.notify_delete, FormField.TYPE_BOOLEAN);
|
||||||
|
setAnswer(ConfigureNodeFields.notify_delete.getFieldName(), notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether subscribers should be notified when items are deleted
|
||||||
|
* from the node.
|
||||||
|
*
|
||||||
|
* @return true if subscribers should be notified, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isNotifyRetract()
|
||||||
|
{
|
||||||
|
return parseBoolean(getFieldValue(ConfigureNodeFields.notify_retract));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether subscribers should be notified when items are deleted
|
||||||
|
* from the node.
|
||||||
|
*
|
||||||
|
* @param notify true if subscribers should be notified, false otherwise
|
||||||
|
*/
|
||||||
|
public void setNotifyRetract(boolean notify)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.notify_retract, FormField.TYPE_BOOLEAN);
|
||||||
|
setAnswer(ConfigureNodeFields.notify_retract.getFieldName(), notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether items should be persisted in the node.
|
||||||
|
*
|
||||||
|
* @return true if items are persisted
|
||||||
|
*/
|
||||||
|
public boolean isPersistItems()
|
||||||
|
{
|
||||||
|
return parseBoolean(getFieldValue(ConfigureNodeFields.persist_items));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether items should be persisted in the node.
|
||||||
|
*
|
||||||
|
* @param persist true if items should be persisted, false otherwise
|
||||||
|
*/
|
||||||
|
public void setPersistentItems(boolean persist)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.persist_items, FormField.TYPE_BOOLEAN);
|
||||||
|
setAnswer(ConfigureNodeFields.persist_items.getFieldName(), persist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether to deliver notifications to available users only.
|
||||||
|
*
|
||||||
|
* @return true if users must be available
|
||||||
|
*/
|
||||||
|
public boolean isPresenceBasedDelivery()
|
||||||
|
{
|
||||||
|
return parseBoolean(getFieldValue(ConfigureNodeFields.presence_based_delivery));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether to deliver notifications to available users only.
|
||||||
|
*
|
||||||
|
* @param presenceBased true if user must be available, false otherwise
|
||||||
|
*/
|
||||||
|
public void setPresenceBasedDelivery(boolean presenceBased)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.presence_based_delivery, FormField.TYPE_BOOLEAN);
|
||||||
|
setAnswer(ConfigureNodeFields.presence_based_delivery.getFieldName(), presenceBased);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the publishing model for the node, which determines who may publish to it.
|
||||||
|
*
|
||||||
|
* @return The publishing model
|
||||||
|
*/
|
||||||
|
public PublishModel getPublishModel()
|
||||||
|
{
|
||||||
|
String value = getFieldValue(ConfigureNodeFields.publish_model);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return PublishModel.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the publishing model for the node, which determines who may publish to it.
|
||||||
|
*
|
||||||
|
* @param publish The enum representing the possible options for the publishing model
|
||||||
|
*/
|
||||||
|
public void setPublishModel(PublishModel publish)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.publish_model, FormField.TYPE_LIST_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.publish_model.getFieldName(), getListSingle(publish.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator over the multi user chat rooms that are specified as reply rooms.
|
||||||
|
*
|
||||||
|
* @return The reply room JID's
|
||||||
|
*/
|
||||||
|
public Iterator<String> getReplyRoom()
|
||||||
|
{
|
||||||
|
return getFieldValues(ConfigureNodeFields.replyroom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the multi user chat rooms that are specified as reply rooms.
|
||||||
|
*
|
||||||
|
* @param replyRooms The multi user chat room to use as reply rooms
|
||||||
|
*/
|
||||||
|
public void setReplyRoom(List<String> replyRooms)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.replyroom, FormField.TYPE_LIST_MULTI);
|
||||||
|
setAnswer(ConfigureNodeFields.replyroom.getFieldName(), replyRooms);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the specific JID's for reply to.
|
||||||
|
*
|
||||||
|
* @return The JID's
|
||||||
|
*/
|
||||||
|
public Iterator<String> getReplyTo()
|
||||||
|
{
|
||||||
|
return getFieldValues(ConfigureNodeFields.replyto);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the specific JID's for reply to.
|
||||||
|
*
|
||||||
|
* @param replyTos The JID's to reply to
|
||||||
|
*/
|
||||||
|
public void setReplyTo(List<String> replyTos)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.replyto, FormField.TYPE_LIST_MULTI);
|
||||||
|
setAnswer(ConfigureNodeFields.replyto.getFieldName(), replyTos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the roster groups that are allowed to subscribe and retrieve items.
|
||||||
|
*
|
||||||
|
* @return The roster groups
|
||||||
|
*/
|
||||||
|
public Iterator<String> getRosterGroupsAllowed()
|
||||||
|
{
|
||||||
|
return getFieldValues(ConfigureNodeFields.roster_groups_allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the roster groups that are allowed to subscribe and retrieve items.
|
||||||
|
*
|
||||||
|
* @param groups The roster groups
|
||||||
|
*/
|
||||||
|
public void setRosterGroupsAllowed(List<String> groups)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.roster_groups_allowed, FormField.TYPE_LIST_MULTI);
|
||||||
|
setAnswer(ConfigureNodeFields.roster_groups_allowed.getFieldName(), groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if subscriptions are allowed.
|
||||||
|
*
|
||||||
|
* @return true if subscriptions are allowed, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isSubscibe()
|
||||||
|
{
|
||||||
|
return parseBoolean(getFieldValue(ConfigureNodeFields.subscribe));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether subscriptions are allowed.
|
||||||
|
*
|
||||||
|
* @param subscribe true if they are, false otherwise
|
||||||
|
*/
|
||||||
|
public void setSubscribe(boolean subscribe)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.subscribe, FormField.TYPE_BOOLEAN);
|
||||||
|
setAnswer(ConfigureNodeFields.subscribe.getFieldName(), subscribe);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the human readable node title.
|
||||||
|
*
|
||||||
|
* @return The node title
|
||||||
|
*/
|
||||||
|
public String getTitle()
|
||||||
|
{
|
||||||
|
return getFieldValue(ConfigureNodeFields.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a human readable title for the node.
|
||||||
|
*
|
||||||
|
* @param title The node title
|
||||||
|
*/
|
||||||
|
public void setTitle(String title)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.title, FormField.TYPE_TEXT_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.title.getFieldName(), title);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of node data, usually specified by the namespace of the payload (if any).
|
||||||
|
*
|
||||||
|
* @return The type of node data
|
||||||
|
*/
|
||||||
|
public String getDataType()
|
||||||
|
{
|
||||||
|
return getFieldValue(ConfigureNodeFields.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type of node data, usually specified by the namespace of the payload (if any).
|
||||||
|
*
|
||||||
|
* @param type The type of node data
|
||||||
|
*/
|
||||||
|
public void setDataType(String type)
|
||||||
|
{
|
||||||
|
addField(ConfigureNodeFields.type, FormField.TYPE_TEXT_SINGLE);
|
||||||
|
setAnswer(ConfigureNodeFields.type.getFieldName(), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder result = new StringBuilder(getClass().getName() + " Content [");
|
||||||
|
|
||||||
|
Iterator<FormField> fields = getFields();
|
||||||
|
|
||||||
|
while (fields.hasNext())
|
||||||
|
{
|
||||||
|
FormField formField = fields.next();
|
||||||
|
result.append('(');
|
||||||
|
result.append(formField.getVariable());
|
||||||
|
result.append(':');
|
||||||
|
|
||||||
|
Iterator<String> values = formField.getValues();
|
||||||
|
StringBuilder valuesBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
while (values.hasNext())
|
||||||
|
{
|
||||||
|
if (valuesBuilder.length() > 0)
|
||||||
|
result.append(',');
|
||||||
|
String value = (String)values.next();
|
||||||
|
valuesBuilder.append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valuesBuilder.length() == 0)
|
||||||
|
valuesBuilder.append("NOT SET");
|
||||||
|
result.append(valuesBuilder);
|
||||||
|
result.append(')');
|
||||||
|
}
|
||||||
|
result.append(']');
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
static private boolean parseBoolean(String fieldValue)
|
||||||
|
{
|
||||||
|
return ("1".equals(fieldValue) || "true".equals(fieldValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFieldValue(ConfigureNodeFields field)
|
||||||
|
{
|
||||||
|
FormField formField = getField(field.getFieldName());
|
||||||
|
|
||||||
|
return formField.getValues().next();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Iterator<String> getFieldValues(ConfigureNodeFields field)
|
||||||
|
{
|
||||||
|
FormField formField = getField(field.getFieldName());
|
||||||
|
|
||||||
|
return formField.getValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addField(ConfigureNodeFields nodeField, String type)
|
||||||
|
{
|
||||||
|
String fieldName = nodeField.getFieldName();
|
||||||
|
|
||||||
|
if (getField(fieldName) == null)
|
||||||
|
{
|
||||||
|
FormField field = new FormField(fieldName);
|
||||||
|
field.setType(type);
|
||||||
|
addField(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getListSingle(String value)
|
||||||
|
{
|
||||||
|
List<String> list = new ArrayList<String>(1);
|
||||||
|
list.add(value);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
218
source/org/jivesoftware/smackx/pubsub/ConfigureNodeFields.java
Normal file
218
source/org/jivesoftware/smackx/pubsub/ConfigureNodeFields.java
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.Form;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This enumeration represents all the fields of a node configuration form. This enumeration
|
||||||
|
* is not required when using the {@link ConfigureForm} to configure nodes, but may be helpful
|
||||||
|
* for generic UI's using only a {@link Form} for configuration.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum ConfigureNodeFields
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determines who may subscribe and retrieve items
|
||||||
|
*
|
||||||
|
* <p><b>Value: {@link AccessModel}</b></p>
|
||||||
|
*/
|
||||||
|
access_model,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of an XSL transformation which can be applied to
|
||||||
|
* payloads in order to generate an appropriate message
|
||||||
|
* body element
|
||||||
|
*
|
||||||
|
* <p><b>Value: {@link URL}</b></p>
|
||||||
|
*/
|
||||||
|
body_xslt,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The collection with which a node is affiliated
|
||||||
|
*
|
||||||
|
* <p><b>Value: String</b></p>
|
||||||
|
*/
|
||||||
|
collection,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of an XSL transformation which can be applied to
|
||||||
|
* payload format in order to generate a valid Data Forms result
|
||||||
|
* that the client could display using a generic Data Forms
|
||||||
|
* rendering engine body element.
|
||||||
|
*
|
||||||
|
* <p><b>Value: {@link URL}</b></p>
|
||||||
|
*/
|
||||||
|
dataform_xslt,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to deliver payloads with event notifications
|
||||||
|
*
|
||||||
|
* <p><b>Value: boolean</b></p>
|
||||||
|
*/
|
||||||
|
deliver_payloads,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether owners or publisher should receive replies to items
|
||||||
|
*
|
||||||
|
* <p><b>Value: {@link ItemReply}</b></p>
|
||||||
|
*/
|
||||||
|
itemreply,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Who may associate leaf nodes with a collection
|
||||||
|
*
|
||||||
|
* <p><b>Value: {@link ChildrenAssociationPolicy}</b></p>
|
||||||
|
*/
|
||||||
|
children_association_policy,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of JIDs that may associate leaf nodes with a
|
||||||
|
* collection
|
||||||
|
*
|
||||||
|
* <p><b>Value: List of JIDs as Strings</b></p>
|
||||||
|
*/
|
||||||
|
children_association_whitelist,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The child nodes (leaf or collection) associated with a collection
|
||||||
|
*
|
||||||
|
* <p><b>Value: List of Strings</b></p>
|
||||||
|
*/
|
||||||
|
children,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of child nodes that can be associated with a
|
||||||
|
* collection
|
||||||
|
*
|
||||||
|
* <p><b>Value: int</b></p>
|
||||||
|
*/
|
||||||
|
children_max,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of items to persist
|
||||||
|
*
|
||||||
|
* <p><b>Value: int</b></p>
|
||||||
|
*/
|
||||||
|
max_items,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum payload size in bytes
|
||||||
|
*
|
||||||
|
* <p><b>Value: int</b></p>
|
||||||
|
*/
|
||||||
|
max_payload_size,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the node is a leaf (default) or collection
|
||||||
|
*
|
||||||
|
* <p><b>Value: {@link NodeType}</b></p>
|
||||||
|
*/
|
||||||
|
node_type,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to notify subscribers when the node configuration changes
|
||||||
|
*
|
||||||
|
* <p><b>Value: boolean</b></p>
|
||||||
|
*/
|
||||||
|
notify_config,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to notify subscribers when the node is deleted
|
||||||
|
*
|
||||||
|
* <p><b>Value: boolean</b></p>
|
||||||
|
*/
|
||||||
|
notify_delete,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to notify subscribers when items are removed from the node
|
||||||
|
*
|
||||||
|
* <p><b>Value: boolean</b></p>
|
||||||
|
*/
|
||||||
|
notify_retract,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to persist items to storage. This is required to have multiple
|
||||||
|
* items in the node.
|
||||||
|
*
|
||||||
|
* <p><b>Value: boolean</b></p>
|
||||||
|
*/
|
||||||
|
persist_items,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to deliver notifications to available users only
|
||||||
|
*
|
||||||
|
* <p><b>Value: boolean</b></p>
|
||||||
|
*/
|
||||||
|
presence_based_delivery,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines who can publish to the node
|
||||||
|
*
|
||||||
|
* <p><b>Value: {@link PublishModel}</b></p>
|
||||||
|
*/
|
||||||
|
publish_model,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The specific multi-user chat rooms to specify for replyroom
|
||||||
|
*
|
||||||
|
* <p><b>Value: List of JIDs as Strings</b></p>
|
||||||
|
*/
|
||||||
|
replyroom,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The specific JID(s) to specify for replyto
|
||||||
|
*
|
||||||
|
* <p><b>Value: List of JIDs as Strings</b></p>
|
||||||
|
*/
|
||||||
|
replyto,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The roster group(s) allowed to subscribe and retrieve items
|
||||||
|
*
|
||||||
|
* <p><b>Value: List of strings</b></p>
|
||||||
|
*/
|
||||||
|
roster_groups_allowed,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to allow subscriptions
|
||||||
|
*
|
||||||
|
* <p><b>Value: boolean</b></p>
|
||||||
|
*/
|
||||||
|
subscribe,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A friendly name for the node
|
||||||
|
*
|
||||||
|
* <p><b>Value: String</b></p>
|
||||||
|
*/
|
||||||
|
title,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of node data, ussually specified by the namespace
|
||||||
|
* of the payload(if any);MAY be a list-single rather than a
|
||||||
|
* text single
|
||||||
|
*
|
||||||
|
* <p><b>Value: String</b></p>
|
||||||
|
*/
|
||||||
|
type;
|
||||||
|
|
||||||
|
public String getFieldName()
|
||||||
|
{
|
||||||
|
return "pubsub#" + toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines {@link PacketExtension} implementations that contain other
|
||||||
|
* extensions. This effectively extends the idea of an extension within one of the
|
||||||
|
* top level {@link Packet} types to consider any embedded element to be an extension
|
||||||
|
* of its parent. This more easily enables the usage of some of Smacks parsing
|
||||||
|
* utilities such as {@link PacketParserUtils#parsePacketExtension(String, String, org.xmlpull.v1.XmlPullParser)} to be used
|
||||||
|
* to parse any element of the XML being parsed.
|
||||||
|
*
|
||||||
|
* <p>Top level extensions have only one element, but they can have multiple children, or
|
||||||
|
* their children can have multiple children. This interface is a way of allowing extensions
|
||||||
|
* to be embedded within one another as a partial or complete one to one mapping of extension
|
||||||
|
* to element.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public interface EmbeddedPacketExtension extends PacketExtension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the list of embedded {@link PacketExtension} objects.
|
||||||
|
*
|
||||||
|
* @return List of embedded {@link PacketExtension}
|
||||||
|
*/
|
||||||
|
List<PacketExtension> getExtensions();
|
||||||
|
}
|
74
source/org/jivesoftware/smackx/pubsub/EventElement.java
Normal file
74
source/org/jivesoftware/smackx/pubsub/EventElement.java
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the top level element of a pubsub event extension. All types of pubsub events are
|
||||||
|
* represented by this class. The specific type can be found by {@link #getEventType()}. The
|
||||||
|
* embedded event information, which is specific to the event type, can be retrieved by the {@link #getEvent()}
|
||||||
|
* method.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class EventElement implements EmbeddedPacketExtension
|
||||||
|
{
|
||||||
|
private EventElementType type;
|
||||||
|
private NodeExtension ext;
|
||||||
|
|
||||||
|
public EventElement(EventElementType eventType, NodeExtension eventExt)
|
||||||
|
{
|
||||||
|
type = eventType;
|
||||||
|
ext = eventExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventElementType getEventType()
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PacketExtension> getExtensions()
|
||||||
|
{
|
||||||
|
return Arrays.asList(new PacketExtension[]{getEvent()});
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeExtension getEvent()
|
||||||
|
{
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElementName()
|
||||||
|
{
|
||||||
|
return "event";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespace()
|
||||||
|
{
|
||||||
|
return PubSubNamespace.EVENT.getXmlns();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<event xmlns='" + PubSubNamespace.EVENT.getXmlns() + "'>");
|
||||||
|
|
||||||
|
builder.append(ext.toXML());
|
||||||
|
builder.append("</event>");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
41
source/org/jivesoftware/smackx/pubsub/EventElementType.java
Normal file
41
source/org/jivesoftware/smackx/pubsub/EventElementType.java
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This enumeration defines the possible event types that are supported within pubsub
|
||||||
|
* event messages.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum EventElementType
|
||||||
|
{
|
||||||
|
/** A node has been associated or dissassociated with a collection node */
|
||||||
|
collection,
|
||||||
|
|
||||||
|
/** A node has had its configuration changed */
|
||||||
|
configuration,
|
||||||
|
|
||||||
|
/** A node has been deleted */
|
||||||
|
delete,
|
||||||
|
|
||||||
|
/** Items have been published to a node */
|
||||||
|
items,
|
||||||
|
|
||||||
|
/** All items have been purged from a node */
|
||||||
|
purge,
|
||||||
|
|
||||||
|
/** A node has been subscribed to */
|
||||||
|
subscription
|
||||||
|
}
|
99
source/org/jivesoftware/smackx/pubsub/FormNode.java
Normal file
99
source/org/jivesoftware/smackx/pubsub/FormNode.java
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.Form;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic packet extension which represents any pubsub form that is
|
||||||
|
* parsed from the incoming stream or being sent out to the server.
|
||||||
|
*
|
||||||
|
* Form types are defined in {@link FormNodeType}.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class FormNode extends NodeExtension
|
||||||
|
{
|
||||||
|
private Form configForm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a {@link FormNode} which contains the specified form.
|
||||||
|
*
|
||||||
|
* @param formType The type of form being sent
|
||||||
|
* @param submitForm The form
|
||||||
|
*/
|
||||||
|
public FormNode(FormNodeType formType, Form submitForm)
|
||||||
|
{
|
||||||
|
super(formType.getNodeElement());
|
||||||
|
|
||||||
|
if (submitForm == null)
|
||||||
|
throw new IllegalArgumentException("Submit form cannot be null");
|
||||||
|
configForm = submitForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a {@link FormNode} which contains the specified form, which is
|
||||||
|
* associated with the specified node.
|
||||||
|
*
|
||||||
|
* @param formType The type of form being sent
|
||||||
|
* @param nodeId The node the form is associated with
|
||||||
|
* @param submitForm The form
|
||||||
|
*/
|
||||||
|
public FormNode(FormNodeType formType, String nodeId, Form submitForm)
|
||||||
|
{
|
||||||
|
super(formType.getNodeElement(), nodeId);
|
||||||
|
|
||||||
|
if (submitForm == null)
|
||||||
|
throw new IllegalArgumentException("Submit form cannot be null");
|
||||||
|
configForm = submitForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Form that is to be sent, or was retrieved from the server.
|
||||||
|
*
|
||||||
|
* @return The form
|
||||||
|
*/
|
||||||
|
public Form getForm()
|
||||||
|
{
|
||||||
|
return configForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
if (configForm == null)
|
||||||
|
{
|
||||||
|
return super.toXML();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<");
|
||||||
|
builder.append(getElementName());
|
||||||
|
|
||||||
|
if (getNode() != null)
|
||||||
|
{
|
||||||
|
builder.append(" node='");
|
||||||
|
builder.append(getNode());
|
||||||
|
builder.append("'>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
builder.append('>');
|
||||||
|
builder.append(configForm.getDataFormToSend().toXML());
|
||||||
|
builder.append("</");
|
||||||
|
builder.append(getElementName() + '>');
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
50
source/org/jivesoftware/smackx/pubsub/FormNodeType.java
Normal file
50
source/org/jivesoftware/smackx/pubsub/FormNodeType.java
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of forms supported by the pubsub specification.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum FormNodeType
|
||||||
|
{
|
||||||
|
/** Form for configuring an existing node */
|
||||||
|
CONFIGURE_OWNER,
|
||||||
|
|
||||||
|
/** Form for configuring a node during creation */
|
||||||
|
CONFIGURE,
|
||||||
|
|
||||||
|
/** Form for configuring subscription options */
|
||||||
|
OPTIONS,
|
||||||
|
|
||||||
|
/** Form which represents the default node configuration options */
|
||||||
|
DEFAULT;
|
||||||
|
|
||||||
|
public PubSubElementType getNodeElement()
|
||||||
|
{
|
||||||
|
return PubSubElementType.valueOf(toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FormNodeType valueOfFromElementName(String elem, String configNamespace)
|
||||||
|
{
|
||||||
|
if ("configure".equals(elem) && PubSubNamespace.OWNER.getXmlns().equals(configNamespace))
|
||||||
|
{
|
||||||
|
return CONFIGURE_OWNER;
|
||||||
|
}
|
||||||
|
return valueOf(elem.toUpperCase());
|
||||||
|
}
|
||||||
|
}
|
26
source/org/jivesoftware/smackx/pubsub/FormType.java
Normal file
26
source/org/jivesoftware/smackx/pubsub/FormType.java
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.Form;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the allowable types for a {@link Form}
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum FormType
|
||||||
|
{
|
||||||
|
form, submit, cancel, result;
|
||||||
|
}
|
109
source/org/jivesoftware/smackx/pubsub/Item.java
Normal file
109
source/org/jivesoftware/smackx/pubsub/Item.java
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents an item that has been, or will be published to a
|
||||||
|
* pubsub node. An <tt>Item</tt> has several properties that are dependent
|
||||||
|
* on the configuration of the node to which it has been or will be published.
|
||||||
|
*
|
||||||
|
* <h1>An Item received from a node (via {@link LeafNode#getItems()} or {@link LeafNode#addItemEventListener(org.jivesoftware.smackx.pubsub.listener.ItemEventListener)}</b>
|
||||||
|
* <li>Will always have an id (either user or server generated) unless node configuration has both
|
||||||
|
* {@link ConfigureForm#isPersistItems()} and {@link ConfigureForm#isDeliverPayloads()}set to false.
|
||||||
|
* <li>Will have a payload if the node configuration has {@link ConfigureForm#isDeliverPayloads()} set
|
||||||
|
* to true, otherwise it will be null.
|
||||||
|
*
|
||||||
|
* <h1>An Item created to send to a node (via {@link LeafNode#send()} or {@link LeafNode#publish()}</b>
|
||||||
|
* <li>The id is optional, since the server will generate one if necessary, but should be used if it is
|
||||||
|
* meaningful in the context of the node. This value must be unique within the node that it is sent to, since
|
||||||
|
* resending an item with the same id will overwrite the one that already exists if the items are persisted.
|
||||||
|
* <li>Will require payload if the node configuration has {@link ConfigureForm#isDeliverPayloads()} set
|
||||||
|
* to true.
|
||||||
|
*
|
||||||
|
* <p>To customise the payload object being returned from the {@link #getPayload()} method, you can
|
||||||
|
* add a custom parser as explained in {@link ItemProvider}.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class Item implements PacketExtension
|
||||||
|
{
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an empty <tt>Item</tt> with no id. This is a valid item for nodes which are configured
|
||||||
|
* so that {@link ConfigureForm#isDeliverPayloads()} is false. In most cases an id will be generated by the server.
|
||||||
|
* For nodes configured with {@link ConfigureForm#isDeliverPayloads()} and {@link ConfigureForm#isPersistItems()}
|
||||||
|
* set to false, no <tt>Item</tt> is sent to the node, you have to use {@link LeafNode#send()} or {@link LeafNode#publish()}
|
||||||
|
* methods in this case.
|
||||||
|
*/
|
||||||
|
public Item()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(String itemId)
|
||||||
|
{
|
||||||
|
id = itemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the item id. Unique to the node it is associated with.
|
||||||
|
*
|
||||||
|
* @return The id
|
||||||
|
*/
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElementName()
|
||||||
|
{
|
||||||
|
return "item";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespace()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<item");
|
||||||
|
|
||||||
|
if (id != null)
|
||||||
|
{
|
||||||
|
builder.append(" id='");
|
||||||
|
builder.append(id);
|
||||||
|
builder.append("'");
|
||||||
|
}
|
||||||
|
builder.append("/>");
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getClass().getName() + " | Content [" + toXML() + "]";
|
||||||
|
}
|
||||||
|
}
|
62
source/org/jivesoftware/smackx/pubsub/ItemDeleteEvent.java
Normal file
62
source/org/jivesoftware/smackx/pubsub/ItemDeleteEvent.java
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an event in which items have been deleted from the node.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class ItemDeleteEvent extends SubscriptionEvent
|
||||||
|
{
|
||||||
|
private List<String> itemIds = Collections.EMPTY_LIST;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an <tt>ItemDeleteEvent</tt> that indicates the the supplied
|
||||||
|
* items (by id) have been deleted, and that the event matches the listed
|
||||||
|
* subscriptions. The subscriptions would have been created by calling
|
||||||
|
* {@link LeafNode#subscribe(String)}.
|
||||||
|
*
|
||||||
|
* @param nodeId The id of the node the event came from
|
||||||
|
* @param deletedItemIds The item ids of the items that were deleted.
|
||||||
|
* @param subscriptionIds The subscriptions that match the event.
|
||||||
|
*/
|
||||||
|
public ItemDeleteEvent(String nodeId, List<String> deletedItemIds, List<String> subscriptionIds)
|
||||||
|
{
|
||||||
|
super(nodeId, subscriptionIds);
|
||||||
|
|
||||||
|
if (deletedItemIds == null)
|
||||||
|
throw new IllegalArgumentException("deletedItemIds cannot be null");
|
||||||
|
itemIds = deletedItemIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the item id's of the items that have been deleted.
|
||||||
|
*
|
||||||
|
* @return List of item id's
|
||||||
|
*/
|
||||||
|
public List<String> getItemIds()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableList(itemIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getClass().getName() + " [subscriptions: " + getSubscriptions() + "], [Deleted Items: " + itemIds + ']';
|
||||||
|
}
|
||||||
|
}
|
123
source/org/jivesoftware/smackx/pubsub/ItemPublishEvent.java
Normal file
123
source/org/jivesoftware/smackx/pubsub/ItemPublishEvent.java
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an event generated by an item(s) being published to a node.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class ItemPublishEvent <T extends Item> extends SubscriptionEvent
|
||||||
|
{
|
||||||
|
private List<T> items;
|
||||||
|
private Date originalDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an <tt>ItemPublishEvent</tt> with the provided list
|
||||||
|
* of {@link Item} that were published.
|
||||||
|
*
|
||||||
|
* @param nodeId The id of the node the event came from
|
||||||
|
* @param eventItems The list of {@link Item} that were published
|
||||||
|
*/
|
||||||
|
public ItemPublishEvent(String nodeId, List<T> eventItems)
|
||||||
|
{
|
||||||
|
super(nodeId);
|
||||||
|
items = eventItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an <tt>ItemPublishEvent</tt> with the provided list
|
||||||
|
* of {@link Item} that were published. The list of subscription ids
|
||||||
|
* represents the subscriptions that matched the event, in the case
|
||||||
|
* of the user having multiple subscriptions.
|
||||||
|
*
|
||||||
|
* @param nodeId The id of the node the event came from
|
||||||
|
* @param eventItems The list of {@link Item} that were published
|
||||||
|
* @param subscriptionIds The list of subscriptionIds
|
||||||
|
*/
|
||||||
|
public ItemPublishEvent(String nodeId, List<T> eventItems, List<String> subscriptionIds)
|
||||||
|
{
|
||||||
|
super(nodeId, subscriptionIds);
|
||||||
|
items = eventItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an <tt>ItemPublishEvent</tt> with the provided list
|
||||||
|
* of {@link Item} that were published in the past. The published
|
||||||
|
* date signifies that this is delayed event. The list of subscription ids
|
||||||
|
* represents the subscriptions that matched the event, in the case
|
||||||
|
* of the user having multiple subscriptions.
|
||||||
|
*
|
||||||
|
* @param nodeId The id of the node the event came from
|
||||||
|
* @param eventItems The list of {@link Item} that were published
|
||||||
|
* @param subscriptionIds The list of subscriptionIds
|
||||||
|
* @param publishedDate The original publishing date of the events
|
||||||
|
*/
|
||||||
|
public ItemPublishEvent(String nodeId, List<T> eventItems, List<String> subscriptionIds, Date publishedDate)
|
||||||
|
{
|
||||||
|
super(nodeId, subscriptionIds);
|
||||||
|
items = eventItems;
|
||||||
|
|
||||||
|
if (publishedDate != null)
|
||||||
|
originalDate = publishedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of {@link Item} that were published.
|
||||||
|
*
|
||||||
|
* @return The list of published {@link Item}
|
||||||
|
*/
|
||||||
|
public List<T> getItems()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableList(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether this event was delayed. That is, the items
|
||||||
|
* were published to the node at some time in the past. This will
|
||||||
|
* typically happen if there is an item already published to the node
|
||||||
|
* before a user subscribes to it. In this case, when the user
|
||||||
|
* subscribes, the server may send the last item published to the node
|
||||||
|
* with a delay date showing its time of original publication.
|
||||||
|
*
|
||||||
|
* @return true if the items are delayed, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isDelayed()
|
||||||
|
{
|
||||||
|
return (originalDate != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the original date the items were published. This is only
|
||||||
|
* valid if {@link #isDelayed()} is true.
|
||||||
|
*
|
||||||
|
* @return Date items were published if {@link #isDelayed()} is true, null otherwise.
|
||||||
|
*/
|
||||||
|
public Date getPublishedDate()
|
||||||
|
{
|
||||||
|
return originalDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getClass().getName() + " [subscriptions: " + getSubscriptions() + "], [Delayed: " +
|
||||||
|
(isDelayed() ? originalDate.toString() : "false") + ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
29
source/org/jivesoftware/smackx/pubsub/ItemReply.java
Normal file
29
source/org/jivesoftware/smackx/pubsub/ItemReply.java
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are the options for the node configuration setting {@link ConfigureForm#setItemReply(ItemReply)},
|
||||||
|
* which defines who should receive replies to items.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum ItemReply
|
||||||
|
{
|
||||||
|
/** The node owner */
|
||||||
|
owner,
|
||||||
|
|
||||||
|
/** The item publisher */
|
||||||
|
publisher;
|
||||||
|
}
|
183
source/org/jivesoftware/smackx/pubsub/ItemsExtension.java
Normal file
183
source/org/jivesoftware/smackx/pubsub/ItemsExtension.java
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to for multiple purposes.
|
||||||
|
* <li>It can represent an event containing a list of items that have been published
|
||||||
|
* <li>It can represent an event containing a list of retracted (deleted) items.
|
||||||
|
* <li>It can represent a request to delete a list of items.
|
||||||
|
* <li>It can represent a request to get existing items.
|
||||||
|
*
|
||||||
|
* <p><b>Please note, this class is used for internal purposes, and is not required for usage of
|
||||||
|
* pubsub functionality.</b>
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class ItemsExtension extends NodeExtension implements EmbeddedPacketExtension
|
||||||
|
{
|
||||||
|
protected ItemsElementType type;
|
||||||
|
protected String attValue;
|
||||||
|
protected List<? extends PacketExtension> items;
|
||||||
|
|
||||||
|
public enum ItemsElementType
|
||||||
|
{
|
||||||
|
/** An items element, which has an optional <b>max_items</b> attribute when requesting items */
|
||||||
|
items(PubSubElementType.ITEMS, "max_items"),
|
||||||
|
|
||||||
|
/** A retract element, which has an optional <b>notify</b> attribute when publishing deletions */
|
||||||
|
retract(PubSubElementType.RETRACT, "notify");
|
||||||
|
|
||||||
|
private PubSubElementType elem;
|
||||||
|
private String att;
|
||||||
|
|
||||||
|
private ItemsElementType(PubSubElementType nodeElement, String attribute)
|
||||||
|
{
|
||||||
|
elem = nodeElement;
|
||||||
|
att = attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PubSubElementType getNodeElement()
|
||||||
|
{
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElementAttribute()
|
||||||
|
{
|
||||||
|
return att;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an instance with a list representing items that have been published or deleted.
|
||||||
|
*
|
||||||
|
* <p>Valid scenarios are:
|
||||||
|
* <li>Request items from node - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and an
|
||||||
|
* optional value for the <b>max_items</b> attribute.
|
||||||
|
* <li>Request to delete items - itemsType = {@link ItemsElementType#retract}, items = list of {@link Item} containing
|
||||||
|
* only id's and an optional value for the <b>notify</b> attribute.
|
||||||
|
* <li>Items published event - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and
|
||||||
|
* attributeValue = <code>null</code>
|
||||||
|
* <li>Items deleted event - itemsType = {@link ItemsElementType#items}, items = list of {@link RetractItem} and
|
||||||
|
* attributeValue = <code>null</code>
|
||||||
|
*
|
||||||
|
* @param itemsType Type of representation
|
||||||
|
* @param nodeId The node to which the items are being sent or deleted
|
||||||
|
* @param items The list of {@link Item} or {@link RetractItem}
|
||||||
|
* @param attributeValue The value of the <b>max_items</b>
|
||||||
|
*/
|
||||||
|
public ItemsExtension(ItemsElementType itemsType, String nodeId, List<? extends PacketExtension> items, String attributeValue)
|
||||||
|
{
|
||||||
|
super(itemsType.getNodeElement(), nodeId);
|
||||||
|
type = itemsType;
|
||||||
|
this.items = items;
|
||||||
|
attValue = attributeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a request to get items from the node as defined in the first scenario
|
||||||
|
* in {@link #ItemsExtension(ItemsElementType, String, List, String)}
|
||||||
|
*
|
||||||
|
* @param nodeId The node the items will be requested from
|
||||||
|
* @param maxItems The limit on the number of items to retrieve (null for all)
|
||||||
|
*/
|
||||||
|
public ItemsExtension(String nodeId, Integer maxItems)
|
||||||
|
{
|
||||||
|
this(ItemsElementType.items, nodeId, null, maxItems == null ? null : maxItems.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of element
|
||||||
|
*
|
||||||
|
* @return The element type
|
||||||
|
*/
|
||||||
|
public ItemsElementType getItemsElementType()
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PacketExtension> getExtensions()
|
||||||
|
{
|
||||||
|
return (List<PacketExtension>)getItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the items related to the type of request or event.
|
||||||
|
*
|
||||||
|
* return List of {@link Item}, {@link RetractItem}, or null
|
||||||
|
*/
|
||||||
|
public List<? extends PacketExtension> getItems()
|
||||||
|
{
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the optional attribute related to the {@link ItemsElementType}.
|
||||||
|
*
|
||||||
|
* @return The attribute value
|
||||||
|
*/
|
||||||
|
public String getAttributeValue()
|
||||||
|
{
|
||||||
|
return attValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
if (((items == null) || (items.size() == 0)) && (attValue == null))
|
||||||
|
{
|
||||||
|
return super.toXML();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<");
|
||||||
|
builder.append(getElementName());
|
||||||
|
builder.append(" node='");
|
||||||
|
builder.append(getNode());
|
||||||
|
|
||||||
|
if (attValue != null)
|
||||||
|
{
|
||||||
|
builder.append("' ");
|
||||||
|
builder.append(type.getElementAttribute());
|
||||||
|
builder.append("='");
|
||||||
|
builder.append(attValue);
|
||||||
|
builder.append("'>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.append("'>");
|
||||||
|
for (PacketExtension item : items)
|
||||||
|
{
|
||||||
|
builder.append(item.toXML());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append("</");
|
||||||
|
builder.append(getElementName());
|
||||||
|
builder.append(">");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getClass().getName() + "Content [" + toXML() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
309
source/org/jivesoftware/smackx/pubsub/LeafNode.java
Normal file
309
source/org/jivesoftware/smackx/pubsub/LeafNode.java
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.packet.IQ.Type;
|
||||||
|
import org.jivesoftware.smackx.packet.DiscoverItems;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSub;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.SyncPacketSend;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main class for the majority of pubsub functionality. In general
|
||||||
|
* almost all pubsub capabilities are related to the concept of a node.
|
||||||
|
* All items are published to a node, and typically subscribed to by other
|
||||||
|
* users. These users then retrieve events based on this subscription.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class LeafNode extends Node
|
||||||
|
{
|
||||||
|
LeafNode(XMPPConnection connection, String nodeName)
|
||||||
|
{
|
||||||
|
super(connection, nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information on the items in the node in standard
|
||||||
|
* {@link DiscoverItems} format.
|
||||||
|
*
|
||||||
|
* @return The item details in {@link DiscoverItems} format
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public DiscoverItems discoverItems()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
DiscoverItems items = new DiscoverItems();
|
||||||
|
items.setTo(to);
|
||||||
|
items.setNode(getId());
|
||||||
|
return (DiscoverItems)SyncPacketSend.getReply(con, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current items stored in the node.
|
||||||
|
*
|
||||||
|
* @return List of {@link Item} in the node
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public <T extends Item> List<T> getItems()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub request = createPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.ITEMS, getId()));
|
||||||
|
|
||||||
|
PubSub result = (PubSub)SyncPacketSend.getReply(con, request);
|
||||||
|
ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS);
|
||||||
|
return (List<T>)itemsElem.getItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the items specified from the node. This would typically be
|
||||||
|
* used when the server does not return the payload due to size
|
||||||
|
* constraints. The user would be required to retrieve the payload
|
||||||
|
* after the items have been retrieved via {@link #getItems()} or an
|
||||||
|
* event, that did not include the payload.
|
||||||
|
*
|
||||||
|
* @param ids Item ids of the items to retrieve
|
||||||
|
*
|
||||||
|
* @return The list of {@link Item} with payload
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public <T extends Item> List<T> getItems(Collection<String> ids)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
List<Item> itemList = new ArrayList<Item>(ids.size());
|
||||||
|
|
||||||
|
for (String id : ids)
|
||||||
|
{
|
||||||
|
itemList.add(new Item(id));
|
||||||
|
}
|
||||||
|
PubSub request = createPubsubPacket(Type.GET, new ItemsExtension(ItemsExtension.ItemsElementType.items, getId(), itemList, null));
|
||||||
|
|
||||||
|
PubSub result = (PubSub)SyncPacketSend.getReply(con, request);
|
||||||
|
ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS);
|
||||||
|
return (List<T>)itemsElem.getItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get items persisted on the node, limited to the specified number.
|
||||||
|
*
|
||||||
|
* @param maxItems Maximum number of items to return
|
||||||
|
*
|
||||||
|
* @return List of {@link Item}
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public <T extends Item> List<T> getItems(int maxItems)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub request = createPubsubPacket(Type.GET, new ItemsExtension(getId(), Integer.valueOf(maxItems)));
|
||||||
|
|
||||||
|
PubSub result = (PubSub)SyncPacketSend.getReply(con, request);
|
||||||
|
ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS);
|
||||||
|
return (List<T>)itemsElem.getItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publishes an event to the node. This is an empty event
|
||||||
|
* with no item.
|
||||||
|
*
|
||||||
|
* This is only acceptable for nodes with {@link ConfigureForm#isPersistItems()}=false
|
||||||
|
* and {@link ConfigureForm#isDeliverPayloads()}=false.
|
||||||
|
*
|
||||||
|
* This is an asynchronous call which returns as soon as the
|
||||||
|
* packet has been sent.
|
||||||
|
*
|
||||||
|
* For synchronous calls use {@link #send() send()}.
|
||||||
|
*/
|
||||||
|
public void publish()
|
||||||
|
{
|
||||||
|
PubSub packet = createPubsubPacket(Type.SET, new NodeExtension(PubSubElementType.PUBLISH, getId()));
|
||||||
|
|
||||||
|
con.sendPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publishes an event to the node. This is a simple item
|
||||||
|
* with no payload.
|
||||||
|
*
|
||||||
|
* If the id is null, an empty item (one without an id) will be sent.
|
||||||
|
* Please note that this is not the same as {@link #send()}, which
|
||||||
|
* publishes an event with NO item.
|
||||||
|
*
|
||||||
|
* This is an asynchronous call which returns as soon as the
|
||||||
|
* packet has been sent.
|
||||||
|
*
|
||||||
|
* For synchronous calls use {@link #send(Item) send(Item))}.
|
||||||
|
*
|
||||||
|
* @param item - The item being sent
|
||||||
|
*/
|
||||||
|
public <T extends Item> void publish(T item)
|
||||||
|
{
|
||||||
|
Collection<T> items = new ArrayList<T>(1);
|
||||||
|
items.add((T)(item == null ? new Item() : item));
|
||||||
|
publish(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publishes multiple events to the node. Same rules apply as in {@link #publish(Item)}.
|
||||||
|
*
|
||||||
|
* In addition, if {@link ConfigureForm#isPersistItems()}=false, only the last item in the input
|
||||||
|
* list will get stored on the node, assuming it stores the last sent item.
|
||||||
|
*
|
||||||
|
* This is an asynchronous call which returns as soon as the
|
||||||
|
* packet has been sent.
|
||||||
|
*
|
||||||
|
* For synchronous calls use {@link #send(Collection) send(Collection))}.
|
||||||
|
*
|
||||||
|
* @param items - The collection of items being sent
|
||||||
|
*/
|
||||||
|
public <T extends Item> void publish(Collection<T> items)
|
||||||
|
{
|
||||||
|
PubSub packet = createPubsubPacket(Type.SET, new PublishItem<T>(getId(), items));
|
||||||
|
|
||||||
|
con.sendPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publishes an event to the node. This is an empty event
|
||||||
|
* with no item.
|
||||||
|
*
|
||||||
|
* This is only acceptable for nodes with {@link ConfigureForm#isPersistItems()}=false
|
||||||
|
* and {@link ConfigureForm#isDeliverPayloads()}=false.
|
||||||
|
*
|
||||||
|
* This is a synchronous call which will throw an exception
|
||||||
|
* on failure.
|
||||||
|
*
|
||||||
|
* For asynchronous calls, use {@link #publish() publish()}.
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public void send()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub packet = createPubsubPacket(Type.SET, new NodeExtension(PubSubElementType.PUBLISH, getId()));
|
||||||
|
|
||||||
|
SyncPacketSend.getReply(con, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publishes an event to the node. This can be either a simple item
|
||||||
|
* with no payload, or one with it. This is determined by the Node
|
||||||
|
* configuration.
|
||||||
|
*
|
||||||
|
* If the node has <b>deliver_payload=false</b>, the Item must not
|
||||||
|
* have a payload.
|
||||||
|
*
|
||||||
|
* If the id is null, an empty item (one without an id) will be sent.
|
||||||
|
* Please note that this is not the same as {@link #send()}, which
|
||||||
|
* publishes an event with NO item.
|
||||||
|
*
|
||||||
|
* This is a synchronous call which will throw an exception
|
||||||
|
* on failure.
|
||||||
|
*
|
||||||
|
* For asynchronous calls, use {@link #publish(Item) publish(Item)}.
|
||||||
|
*
|
||||||
|
* @param item - The item being sent
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public <T extends Item> void send(T item)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
Collection<T> items = new ArrayList<T>(1);
|
||||||
|
items.add((item == null ? (T)new Item() : item));
|
||||||
|
send(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publishes multiple events to the node. Same rules apply as in {@link #send(Item)}.
|
||||||
|
*
|
||||||
|
* In addition, if {@link ConfigureForm#isPersistItems()}=false, only the last item in the input
|
||||||
|
* list will get stored on the node, assuming it stores the last sent item.
|
||||||
|
*
|
||||||
|
* This is a synchronous call which will throw an exception
|
||||||
|
* on failure.
|
||||||
|
*
|
||||||
|
* For asynchronous calls, use {@link #publish(Collection) publish(Collection))}.
|
||||||
|
*
|
||||||
|
* @param items - The collection of {@link Item} objects being sent
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public <T extends Item> void send(Collection<T> items)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub packet = createPubsubPacket(Type.SET, new PublishItem<T>(getId(), items));
|
||||||
|
|
||||||
|
SyncPacketSend.getReply(con, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purges the node of all items.
|
||||||
|
*
|
||||||
|
* <p>Note: Some implementations may keep the last item
|
||||||
|
* sent.
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public void deleteAllItems()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub request = createPubsubPacket(Type.SET, new NodeExtension(PubSubElementType.PURGE_OWNER, getId()), PubSubElementType.PURGE_OWNER.getNamespace());
|
||||||
|
|
||||||
|
SyncPacketSend.getReply(con, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the item with the specified id from the node.
|
||||||
|
*
|
||||||
|
* @param itemId The id of the item
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public void deleteItem(String itemId)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
Collection<String> items = new ArrayList<String>(1);
|
||||||
|
items.add(itemId);
|
||||||
|
deleteItem(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the items with the specified id's from the node.
|
||||||
|
*
|
||||||
|
* @param itemIds The list of id's of items to delete
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public void deleteItem(Collection<String> itemIds)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
List<Item> items = new ArrayList<Item>(itemIds.size());
|
||||||
|
|
||||||
|
for (String id : itemIds)
|
||||||
|
{
|
||||||
|
items.add(new Item(id));
|
||||||
|
}
|
||||||
|
PubSub request = createPubsubPacket(Type.SET, new ItemsExtension(ItemsExtension.ItemsElementType.retract, getId(), items, null));
|
||||||
|
SyncPacketSend.getReply(con, request);
|
||||||
|
}
|
||||||
|
}
|
525
source/org/jivesoftware/smackx/pubsub/Node.java
Normal file
525
source/org/jivesoftware/smackx/pubsub/Node.java
Normal file
|
@ -0,0 +1,525 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-07-09
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.PacketListener;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.filter.OrFilter;
|
||||||
|
import org.jivesoftware.smack.filter.PacketFilter;
|
||||||
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smack.packet.IQ.Type;
|
||||||
|
import org.jivesoftware.smackx.Form;
|
||||||
|
import org.jivesoftware.smackx.packet.DelayInformation;
|
||||||
|
import org.jivesoftware.smackx.packet.DiscoverInfo;
|
||||||
|
import org.jivesoftware.smackx.packet.Header;
|
||||||
|
import org.jivesoftware.smackx.packet.HeadersExtension;
|
||||||
|
import org.jivesoftware.smackx.pubsub.listener.ItemDeleteListener;
|
||||||
|
import org.jivesoftware.smackx.pubsub.listener.ItemEventListener;
|
||||||
|
import org.jivesoftware.smackx.pubsub.listener.NodeConfigListener;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSub;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.SyncPacketSend;
|
||||||
|
import org.jivesoftware.smackx.pubsub.util.NodeUtils;
|
||||||
|
|
||||||
|
abstract public class Node
|
||||||
|
{
|
||||||
|
protected XMPPConnection con;
|
||||||
|
protected String id;
|
||||||
|
protected String to;
|
||||||
|
|
||||||
|
protected ConcurrentHashMap<ItemEventListener, PacketListener> itemEventToListenerMap = new ConcurrentHashMap<ItemEventListener, PacketListener>();
|
||||||
|
protected ConcurrentHashMap<ItemDeleteListener, PacketListener> itemDeleteToListenerMap = new ConcurrentHashMap<ItemDeleteListener, PacketListener>();
|
||||||
|
protected ConcurrentHashMap<NodeConfigListener, PacketListener> configEventToListenerMap = new ConcurrentHashMap<NodeConfigListener, PacketListener>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a node associated to the supplied connection with the specified
|
||||||
|
* node id.
|
||||||
|
*
|
||||||
|
* @param connection The connection the node is associated with
|
||||||
|
* @param nodeName The node id
|
||||||
|
*/
|
||||||
|
Node(XMPPConnection connection, String nodeName)
|
||||||
|
{
|
||||||
|
con = connection;
|
||||||
|
id = nodeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some XMPP servers may require a specific service to be addressed on the
|
||||||
|
* server.
|
||||||
|
*
|
||||||
|
* For example, OpenFire requires the server to be prefixed by <b>pubsub</b>
|
||||||
|
*/
|
||||||
|
void setTo(String toAddress)
|
||||||
|
{
|
||||||
|
to = toAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the NodeId
|
||||||
|
*
|
||||||
|
* @return the node id
|
||||||
|
*/
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns a configuration form, from which you can create an answer form to be submitted
|
||||||
|
* via the {@link #sendConfigurationForm(Form)}.
|
||||||
|
*
|
||||||
|
* @return the configuration form
|
||||||
|
*/
|
||||||
|
public ConfigureForm getNodeConfiguration()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
Packet reply = sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.CONFIGURE_OWNER, getId()), PubSubNamespace.OWNER);
|
||||||
|
return NodeUtils.getFormFromPacket(reply, PubSubElementType.CONFIGURE_OWNER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the configuration with the contents of the new {@link Form}
|
||||||
|
*
|
||||||
|
* @param submitForm
|
||||||
|
*/
|
||||||
|
public void sendConfigurationForm(Form submitForm)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub packet = createPubsubPacket(Type.SET, new FormNode(FormNodeType.CONFIGURE_OWNER, getId(), submitForm), PubSubNamespace.OWNER);
|
||||||
|
SyncPacketSend.getReply(con, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover node information in standard {@link DiscoverInfo} format.
|
||||||
|
*
|
||||||
|
* @return The discovery information about the node.
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public DiscoverInfo discoverInfo()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
DiscoverInfo info = new DiscoverInfo();
|
||||||
|
info.setTo(to);
|
||||||
|
info.setNode(getId());
|
||||||
|
return (DiscoverInfo)SyncPacketSend.getReply(con, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the subscriptions currently associated with this node.
|
||||||
|
*
|
||||||
|
* @return List of {@link Subscription}
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public List<Subscription> getSubscriptions()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub reply = (PubSub)sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.SUBSCRIPTIONS, getId()));
|
||||||
|
SubscriptionsExtension subElem = (SubscriptionsExtension)reply.getExtension(PubSubElementType.SUBSCRIPTIONS);
|
||||||
|
return subElem.getSubscriptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user subscribes to the node using the supplied jid. The
|
||||||
|
* bare jid portion of this one must match the jid for the connection.
|
||||||
|
*
|
||||||
|
* Please note that the {@link Subscription.State} should be checked
|
||||||
|
* on return since more actions may be required by the caller.
|
||||||
|
* {@link Subscription.State#pending} - The owner must approve the subscription
|
||||||
|
* request before messages will be received.
|
||||||
|
* {@link Subscription.State#unconfigured} - If the {@link Subscription#isConfigRequired()} is true,
|
||||||
|
* the caller must configure the subscription before messages will be received. If it is false
|
||||||
|
* the caller can configure it but is not required to do so.
|
||||||
|
* @param jid The jid to subscribe as.
|
||||||
|
* @return The subscription
|
||||||
|
* @exception XMPPException
|
||||||
|
*/
|
||||||
|
public Subscription subscribe(String jid)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub reply = (PubSub)sendPubsubPacket(Type.SET, new SubscribeExtension(jid, getId()));
|
||||||
|
return (Subscription)reply.getExtension(PubSubElementType.SUBSCRIPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user subscribes to the node using the supplied jid and subscription
|
||||||
|
* options. The bare jid portion of this one must match the jid for the
|
||||||
|
* connection.
|
||||||
|
*
|
||||||
|
* Please note that the {@link Subscription.State} should be checked
|
||||||
|
* on return since more actions may be required by the caller.
|
||||||
|
* {@link Subscription.State#pending} - The owner must approve the subscription
|
||||||
|
* request before messages will be received.
|
||||||
|
* {@link Subscription.State#unconfigured} - If the {@link Subscription#isConfigRequired()} is true,
|
||||||
|
* the caller must configure the subscription before messages will be received. If it is false
|
||||||
|
* the caller can configure it but is not required to do so.
|
||||||
|
* @param jid The jid to subscribe as.
|
||||||
|
* @return The subscription
|
||||||
|
* @exception XMPPException
|
||||||
|
*/
|
||||||
|
public Subscription subscribe(String jid, SubscribeForm subForm)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub request = createPubsubPacket(Type.SET, new SubscribeExtension(jid, getId()));
|
||||||
|
request.addExtension(new FormNode(FormNodeType.OPTIONS, subForm));
|
||||||
|
PubSub reply = (PubSub)PubSubManager.sendPubsubPacket(con, jid, Type.SET, request);
|
||||||
|
return (Subscription)reply.getExtension(PubSubElementType.SUBSCRIPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the subscription related to the specified JID. This will only
|
||||||
|
* work if there is only 1 subscription. If there are multiple subscriptions,
|
||||||
|
* use {@link #unsubscribe(String, String)}.
|
||||||
|
*
|
||||||
|
* @param jid The JID used to subscribe to the node
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public void unsubscribe(String jid)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
unsubscribe(jid, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specific subscription related to the specified JID.
|
||||||
|
*
|
||||||
|
* @param jid The JID used to subscribe to the node
|
||||||
|
* @param subscriptionId The id of the subscription being removed
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public void unsubscribe(String jid, String subscriptionId)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
sendPubsubPacket(Type.SET, new UnsubscribeExtension(jid, getId(), subscriptionId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a SubscribeForm for subscriptions, from which you can create an answer form to be submitted
|
||||||
|
* via the {@link #sendConfigurationForm(Form)}.
|
||||||
|
*
|
||||||
|
* @return A subscription options form
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public SubscribeForm getSubscriptionOptions(String jid)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return getSubscriptionOptions(jid, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the options for configuring the specified subscription.
|
||||||
|
*
|
||||||
|
* @param jid JID the subscription is registered under
|
||||||
|
* @param subscriptionId The subscription id
|
||||||
|
*
|
||||||
|
* @return The subscription option form
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public SubscribeForm getSubscriptionOptions(String jid, String subscriptionId)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub packet = (PubSub)sendPubsubPacket(Type.GET, new OptionsExtension(jid, getId(), subscriptionId));
|
||||||
|
FormNode ext = (FormNode)packet.getExtension(PubSubElementType.OPTIONS);
|
||||||
|
return new SubscribeForm(ext.getForm());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a listener for item publication events. This
|
||||||
|
* listener will get called whenever an item is published to
|
||||||
|
* this node.
|
||||||
|
*
|
||||||
|
* @param listener The handler for the event
|
||||||
|
*/
|
||||||
|
public void addItemEventListener(ItemEventListener listener)
|
||||||
|
{
|
||||||
|
PacketListener conListener = new ItemEventTranslator(listener);
|
||||||
|
itemEventToListenerMap.put(listener, conListener);
|
||||||
|
con.addPacketListener(conListener, new EventContentFilter(EventElementType.items.toString(), "item"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a listener for publication events.
|
||||||
|
*
|
||||||
|
* @param listener The handler to unregister
|
||||||
|
*/
|
||||||
|
public void removeItemEventListener(ItemEventListener listener)
|
||||||
|
{
|
||||||
|
PacketListener conListener = itemEventToListenerMap.remove(listener);
|
||||||
|
|
||||||
|
if (conListener != null)
|
||||||
|
con.removePacketListener(conListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a listener for configuration events. This listener
|
||||||
|
* will get called whenever the node's configuration changes.
|
||||||
|
*
|
||||||
|
* @param listener The handler for the event
|
||||||
|
*/
|
||||||
|
public void addConfigurationListener(NodeConfigListener listener)
|
||||||
|
{
|
||||||
|
PacketListener conListener = new NodeConfigTranslator(listener);
|
||||||
|
configEventToListenerMap.put(listener, conListener);
|
||||||
|
con.addPacketListener(conListener, new EventContentFilter(EventElementType.configuration.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a listener for configuration events.
|
||||||
|
*
|
||||||
|
* @param listener The handler to unregister
|
||||||
|
*/
|
||||||
|
public void removeConfigurationListener(NodeConfigListener listener)
|
||||||
|
{
|
||||||
|
PacketListener conListener = configEventToListenerMap .remove(listener);
|
||||||
|
|
||||||
|
if (conListener != null)
|
||||||
|
con.removePacketListener(conListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an listener for item delete events. This listener
|
||||||
|
* gets called whenever an item is deleted from the node.
|
||||||
|
*
|
||||||
|
* @param listener The handler for the event
|
||||||
|
*/
|
||||||
|
public void addItemDeleteListener(ItemDeleteListener listener)
|
||||||
|
{
|
||||||
|
PacketListener delListener = new ItemDeleteTranslator(listener);
|
||||||
|
itemDeleteToListenerMap.put(listener, delListener);
|
||||||
|
EventContentFilter deleteItem = new EventContentFilter(EventElementType.items.toString(), "retract");
|
||||||
|
EventContentFilter purge = new EventContentFilter(EventElementType.purge.toString());
|
||||||
|
|
||||||
|
con.addPacketListener(delListener, new OrFilter(deleteItem, purge));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a listener for item delete events.
|
||||||
|
*
|
||||||
|
* @param listener The handler to unregister
|
||||||
|
*/
|
||||||
|
public void removeItemDeleteListener(ItemDeleteListener listener)
|
||||||
|
{
|
||||||
|
PacketListener conListener = itemDeleteToListenerMap .remove(listener);
|
||||||
|
|
||||||
|
if (conListener != null)
|
||||||
|
con.removePacketListener(conListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return super.toString() + " " + getClass().getName() + " id: " + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PubSub createPubsubPacket(Type type, PacketExtension ext)
|
||||||
|
{
|
||||||
|
return createPubsubPacket(type, ext, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PubSub createPubsubPacket(Type type, PacketExtension ext, PubSubNamespace ns)
|
||||||
|
{
|
||||||
|
return PubSubManager.createPubsubPacket(to, type, ext, ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Packet sendPubsubPacket(Type type, NodeExtension ext)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return PubSubManager.sendPubsubPacket(con, to, type, ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Packet sendPubsubPacket(Type type, NodeExtension ext, PubSubNamespace ns)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return PubSubManager.sendPubsubPacket(con, to, type, ext, ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static List<String> getSubscriptionIds(Packet packet)
|
||||||
|
{
|
||||||
|
HeadersExtension headers = (HeadersExtension)packet.getExtension("headers", "http://jabber.org/protocol/shim");
|
||||||
|
List<String> values = null;
|
||||||
|
|
||||||
|
if (headers != null)
|
||||||
|
{
|
||||||
|
values = new ArrayList<String>(headers.getHeaders().size());
|
||||||
|
|
||||||
|
for (Header header : headers.getHeaders())
|
||||||
|
{
|
||||||
|
values.add(header.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class translates low level item publication events into api level objects for
|
||||||
|
* user consumption.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class ItemEventTranslator implements PacketListener
|
||||||
|
{
|
||||||
|
private ItemEventListener listener;
|
||||||
|
|
||||||
|
public ItemEventTranslator(ItemEventListener eventListener)
|
||||||
|
{
|
||||||
|
listener = eventListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processPacket(Packet packet)
|
||||||
|
{
|
||||||
|
EventElement event = (EventElement)packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
|
||||||
|
ItemsExtension itemsElem = (ItemsExtension)event.getEvent();
|
||||||
|
DelayInformation delay = (DelayInformation)packet.getExtension("delay", "urn:xmpp:delay");
|
||||||
|
|
||||||
|
// If there was no delay based on XEP-0203, then try XEP-0091 for backward compatibility
|
||||||
|
if (delay == null)
|
||||||
|
{
|
||||||
|
delay = (DelayInformation)packet.getExtension("x", "jabber:x:delay");
|
||||||
|
}
|
||||||
|
ItemPublishEvent eventItems = new ItemPublishEvent(itemsElem.getNode(), (List<Item>)itemsElem.getItems(), getSubscriptionIds(packet), (delay == null ? null : delay.getStamp()));
|
||||||
|
listener.handlePublishedItems(eventItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class translates low level item deletion events into api level objects for
|
||||||
|
* user consumption.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class ItemDeleteTranslator implements PacketListener
|
||||||
|
{
|
||||||
|
private ItemDeleteListener listener;
|
||||||
|
|
||||||
|
public ItemDeleteTranslator(ItemDeleteListener eventListener)
|
||||||
|
{
|
||||||
|
listener = eventListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processPacket(Packet packet)
|
||||||
|
{
|
||||||
|
EventElement event = (EventElement)packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
|
||||||
|
|
||||||
|
List<PacketExtension> extList = event.getExtensions();
|
||||||
|
|
||||||
|
if (extList.get(0).getElementName().equals(PubSubElementType.PURGE_EVENT.getElementName()))
|
||||||
|
{
|
||||||
|
listener.handlePurge();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ItemsExtension itemsElem = (ItemsExtension)event.getEvent();
|
||||||
|
Collection<? extends PacketExtension> pubItems = itemsElem.getItems();
|
||||||
|
Iterator<RetractItem> it = (Iterator<RetractItem>)pubItems.iterator();
|
||||||
|
List<String> items = new ArrayList<String>(pubItems.size());
|
||||||
|
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
RetractItem item = it.next();
|
||||||
|
items.add(item.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemDeleteEvent eventItems = new ItemDeleteEvent(itemsElem.getNode(), items, getSubscriptionIds(packet));
|
||||||
|
listener.handleDeletedItems(eventItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class translates low level node configuration events into api level objects for
|
||||||
|
* user consumption.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class NodeConfigTranslator implements PacketListener
|
||||||
|
{
|
||||||
|
private NodeConfigListener listener;
|
||||||
|
|
||||||
|
public NodeConfigTranslator(NodeConfigListener eventListener)
|
||||||
|
{
|
||||||
|
listener = eventListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processPacket(Packet packet)
|
||||||
|
{
|
||||||
|
EventElement event = (EventElement)packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
|
||||||
|
ConfigurationEvent config = (ConfigurationEvent)event.getEvent();
|
||||||
|
|
||||||
|
listener.handleNodeConfiguration(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter for {@link PacketListener} to filter out events not specific to the
|
||||||
|
* event type expected for this node.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
class EventContentFilter implements PacketFilter
|
||||||
|
{
|
||||||
|
private String firstElement;
|
||||||
|
private String secondElement;
|
||||||
|
|
||||||
|
EventContentFilter(String elementName)
|
||||||
|
{
|
||||||
|
firstElement = elementName;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventContentFilter(String firstLevelEelement, String secondLevelElement)
|
||||||
|
{
|
||||||
|
firstElement = firstLevelEelement;
|
||||||
|
secondElement = secondLevelElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean accept(Packet packet)
|
||||||
|
{
|
||||||
|
if (!(packet instanceof Message))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
EventElement event = (EventElement)packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
|
||||||
|
|
||||||
|
if (event == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
NodeExtension embedEvent = event.getEvent();
|
||||||
|
|
||||||
|
if (embedEvent == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (embedEvent.getElementName().equals(firstElement))
|
||||||
|
{
|
||||||
|
if (!embedEvent.getNode().equals(getId()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (secondElement == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (embedEvent instanceof EmbeddedPacketExtension)
|
||||||
|
{
|
||||||
|
List<PacketExtension> secondLevelList = ((EmbeddedPacketExtension)embedEvent).getExtensions();
|
||||||
|
|
||||||
|
if (secondLevelList.size() > 0 && secondLevelList.get(0).getElementName().equals(secondElement))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
source/org/jivesoftware/smackx/pubsub/NodeEvent.java
Normal file
19
source/org/jivesoftware/smackx/pubsub/NodeEvent.java
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-05-12
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
abstract public class NodeEvent
|
||||||
|
{
|
||||||
|
private String nodeId;
|
||||||
|
|
||||||
|
protected NodeEvent(String id)
|
||||||
|
{
|
||||||
|
nodeId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNodeId()
|
||||||
|
{
|
||||||
|
return nodeId;
|
||||||
|
}
|
||||||
|
}
|
85
source/org/jivesoftware/smackx/pubsub/NodeExtension.java
Normal file
85
source/org/jivesoftware/smackx/pubsub/NodeExtension.java
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* used on its own as well as a base class for many others, since the
|
||||||
|
* node is a central concept to most pubsub functionality.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class NodeExtension implements PacketExtension
|
||||||
|
{
|
||||||
|
private PubSubElementType element;
|
||||||
|
private String node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a <tt>NodeExtension</tt> with an element name specified
|
||||||
|
* by {@link PubSubElementType} and the specified node id.
|
||||||
|
*
|
||||||
|
* @param elem Defines the element name and namespace
|
||||||
|
* @param nodeId Specifies the id of the node
|
||||||
|
*/
|
||||||
|
public NodeExtension(PubSubElementType elem, String nodeId)
|
||||||
|
{
|
||||||
|
element = elem;
|
||||||
|
this.node = nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a <tt>NodeExtension</tt> with an element name specified
|
||||||
|
* by {@link PubSubElementType}.
|
||||||
|
*
|
||||||
|
* @param elem Defines the element name and namespace
|
||||||
|
*/
|
||||||
|
public NodeExtension(PubSubElementType elem)
|
||||||
|
{
|
||||||
|
this(elem, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the node id
|
||||||
|
*
|
||||||
|
* @return The node id
|
||||||
|
*/
|
||||||
|
public String getNode()
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElementName()
|
||||||
|
{
|
||||||
|
return element.getElementName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespace()
|
||||||
|
{
|
||||||
|
return element.getNamespace().getXmlns();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
return '<' + getElementName() + (node == null ? "" : " node='" + node + '\'') + "/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getClass().getName() + " - content [" + toXML() + "]";
|
||||||
|
}
|
||||||
|
}
|
25
source/org/jivesoftware/smackx/pubsub/NodeType.java
Normal file
25
source/org/jivesoftware/smackx/pubsub/NodeType.java
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the available types of nodes
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum NodeType
|
||||||
|
{
|
||||||
|
leaf,
|
||||||
|
collection;
|
||||||
|
}
|
72
source/org/jivesoftware/smackx/pubsub/OptionsExtension.java
Normal file
72
source/org/jivesoftware/smackx/pubsub/OptionsExtension.java
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.pubsub.util.XmlUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A packet extension representing the <b>options</b> element.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class OptionsExtension extends NodeExtension
|
||||||
|
{
|
||||||
|
protected String jid;
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
public OptionsExtension(String subscriptionJid)
|
||||||
|
{
|
||||||
|
this(subscriptionJid, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OptionsExtension(String subscriptionJid, String nodeId)
|
||||||
|
{
|
||||||
|
this(subscriptionJid, nodeId, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OptionsExtension(String jid, String nodeId, String subscriptionId)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.OPTIONS, nodeId);
|
||||||
|
this.jid = jid;
|
||||||
|
id = subscriptionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJid()
|
||||||
|
{
|
||||||
|
return jid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<");
|
||||||
|
builder.append(getElementName());
|
||||||
|
XmlUtils.appendAttribute(builder, "jid", jid);
|
||||||
|
|
||||||
|
if (getNode() != null)
|
||||||
|
XmlUtils.appendAttribute(builder, "node", getNode());
|
||||||
|
|
||||||
|
if (id != null)
|
||||||
|
XmlUtils.appendAttribute(builder, "subid", id);
|
||||||
|
|
||||||
|
builder.append("/>");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
95
source/org/jivesoftware/smackx/pubsub/PayloadItem.java
Normal file
95
source/org/jivesoftware/smackx/pubsub/PayloadItem.java
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents an item that has been, or will be published to a
|
||||||
|
* pubsub node. An <tt>Item</tt> has several properties that are dependent
|
||||||
|
* on the configuration of the node to which it has been or will be published.
|
||||||
|
*
|
||||||
|
* <h1>An Item received from a node (via {@link LeafNode#getItems()} or {@link LeafNode#addItemEventListener(org.jivesoftware.smackx.pubsub.listener.ItemEventListener)}</b>
|
||||||
|
* <li>Will always have an id (either user or server generated) unless node configuration has both
|
||||||
|
* {@link ConfigureForm#isPersistItems()} and {@link ConfigureForm#isDeliverPayloads()}set to false.
|
||||||
|
* <li>Will have a payload if the node configuration has {@link ConfigureForm#isDeliverPayloads()} set
|
||||||
|
* to true, otherwise it will be null.
|
||||||
|
*
|
||||||
|
* <h1>An Item created to send to a node (via {@link LeafNode#send()} or {@link LeafNode#publish()}</b>
|
||||||
|
* <li>The id is optional, since the server will generate one if necessary, but should be used if it is
|
||||||
|
* meaningful in the context of the node. This value must be unique within the node that it is sent to, since
|
||||||
|
* resending an item with the same id will overwrite the one that already exists if the items are persisted.
|
||||||
|
* <li>Will require payload if the node configuration has {@link ConfigureForm#isDeliverPayloads()} set
|
||||||
|
* to true.
|
||||||
|
*
|
||||||
|
* <p>To customise the payload object being returned from the {@link #getPayload()} method, you can
|
||||||
|
* add a custom parser as explained in {@link ItemProvider}.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class PayloadItem<E extends PacketExtension> extends Item
|
||||||
|
{
|
||||||
|
private E payload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an <tt>Item</tt> with an id and payload.
|
||||||
|
*
|
||||||
|
* @param itemId The id of this item. It can be null if we want the server to set the id.
|
||||||
|
* @param payloadExt A {@link PacketExtension} which represents the payload data.
|
||||||
|
*/
|
||||||
|
public PayloadItem(String itemId, E payloadExt)
|
||||||
|
{
|
||||||
|
super(itemId);
|
||||||
|
|
||||||
|
if (payloadExt == null)
|
||||||
|
throw new IllegalArgumentException("payload cannot be 'null'");
|
||||||
|
payload = payloadExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the payload associated with this <tt>Item</tt>. Customising the payload
|
||||||
|
* parsing from the server can be accomplished as described in {@link ItemProvider}.
|
||||||
|
*
|
||||||
|
* @return The payload as a {@link PacketExtension}.
|
||||||
|
*/
|
||||||
|
public E getPayload()
|
||||||
|
{
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<item");
|
||||||
|
|
||||||
|
if (getId() != null)
|
||||||
|
{
|
||||||
|
builder.append(" id='");
|
||||||
|
builder.append(getId());
|
||||||
|
builder.append("'");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(">");
|
||||||
|
builder.append(payload.toXML());
|
||||||
|
builder.append("</item>");
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getClass().getName() + " | Content [" + toXML() + "]";
|
||||||
|
}
|
||||||
|
}
|
25
source/org/jivesoftware/smackx/pubsub/PresenceState.java
Normal file
25
source/org/jivesoftware/smackx/pubsub/PresenceState.java
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the possible valid presence states for node subscription via
|
||||||
|
* {@link SubscribeForm#getShowValues()}.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum PresenceState
|
||||||
|
{
|
||||||
|
chat, online, away, xa, dnd
|
||||||
|
}
|
77
source/org/jivesoftware/smackx/pubsub/PubSubElementType.java
Normal file
77
source/org/jivesoftware/smackx/pubsub/PubSubElementType.java
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines all the possible element types as defined for all the pubsub
|
||||||
|
* schemas in all 3 namespaces.
|
||||||
|
*
|
||||||
|
* @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),
|
||||||
|
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);
|
||||||
|
|
||||||
|
private String eName;
|
||||||
|
private PubSubNamespace nSpace;
|
||||||
|
|
||||||
|
private PubSubElementType(String elemName, PubSubNamespace ns)
|
||||||
|
{
|
||||||
|
eName = elemName;
|
||||||
|
nSpace = ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PubSubNamespace getNamespace()
|
||||||
|
{
|
||||||
|
return nSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElementName()
|
||||||
|
{
|
||||||
|
return eName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PubSubElementType valueOfFromElemName(String elemName, String namespace)
|
||||||
|
{
|
||||||
|
int index = namespace.lastIndexOf('#');
|
||||||
|
String fragment = (index == -1 ? null : namespace.substring(index+1));
|
||||||
|
|
||||||
|
if (fragment != null)
|
||||||
|
{
|
||||||
|
return valueOf((elemName + '_' + fragment).toUpperCase());
|
||||||
|
}
|
||||||
|
return valueOf(elemName.toUpperCase().replace('-', '_'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
327
source/org/jivesoftware/smackx/pubsub/PubSubManager.java
Normal file
327
source/org/jivesoftware/smackx/pubsub/PubSubManager.java
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smack.packet.IQ.Type;
|
||||||
|
import org.jivesoftware.smackx.Form;
|
||||||
|
import org.jivesoftware.smackx.FormField;
|
||||||
|
import org.jivesoftware.smackx.ServiceDiscoveryManager;
|
||||||
|
import org.jivesoftware.smackx.packet.DiscoverInfo;
|
||||||
|
import org.jivesoftware.smackx.packet.DiscoverItems;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSub;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.SyncPacketSend;
|
||||||
|
import org.jivesoftware.smackx.pubsub.util.NodeUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the starting point for access to the pubsub service. It
|
||||||
|
* will provide access to general information about the service, as
|
||||||
|
* well as create or retrieve pubsub {@link LeafNode} instances. These
|
||||||
|
* instances provide the bulk of the functionality as defined in the
|
||||||
|
* pubsub specification <a href="http://xmpp.org/extensions/xep-0060.html">XEP-0060</a>.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
final public class PubSubManager
|
||||||
|
{
|
||||||
|
private XMPPConnection con;
|
||||||
|
private String to;
|
||||||
|
private Map<String, Node> nodeMap = new ConcurrentHashMap<String, Node>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a pubsub manager associated to the specified connection.
|
||||||
|
*
|
||||||
|
* @param connection The XMPP connection
|
||||||
|
*/
|
||||||
|
public PubSubManager(XMPPConnection connection)
|
||||||
|
{
|
||||||
|
con = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a pubsub manager associated to the specified connection where
|
||||||
|
* the pubsub requests require a specific to address for packets.
|
||||||
|
*
|
||||||
|
* @param connection The XMPP connection
|
||||||
|
* @param toAddress The pubsub specific to address (required for some servers)
|
||||||
|
*/
|
||||||
|
public PubSubManager(XMPPConnection connection, String toAddress)
|
||||||
|
{
|
||||||
|
con = connection;
|
||||||
|
to = toAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instant node, if supported.
|
||||||
|
*
|
||||||
|
* @return The node that was created
|
||||||
|
* @exception XMPPException
|
||||||
|
*/
|
||||||
|
public LeafNode createNode()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub reply = (PubSub)sendPubsubPacket(Type.SET, new NodeExtension(PubSubElementType.CREATE));
|
||||||
|
NodeExtension elem = (NodeExtension)reply.getExtension("create", PubSubNamespace.BASIC.getXmlns());
|
||||||
|
|
||||||
|
LeafNode newNode = new LeafNode(con, elem.getNode());
|
||||||
|
newNode.setTo(to);
|
||||||
|
nodeMap.put(newNode.getId(), newNode);
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a node with default configuration.
|
||||||
|
*
|
||||||
|
* @param id The id of the node, which must be unique within the
|
||||||
|
* pubsub service
|
||||||
|
* @return The node that was created
|
||||||
|
* @exception XMPPException
|
||||||
|
*/
|
||||||
|
public LeafNode createNode(String id)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return (LeafNode)createNode(id, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a node with specified configuration.
|
||||||
|
*
|
||||||
|
* Note: This is the only way to create a collection node.
|
||||||
|
*
|
||||||
|
* @param name The name of the node, which must be unique within the
|
||||||
|
* pubsub service
|
||||||
|
* @param config The configuration for the node
|
||||||
|
* @return The node that was created
|
||||||
|
* @exception XMPPException
|
||||||
|
*/
|
||||||
|
public Node createNode(String name, Form config)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub request = createPubsubPacket(to, Type.SET, new NodeExtension(PubSubElementType.CREATE, name));
|
||||||
|
boolean isLeafNode = true;
|
||||||
|
|
||||||
|
if (config != null)
|
||||||
|
{
|
||||||
|
request.addExtension(new FormNode(FormNodeType.CONFIGURE, config));
|
||||||
|
FormField nodeTypeField = config.getField(ConfigureNodeFields.node_type.getFieldName());
|
||||||
|
|
||||||
|
if (nodeTypeField != null)
|
||||||
|
isLeafNode = nodeTypeField.getValues().next().equals(NodeType.leaf.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errors will cause exceptions in getReply, so it only returns
|
||||||
|
// on success.
|
||||||
|
sendPubsubPacket(con, to, Type.SET, request);
|
||||||
|
Node newNode = isLeafNode ? new LeafNode(con, name) : new CollectionNode(con, name);
|
||||||
|
newNode.setTo(to);
|
||||||
|
nodeMap.put(newNode.getId(), newNode);
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the requested node, if it exists. It will throw an
|
||||||
|
* exception if it does not.
|
||||||
|
*
|
||||||
|
* @param id - The unique id of the node
|
||||||
|
* @return the node
|
||||||
|
* @throws XMPPException The node does not exist
|
||||||
|
*/
|
||||||
|
public Node getNode(String id)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
Node node = nodeMap.get(id);
|
||||||
|
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
DiscoverInfo info = new DiscoverInfo();
|
||||||
|
info.setTo(to);
|
||||||
|
info.setNode(id);
|
||||||
|
|
||||||
|
DiscoverInfo infoReply = (DiscoverInfo)SyncPacketSend.getReply(con, info);
|
||||||
|
|
||||||
|
if (infoReply.getIdentities().next().getType().equals(NodeType.leaf.toString()))
|
||||||
|
node = new LeafNode(con, id);
|
||||||
|
else
|
||||||
|
node = new CollectionNode(con, id);
|
||||||
|
node.setTo(to);
|
||||||
|
nodeMap.put(id, node);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the nodes that currently exist as a child of the specified
|
||||||
|
* collection node. If the service does not support collection nodes
|
||||||
|
* then all nodes will be returned.
|
||||||
|
*
|
||||||
|
* To retrieve contents of the root collection node (if it exists),
|
||||||
|
* or there is no root collection node, pass null as the nodeId.
|
||||||
|
*
|
||||||
|
* @param nodeId - The id of the collection node for which the child
|
||||||
|
* nodes will be returned.
|
||||||
|
* @return {@link DiscoverItems} representing the existing nodes
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public DiscoverItems discoverNodes(String nodeId)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
DiscoverItems items = new DiscoverItems();
|
||||||
|
|
||||||
|
if (nodeId != null)
|
||||||
|
items.setNode(nodeId);
|
||||||
|
items.setTo(to);
|
||||||
|
DiscoverItems nodeItems = (DiscoverItems)SyncPacketSend.getReply(con, items);
|
||||||
|
return nodeItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the subscriptions on the root node.
|
||||||
|
*
|
||||||
|
* @return List of exceptions
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public List<Subscription> getSubscriptions()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
Packet reply = sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.SUBSCRIPTIONS));
|
||||||
|
SubscriptionsExtension subElem = (SubscriptionsExtension)reply.getExtension(PubSubElementType.SUBSCRIPTIONS.getElementName(), PubSubElementType.SUBSCRIPTIONS.getNamespace().getXmlns());
|
||||||
|
return subElem.getSubscriptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the affiliations on the root node.
|
||||||
|
*
|
||||||
|
* @return List of affiliations
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public List<Affiliation> getAffiliations()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PubSub reply = (PubSub)sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.AFFILIATIONS));
|
||||||
|
AffiliationsExtension listElem = (AffiliationsExtension)reply.getExtension(PubSubElementType.AFFILIATIONS);
|
||||||
|
return listElem.getAffiliations();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the specified node
|
||||||
|
*
|
||||||
|
* @param nodeId
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public void deleteNode(String nodeId)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
sendPubsubPacket(Type.SET, new NodeExtension(PubSubElementType.DELETE, nodeId), PubSubElementType.DELETE.getNamespace());
|
||||||
|
nodeMap.remove(nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default settings for Node configuration.
|
||||||
|
*
|
||||||
|
* @return configuration form containing the default settings.
|
||||||
|
*/
|
||||||
|
public ConfigureForm getDefaultConfiguration()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
// Errors will cause exceptions in getReply, so it only returns
|
||||||
|
// on success.
|
||||||
|
PubSub reply = (PubSub)sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.DEFAULT), PubSubElementType.DEFAULT.getNamespace());
|
||||||
|
return NodeUtils.getFormFromPacket(reply, PubSubElementType.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the supported features of the servers pubsub implementation
|
||||||
|
* as a standard {@link DiscoverInfo} instance.
|
||||||
|
*
|
||||||
|
* @return The supported features
|
||||||
|
*
|
||||||
|
* @throws XMPPException
|
||||||
|
*/
|
||||||
|
public DiscoverInfo getSupportedFeatures()
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
ServiceDiscoveryManager mgr = ServiceDiscoveryManager.getInstanceFor(con);
|
||||||
|
return mgr.discoverInfo(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Packet sendPubsubPacket(Type type, PacketExtension ext, PubSubNamespace ns)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return sendPubsubPacket(con, to, type, ext, ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Packet sendPubsubPacket(Type type, PacketExtension ext)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return sendPubsubPacket(type, ext, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PubSub createPubsubPacket(String to, Type type, PacketExtension ext)
|
||||||
|
{
|
||||||
|
return createPubsubPacket(to, type, ext, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PubSub createPubsubPacket(String to, Type type, PacketExtension ext, PubSubNamespace ns)
|
||||||
|
{
|
||||||
|
PubSub request = new PubSub();
|
||||||
|
request.setTo(to);
|
||||||
|
request.setType(type);
|
||||||
|
|
||||||
|
if (ns != null)
|
||||||
|
{
|
||||||
|
request.setPubSubNamespace(ns);
|
||||||
|
}
|
||||||
|
request.addExtension(ext);
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Packet sendPubsubPacket(XMPPConnection con, String to, Type type, PacketExtension ext)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return sendPubsubPacket(con, to, type, ext, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Packet sendPubsubPacket(XMPPConnection con, String to, Type type, PacketExtension ext, PubSubNamespace ns)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return SyncPacketSend.getReply(con, createPubsubPacket(to, type, ext, ns));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Packet sendPubsubPacket(XMPPConnection con, String to, Type type, PubSub packet)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return sendPubsubPacket(con, to, type, packet, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Packet sendPubsubPacket(XMPPConnection con, String to, Type type, PubSub packet, PubSubNamespace ns)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return SyncPacketSend.getReply(con, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
70
source/org/jivesoftware/smackx/pubsub/PublishItem.java
Normal file
70
source/org/jivesoftware/smackx/pubsub/PublishItem.java
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a request to publish an item(s) to a specific node.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class PublishItem <T extends Item> extends NodeExtension
|
||||||
|
{
|
||||||
|
protected Collection<T> items;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a request to publish an item to a node.
|
||||||
|
*
|
||||||
|
* @param nodeId The node to publish to
|
||||||
|
* @param toPublish The {@link Item} to publish
|
||||||
|
*/
|
||||||
|
public PublishItem(String nodeId, T toPublish)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.PUBLISH, nodeId);
|
||||||
|
items = new ArrayList<T>(1);
|
||||||
|
items.add(toPublish);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a request to publish multiple items to a node.
|
||||||
|
*
|
||||||
|
* @param nodeId The node to publish to
|
||||||
|
* @param toPublish The list of {@link Item} to publish
|
||||||
|
*/
|
||||||
|
public PublishItem(String nodeId, Collection<T> toPublish)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.PUBLISH, nodeId);
|
||||||
|
items = toPublish;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<");
|
||||||
|
builder.append(getElementName());
|
||||||
|
builder.append(" node='");
|
||||||
|
builder.append(getNode());
|
||||||
|
builder.append("'>");
|
||||||
|
|
||||||
|
for (Item item : items)
|
||||||
|
{
|
||||||
|
builder.append(item.toXML());
|
||||||
|
}
|
||||||
|
builder.append("</publish>");
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
32
source/org/jivesoftware/smackx/pubsub/PublishModel.java
Normal file
32
source/org/jivesoftware/smackx/pubsub/PublishModel.java
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines who may publish to a node. Denotes possible values
|
||||||
|
* for {@link ConfigureForm#setPublishModel(PublishModel)}.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum PublishModel
|
||||||
|
{
|
||||||
|
/** Only publishers may publish */
|
||||||
|
publishers,
|
||||||
|
|
||||||
|
/** Only subscribers may publish */
|
||||||
|
subscribers,
|
||||||
|
|
||||||
|
/** Anyone may publish */
|
||||||
|
open;
|
||||||
|
}
|
59
source/org/jivesoftware/smackx/pubsub/RetractItem.java
Normal file
59
source/org/jivesoftware/smackx/pubsub/RetractItem.java
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents and item that has been deleted from a node.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class RetractItem implements PacketExtension
|
||||||
|
{
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a <tt>RetractItem</tt> with the specified id.
|
||||||
|
*
|
||||||
|
* @param itemId The id if the item deleted
|
||||||
|
*/
|
||||||
|
public RetractItem(String itemId)
|
||||||
|
{
|
||||||
|
if (itemId == null)
|
||||||
|
throw new IllegalArgumentException("itemId must not be 'null'");
|
||||||
|
id = itemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElementName()
|
||||||
|
{
|
||||||
|
return "retract";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespace()
|
||||||
|
{
|
||||||
|
return PubSubNamespace.EVENT.getXmlns();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
return "<retract id='" + id + "'/>";
|
||||||
|
}
|
||||||
|
}
|
65
source/org/jivesoftware/smackx/pubsub/SimplePayload.java
Normal file
65
source/org/jivesoftware/smackx/pubsub/SimplePayload.java
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default payload representation for {@link Item#getPayload()}. It simply
|
||||||
|
* stores the XML payload as a string.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class SimplePayload implements PacketExtension
|
||||||
|
{
|
||||||
|
private String elemName;
|
||||||
|
private String ns;
|
||||||
|
private String payload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a <tt>SimplePayload</tt> object with the specified element name,
|
||||||
|
* namespace and content. The content must be well formed XML.
|
||||||
|
*
|
||||||
|
* @param elementName The root element name (of the payload)
|
||||||
|
* @param namespace The namespace of the payload, null if there is none
|
||||||
|
* @param xmlPayload The payload data
|
||||||
|
*/
|
||||||
|
public SimplePayload(String elementName, String namespace, String xmlPayload)
|
||||||
|
{
|
||||||
|
elemName = elementName;
|
||||||
|
payload = xmlPayload;
|
||||||
|
ns = namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElementName()
|
||||||
|
{
|
||||||
|
return elemName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespace()
|
||||||
|
{
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getClass().getName() + "payload [" + toXML() + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a request to subscribe to a node.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class SubscribeExtension extends NodeExtension
|
||||||
|
{
|
||||||
|
protected String jid;
|
||||||
|
|
||||||
|
public SubscribeExtension(String subscribeJid)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.SUBSCRIBE);
|
||||||
|
jid = subscribeJid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscribeExtension(String subscribeJid, String nodeId)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.SUBSCRIBE, nodeId);
|
||||||
|
jid = subscribeJid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJid()
|
||||||
|
{
|
||||||
|
return jid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<");
|
||||||
|
builder.append(getElementName());
|
||||||
|
|
||||||
|
if (getNode() != null)
|
||||||
|
{
|
||||||
|
builder.append(" node='");
|
||||||
|
builder.append(getNode());
|
||||||
|
builder.append("'");
|
||||||
|
}
|
||||||
|
builder.append(" jid='");
|
||||||
|
builder.append(getJid());
|
||||||
|
builder.append("'/>");
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
242
source/org/jivesoftware/smackx/pubsub/SubscribeForm.java
Normal file
242
source/org/jivesoftware/smackx/pubsub/SubscribeForm.java
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.UnknownFormatConversionException;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.Form;
|
||||||
|
import org.jivesoftware.smackx.FormField;
|
||||||
|
import org.jivesoftware.smackx.packet.DataForm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A decorator for a {@link Form} to easily enable reading and updating
|
||||||
|
* of subscription options. All operations read or update the underlying {@link DataForm}.
|
||||||
|
*
|
||||||
|
* <p>Unlike the {@link Form}.setAnswer(XXX)} methods, which throw an exception if the field does not
|
||||||
|
* exist, all <b>SubscribeForm.setXXX</b> methods will create the field in the wrapped form
|
||||||
|
* if it does not already exist.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class SubscribeForm extends Form
|
||||||
|
{
|
||||||
|
private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||||
|
|
||||||
|
public SubscribeForm(DataForm configDataForm)
|
||||||
|
{
|
||||||
|
super(configDataForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscribeForm(Form subscribeOptionsForm)
|
||||||
|
{
|
||||||
|
super(subscribeOptionsForm.getDataFormToSend());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscribeForm(FormType formType)
|
||||||
|
{
|
||||||
|
super(formType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if an entity wants to receive notifications.
|
||||||
|
*
|
||||||
|
* @return true if want to receive, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isDeliverOn()
|
||||||
|
{
|
||||||
|
return parseBoolean(getFieldValue(SubscribeOptionFields.deliver));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether an entity wants to receive notifications.
|
||||||
|
*
|
||||||
|
* @param deliverNotifications
|
||||||
|
*/
|
||||||
|
public void setDeliverOn(boolean deliverNotifications)
|
||||||
|
{
|
||||||
|
addField(SubscribeOptionFields.deliver, FormField.TYPE_BOOLEAN);
|
||||||
|
setAnswer(SubscribeOptionFields.deliver.getFieldName(), deliverNotifications);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if notifications should be delivered as aggregations or not.
|
||||||
|
*
|
||||||
|
* @return true to aggregate, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isDigestOn()
|
||||||
|
{
|
||||||
|
return parseBoolean(getFieldValue(SubscribeOptionFields.digest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether notifications should be delivered as aggregations or not.
|
||||||
|
*
|
||||||
|
* @param digestOn true to aggregate, false otherwise
|
||||||
|
*/
|
||||||
|
public void setDigestOn(boolean digestOn)
|
||||||
|
{
|
||||||
|
addField(SubscribeOptionFields.deliver, FormField.TYPE_BOOLEAN);
|
||||||
|
setAnswer(SubscribeOptionFields.deliver.getFieldName(), digestOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum number of milliseconds between sending notification digests
|
||||||
|
*
|
||||||
|
* @return The frequency in milliseconds
|
||||||
|
*/
|
||||||
|
public int getDigestFrequency()
|
||||||
|
{
|
||||||
|
return Integer.parseInt(getFieldValue(SubscribeOptionFields.digest_frequency));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the minimum number of milliseconds between sending notification digests
|
||||||
|
*
|
||||||
|
* @param frequency The frequency in milliseconds
|
||||||
|
*/
|
||||||
|
public void setDigestFrequency(int frequency)
|
||||||
|
{
|
||||||
|
addField(SubscribeOptionFields.digest_frequency, FormField.TYPE_TEXT_SINGLE);
|
||||||
|
setAnswer(SubscribeOptionFields.digest_frequency.getFieldName(), frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time at which the leased subscription will expire, or has expired.
|
||||||
|
*
|
||||||
|
* @return The expiry date
|
||||||
|
*/
|
||||||
|
public Date getExpiry()
|
||||||
|
{
|
||||||
|
String dateTime = getFieldValue(SubscribeOptionFields.expire);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return format.parse(dateTime);
|
||||||
|
}
|
||||||
|
catch (ParseException e)
|
||||||
|
{
|
||||||
|
UnknownFormatConversionException exc = new UnknownFormatConversionException(dateTime);
|
||||||
|
exc.initCause(e);
|
||||||
|
throw exc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the time at which the leased subscription will expire, or has expired.
|
||||||
|
*
|
||||||
|
* @param expire The expiry date
|
||||||
|
*/
|
||||||
|
public void setExpiry(Date expire)
|
||||||
|
{
|
||||||
|
addField(SubscribeOptionFields.expire, FormField.TYPE_TEXT_SINGLE);
|
||||||
|
setAnswer(SubscribeOptionFields.expire.getFieldName(), format.format(expire));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the entity wants to receive an XMPP message body in
|
||||||
|
* addition to the payload format.
|
||||||
|
*
|
||||||
|
* @return true to receive the message body, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isIncludeBody()
|
||||||
|
{
|
||||||
|
return parseBoolean(getFieldValue(SubscribeOptionFields.include_body));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the entity wants to receive an XMPP message body in
|
||||||
|
* addition to the payload format.
|
||||||
|
*
|
||||||
|
* @param include true to receive the message body, false otherwise
|
||||||
|
*/
|
||||||
|
public void setIncludeBody(boolean include)
|
||||||
|
{
|
||||||
|
addField(SubscribeOptionFields.include_body, FormField.TYPE_BOOLEAN);
|
||||||
|
setAnswer(SubscribeOptionFields.include_body.getFieldName(), include);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link PresenceState} for which an entity wants to receive
|
||||||
|
* notifications.
|
||||||
|
*
|
||||||
|
* @return iterator over the list of states
|
||||||
|
*/
|
||||||
|
public Iterator<PresenceState> getShowValues()
|
||||||
|
{
|
||||||
|
ArrayList<PresenceState> result = new ArrayList<PresenceState>(5);
|
||||||
|
Iterator<String > it = getFieldValues(SubscribeOptionFields.show_values);
|
||||||
|
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
String state = it.next();
|
||||||
|
result.add(PresenceState.valueOf(state));
|
||||||
|
}
|
||||||
|
return result.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the list of {@link PresenceState} for which an entity wants
|
||||||
|
* to receive notifications.
|
||||||
|
*
|
||||||
|
* @param stateValues The list of states
|
||||||
|
*/
|
||||||
|
public void setShowValues(Collection<PresenceState> stateValues)
|
||||||
|
{
|
||||||
|
ArrayList<String> values = new ArrayList<String>(stateValues.size());
|
||||||
|
|
||||||
|
for (PresenceState state : stateValues)
|
||||||
|
{
|
||||||
|
values.add(state.toString());
|
||||||
|
}
|
||||||
|
addField(SubscribeOptionFields.show_values, FormField.TYPE_LIST_MULTI);
|
||||||
|
setAnswer(SubscribeOptionFields.show_values.getFieldName(), values);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static private boolean parseBoolean(String fieldValue)
|
||||||
|
{
|
||||||
|
return ("1".equals(fieldValue) || "true".equals(fieldValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFieldValue(SubscribeOptionFields field)
|
||||||
|
{
|
||||||
|
FormField formField = getField(field.getFieldName());
|
||||||
|
|
||||||
|
return formField.getValues().next();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Iterator<String> getFieldValues(SubscribeOptionFields field)
|
||||||
|
{
|
||||||
|
FormField formField = getField(field.getFieldName());
|
||||||
|
|
||||||
|
return formField.getValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addField(SubscribeOptionFields nodeField, String type)
|
||||||
|
{
|
||||||
|
String fieldName = nodeField.getFieldName();
|
||||||
|
|
||||||
|
if (getField(fieldName) == null)
|
||||||
|
{
|
||||||
|
FormField field = new FormField(fieldName);
|
||||||
|
field.setType(type);
|
||||||
|
addField(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the possible field options for a subscribe options form as defined
|
||||||
|
* by <a href="http://xmpp.org/extensions/xep-0060.html#registrar-formtypes-subscribe">Section 16.4.2</a>.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum SubscribeOptionFields
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Whether an entity wants to receive or disable notifications
|
||||||
|
*
|
||||||
|
* <p><b>Value: boolean</b></p>
|
||||||
|
*/
|
||||||
|
deliver,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether an entity wants to receive digests (aggregations) of
|
||||||
|
* notifications or all notifications individually.
|
||||||
|
*
|
||||||
|
* <p><b>Value: boolean</b></p>
|
||||||
|
*/
|
||||||
|
digest,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum number of seconds between sending any two notifications digests
|
||||||
|
*
|
||||||
|
* <p><b>Value: int</b></p>
|
||||||
|
*/
|
||||||
|
digest_frequency,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DateTime at which a leased subsscription will end ro has ended.
|
||||||
|
*
|
||||||
|
* <p><b>Value: {@link Calendar}</b></p>
|
||||||
|
*/
|
||||||
|
expire,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether an entity wants to receive an XMPP message body in addition to
|
||||||
|
* the payload format.
|
||||||
|
*
|
||||||
|
* <p><b>Value: boolean</b></p>
|
||||||
|
*/
|
||||||
|
include_body,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The presence states for which an entity wants to receive notifications.
|
||||||
|
*
|
||||||
|
* <p><b>Value: {@link PresenceState}</b></p>
|
||||||
|
*/
|
||||||
|
show_values,
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p><b>Value: </b></p>
|
||||||
|
*/
|
||||||
|
subscription_type,
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* <p><b>Value: </b></p>
|
||||||
|
*/
|
||||||
|
subscription_depth;
|
||||||
|
|
||||||
|
public String getFieldName()
|
||||||
|
{
|
||||||
|
if (this == show_values)
|
||||||
|
return "pubsub#" + toString().replace('_', '-');
|
||||||
|
return "pubsub#" + toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
static public SubscribeOptionFields valueOfFromElement(String elementName)
|
||||||
|
{
|
||||||
|
String portion = elementName.substring(elementName.lastIndexOf('#' + 1));
|
||||||
|
|
||||||
|
if ("show-values".equals(portion))
|
||||||
|
return show_values;
|
||||||
|
else
|
||||||
|
return valueOf(portion);
|
||||||
|
}
|
||||||
|
}
|
160
source/org/jivesoftware/smackx/pubsub/Subscription.java
Normal file
160
source/org/jivesoftware/smackx/pubsub/Subscription.java
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a subscription to node for both requests and replies.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class Subscription extends NodeExtension
|
||||||
|
{
|
||||||
|
protected String jid;
|
||||||
|
protected String id;
|
||||||
|
protected State state;
|
||||||
|
protected boolean configRequired = false;
|
||||||
|
|
||||||
|
public enum State
|
||||||
|
{
|
||||||
|
subscribed, unconfigured, pending, none
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to constructs a subscription request to the root node with the specified
|
||||||
|
* JID.
|
||||||
|
*
|
||||||
|
* @param subscriptionJid The subscriber JID
|
||||||
|
*/
|
||||||
|
public Subscription(String subscriptionJid)
|
||||||
|
{
|
||||||
|
this(subscriptionJid, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to constructs a subscription request to the specified node with the specified
|
||||||
|
* JID.
|
||||||
|
*
|
||||||
|
* @param subscriptionJid The subscriber JID
|
||||||
|
* @param nodeId The node id
|
||||||
|
*/
|
||||||
|
public Subscription(String subscriptionJid, String nodeId)
|
||||||
|
{
|
||||||
|
this(subscriptionJid, nodeId, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a representation of a subscription reply to the specified node
|
||||||
|
* and JID. The server will have supplied the subscription id and current state.
|
||||||
|
*
|
||||||
|
* @param jid The JID the request was made under
|
||||||
|
* @param nodeId The node subscribed to
|
||||||
|
* @param subscriptionId The id of this subscription
|
||||||
|
* @param state The current state of the subscription
|
||||||
|
*/
|
||||||
|
public Subscription(String jid, String nodeId, String subscriptionId, State state)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.SUBSCRIPTION, nodeId);
|
||||||
|
this.jid = jid;
|
||||||
|
id = subscriptionId;
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a representation of a subscription reply to the specified node
|
||||||
|
* and JID. The server will have supplied the subscription id and current state
|
||||||
|
* and whether the subscription need to be configured.
|
||||||
|
*
|
||||||
|
* @param jid The JID the request was made under
|
||||||
|
* @param nodeId The node subscribed to
|
||||||
|
* @param subscriptionId The id of this subscription
|
||||||
|
* @param state The current state of the subscription
|
||||||
|
* @param configRequired Is configuration required to complete the subscription
|
||||||
|
*/
|
||||||
|
public Subscription(String jid, String nodeId, String subscriptionId, State state, boolean configRequired)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.SUBSCRIPTION, nodeId);
|
||||||
|
this.jid = jid;
|
||||||
|
id = subscriptionId;
|
||||||
|
this.state = state;
|
||||||
|
this.configRequired = configRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the JID the subscription is created for
|
||||||
|
*
|
||||||
|
* @return The JID
|
||||||
|
*/
|
||||||
|
public String getJid()
|
||||||
|
{
|
||||||
|
return jid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the subscription id
|
||||||
|
*
|
||||||
|
* @return The subscription id
|
||||||
|
*/
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current subscription state.
|
||||||
|
*
|
||||||
|
* @return Current subscription state
|
||||||
|
*/
|
||||||
|
public State getState()
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This value is only relevant when the {@link #getState()} is {@link State#unconfigured}
|
||||||
|
*
|
||||||
|
* @return true if configuration is required, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isConfigRequired()
|
||||||
|
{
|
||||||
|
return configRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<subscription");
|
||||||
|
appendAttribute(builder, "jid", jid);
|
||||||
|
|
||||||
|
if (getNode() != null)
|
||||||
|
appendAttribute(builder, "node", getNode());
|
||||||
|
|
||||||
|
if (id != null)
|
||||||
|
appendAttribute(builder, "subid", id);
|
||||||
|
|
||||||
|
if (state != null)
|
||||||
|
appendAttribute(builder, "subscription", state.toString());
|
||||||
|
|
||||||
|
builder.append("/>");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendAttribute(StringBuilder builder, String att, String value)
|
||||||
|
{
|
||||||
|
builder.append(" ");
|
||||||
|
builder.append(att);
|
||||||
|
builder.append("='");
|
||||||
|
builder.append(value);
|
||||||
|
builder.append("'");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
75
source/org/jivesoftware/smackx/pubsub/SubscriptionEvent.java
Normal file
75
source/org/jivesoftware/smackx/pubsub/SubscriptionEvent.java
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class to represents events that are associated to subscriptions.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
abstract public class SubscriptionEvent extends NodeEvent
|
||||||
|
{
|
||||||
|
private List<String> subIds = Collections.EMPTY_LIST;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an event with no subscription id's. This can
|
||||||
|
* occur when there is only one subscription to a node. The
|
||||||
|
* event may or may not report the subscription id along
|
||||||
|
* with the event.
|
||||||
|
*
|
||||||
|
* @param nodeId The id of the node the event came from
|
||||||
|
*/
|
||||||
|
protected SubscriptionEvent(String nodeId)
|
||||||
|
{
|
||||||
|
super(nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an event with multiple subscriptions.
|
||||||
|
*
|
||||||
|
* @param nodeId The id of the node the event came from
|
||||||
|
* @param subscriptionIds The list of subscription id's
|
||||||
|
*/
|
||||||
|
protected SubscriptionEvent(String nodeId, List<String> subscriptionIds)
|
||||||
|
{
|
||||||
|
super(nodeId);
|
||||||
|
|
||||||
|
if (subscriptionIds != null)
|
||||||
|
subIds = subscriptionIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the subscriptions this event is associated with.
|
||||||
|
*
|
||||||
|
* @return List of subscription id's
|
||||||
|
*/
|
||||||
|
public List<String> getSubscriptions()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableList(subIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the list of subscription id's for this event.
|
||||||
|
*
|
||||||
|
* @param subscriptionIds The list of subscription id's
|
||||||
|
*/
|
||||||
|
protected void setSubscriptions(List<String> subscriptionIds)
|
||||||
|
{
|
||||||
|
if (subscriptionIds != null)
|
||||||
|
subIds = subscriptionIds;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the element holding the list of subscription elements.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class SubscriptionsExtension extends NodeExtension
|
||||||
|
{
|
||||||
|
protected List<Subscription> items = Collections.EMPTY_LIST;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscriptions to the root node
|
||||||
|
*
|
||||||
|
* @param subList The list of subscriptions
|
||||||
|
*/
|
||||||
|
public SubscriptionsExtension(List<Subscription> subList)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.SUBSCRIPTIONS);
|
||||||
|
|
||||||
|
if (subList != null)
|
||||||
|
items = subList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscriptions to the specified node.
|
||||||
|
*
|
||||||
|
* @param nodeId The node subscribed to
|
||||||
|
* @param subList The list of subscriptions
|
||||||
|
*/
|
||||||
|
public SubscriptionsExtension(String nodeId, List<Subscription> subList)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.SUBSCRIPTIONS, nodeId);
|
||||||
|
|
||||||
|
if (subList != null)
|
||||||
|
items = subList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of subscriptions.
|
||||||
|
*
|
||||||
|
* @return List of subscriptions
|
||||||
|
*/
|
||||||
|
public List<Subscription> getSubscriptions()
|
||||||
|
{
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.size() == 0))
|
||||||
|
{
|
||||||
|
return super.toXML();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<");
|
||||||
|
builder.append(getElementName());
|
||||||
|
|
||||||
|
if (getNode() != null)
|
||||||
|
{
|
||||||
|
builder.append(" node='");
|
||||||
|
builder.append(getNode());
|
||||||
|
builder.append("'");
|
||||||
|
}
|
||||||
|
builder.append(">");
|
||||||
|
|
||||||
|
for (Subscription item : items)
|
||||||
|
{
|
||||||
|
builder.append(item.toXML());
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append("</");
|
||||||
|
builder.append(getElementName());
|
||||||
|
builder.append(">");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.pubsub.util.XmlUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an unsubscribe element.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class UnsubscribeExtension extends NodeExtension
|
||||||
|
{
|
||||||
|
protected String jid;
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
public UnsubscribeExtension(String subscriptionJid)
|
||||||
|
{
|
||||||
|
this(subscriptionJid, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnsubscribeExtension(String subscriptionJid, String nodeId)
|
||||||
|
{
|
||||||
|
this(subscriptionJid, nodeId, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnsubscribeExtension(String jid, String nodeId, String subscriptionId)
|
||||||
|
{
|
||||||
|
super(PubSubElementType.UNSUBSCRIBE, nodeId);
|
||||||
|
this.jid = jid;
|
||||||
|
id = subscriptionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJid()
|
||||||
|
{
|
||||||
|
return jid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder("<");
|
||||||
|
builder.append(getElementName());
|
||||||
|
XmlUtils.appendAttribute(builder, "jid", jid);
|
||||||
|
|
||||||
|
if (getNode() != null)
|
||||||
|
XmlUtils.appendAttribute(builder, "node", getNode());
|
||||||
|
|
||||||
|
if (id != null)
|
||||||
|
XmlUtils.appendAttribute(builder, "subid", id);
|
||||||
|
|
||||||
|
builder.append("/>");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.listener;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.pubsub.ItemDeleteEvent;
|
||||||
|
import org.jivesoftware.smackx.pubsub.LeafNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the listener for item deletion events from a node.
|
||||||
|
*
|
||||||
|
* @see LeafNode#addItemDeleteListener(ItemDeleteListener)
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public interface ItemDeleteListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called when items are deleted from a node the listener is
|
||||||
|
* registered with.
|
||||||
|
*
|
||||||
|
* @param items The event with item deletion details
|
||||||
|
*/
|
||||||
|
void handleDeletedItems(ItemDeleteEvent items);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when <b>all</b> items are deleted from a node the listener is
|
||||||
|
* registered with.
|
||||||
|
*/
|
||||||
|
void handlePurge();
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.listener;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.pubsub.Item;
|
||||||
|
import org.jivesoftware.smackx.pubsub.ItemPublishEvent;
|
||||||
|
import org.jivesoftware.smackx.pubsub.LeafNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the listener for items being published to a node.
|
||||||
|
*
|
||||||
|
* @see LeafNode#addItemEventListener(ItemEventListener)
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public interface ItemEventListener <T extends Item>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called whenever an item is published to the node the listener
|
||||||
|
* is registered with.
|
||||||
|
*
|
||||||
|
* @param items The publishing details.
|
||||||
|
*/
|
||||||
|
void handlePublishedItems(ItemPublishEvent<T> items);
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.listener;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.pubsub.ConfigurationEvent;
|
||||||
|
import org.jivesoftware.smackx.pubsub.LeafNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the listener for a node being configured.
|
||||||
|
*
|
||||||
|
* @see LeafNode#addConfigurationListener(NodeConfigListener)
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public interface NodeConfigListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called whenever the node the listener
|
||||||
|
* is registered with is configured.
|
||||||
|
*
|
||||||
|
* @param config The configuration details.
|
||||||
|
*/
|
||||||
|
void handleNodeConfiguration(ConfigurationEvent config);
|
||||||
|
}
|
106
source/org/jivesoftware/smackx/pubsub/packet/PubSub.java
Normal file
106
source/org/jivesoftware/smackx/pubsub/packet/PubSub.java
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.packet;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.pubsub.PubSubElementType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The standard PubSub extension of an {@link IQ} packet. This is the topmost
|
||||||
|
* element of all pubsub requests and replies as defined in the <a href="http://xmpp.org/extensions/xep-0060">Publish-Subscribe</a>
|
||||||
|
* specification.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class PubSub extends IQ
|
||||||
|
{
|
||||||
|
private PubSubNamespace ns = PubSubNamespace.BASIC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the XML element name of the extension sub-packet root element.
|
||||||
|
*
|
||||||
|
* @return the XML element name of the packet extension.
|
||||||
|
*/
|
||||||
|
public String getElementName() {
|
||||||
|
return "pubsub";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the XML namespace of the extension sub-packet root element.
|
||||||
|
* According the specification the namespace is
|
||||||
|
* http://jabber.org/protocol/pubsub with a specific fragment depending
|
||||||
|
* on the request. The namespace is defined at <a href="http://xmpp.org/registrar/namespaces.html">XMPP Registrar</a> at
|
||||||
|
*
|
||||||
|
* The default value has no fragment.
|
||||||
|
*
|
||||||
|
* @return the XML namespace of the packet extension.
|
||||||
|
*/
|
||||||
|
public String getNamespace()
|
||||||
|
{
|
||||||
|
return ns.getXmlns();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the namespace for the packet if it something other than the default
|
||||||
|
* case of {@link PubSubNamespace#BASIC}. The {@link #getNamespace()} method will return
|
||||||
|
* the result of calling {@link PubSubNamespace#getXmlns()} on the specified enum.
|
||||||
|
*
|
||||||
|
* @param ns - The new value for the namespace.
|
||||||
|
*/
|
||||||
|
public void setPubSubNamespace(PubSubNamespace ns)
|
||||||
|
{
|
||||||
|
this.ns = ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketExtension getExtension(PubSubElementType elem)
|
||||||
|
{
|
||||||
|
return getExtension(elem.getElementName(), elem.getNamespace().getXmlns());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current value of the namespace. The {@link #getNamespace()} method will return
|
||||||
|
* the result of calling {@link PubSubNamespace#getXmlns()} this value.
|
||||||
|
*
|
||||||
|
* @return The current value of the namespace.
|
||||||
|
*/
|
||||||
|
public PubSubNamespace getPubSubNamespace()
|
||||||
|
{
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the XML representation of a pubsub element according the specification.
|
||||||
|
*
|
||||||
|
* The XML representation will be inside of an iq packet like
|
||||||
|
* in the following example:
|
||||||
|
* <pre>
|
||||||
|
* <iq type='set' id="MlIpV-4" to="pubsub.gato.home" from="gato3@gato.home/Smack">
|
||||||
|
* <pubsub xmlns="http://jabber.org/protocol/pubsub">
|
||||||
|
* :
|
||||||
|
* Specific request extension
|
||||||
|
* :
|
||||||
|
* </pubsub>
|
||||||
|
* </iq>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public String getChildElementXML() {
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append("\">");
|
||||||
|
buf.append(getExtensionsXML());
|
||||||
|
buf.append("</").append(getElementName()).append(">");
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.packet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines all the valid namespaces that are used with the {@link PubSub} packet
|
||||||
|
* as defined by the specification.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public enum PubSubNamespace
|
||||||
|
{
|
||||||
|
BASIC(null),
|
||||||
|
ERROR("errors"),
|
||||||
|
EVENT("event"),
|
||||||
|
OWNER("owner");
|
||||||
|
|
||||||
|
private String fragment;
|
||||||
|
|
||||||
|
private PubSubNamespace(String fragment)
|
||||||
|
{
|
||||||
|
this.fragment = fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getXmlns()
|
||||||
|
{
|
||||||
|
String ns = "http://jabber.org/protocol/pubsub";
|
||||||
|
|
||||||
|
if (fragment != null)
|
||||||
|
ns += '#' + fragment;
|
||||||
|
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFragment()
|
||||||
|
{
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PubSubNamespace valueOfFromXmlns(String ns)
|
||||||
|
{
|
||||||
|
int index = ns.lastIndexOf('#');
|
||||||
|
|
||||||
|
if (index != -1)
|
||||||
|
{
|
||||||
|
String suffix = ns.substring(ns.lastIndexOf('#')+1);
|
||||||
|
return valueOf(suffix.toUpperCase());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return BASIC;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.packet;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.PacketCollector;
|
||||||
|
import org.jivesoftware.smack.SmackConfiguration;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.filter.PacketFilter;
|
||||||
|
import org.jivesoftware.smack.filter.PacketIDFilter;
|
||||||
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for doing synchronous calls to the server. Provides several
|
||||||
|
* methods for sending a packet to the server and waiting for the reply.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
final public class SyncPacketSend
|
||||||
|
{
|
||||||
|
private SyncPacketSend()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
static public Packet getReply(XMPPConnection connection, Packet packet, long timeout)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
PacketFilter responseFilter = new PacketIDFilter(packet.getPacketID());
|
||||||
|
PacketCollector response = connection.createPacketCollector(responseFilter);
|
||||||
|
|
||||||
|
connection.sendPacket(packet);
|
||||||
|
|
||||||
|
// Wait up to a certain number of seconds for a reply.
|
||||||
|
Packet result = response.nextResult(timeout);
|
||||||
|
|
||||||
|
// Stop queuing results
|
||||||
|
response.cancel();
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
throw new XMPPException("No response from server.");
|
||||||
|
}
|
||||||
|
else if (result.getError() != null) {
|
||||||
|
throw new XMPPException(result.getError());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Packet getReply(XMPPConnection connection, Packet packet)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
return getReply(connection, packet, SmackConfiguration.getPacketReplyTimeout());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.provider.EmbeddedExtensionProvider;
|
||||||
|
import org.jivesoftware.smackx.pubsub.Affiliation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the affiliation element out of the reply stanza from the server
|
||||||
|
* as specified in the <a href="http://xmpp.org/extensions/xep-0060.html#schemas-pubsub">affiliation schema</a>.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class AffiliationProvider extends EmbeddedExtensionProvider
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends PacketExtension> content)
|
||||||
|
{
|
||||||
|
return new Affiliation(attributeMap.get("node"), Affiliation.Type.valueOf(attributeMap.get("affiliation")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.provider.EmbeddedExtensionProvider;
|
||||||
|
import org.jivesoftware.smackx.pubsub.Affiliation;
|
||||||
|
import org.jivesoftware.smackx.pubsub.AffiliationsExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the affiliations element out of the reply stanza from the server
|
||||||
|
* as specified in the <a href="http://xmpp.org/extensions/xep-0060.html#schemas-pubsub">affiliation schema</a>.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/public class AffiliationsProvider extends EmbeddedExtensionProvider
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends PacketExtension> content)
|
||||||
|
{
|
||||||
|
return new AffiliationsExtension((List<Affiliation>)content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.packet.DataForm;
|
||||||
|
import org.jivesoftware.smackx.provider.EmbeddedExtensionProvider;
|
||||||
|
import org.jivesoftware.smackx.pubsub.ConfigurationEvent;
|
||||||
|
import org.jivesoftware.smackx.pubsub.ConfigureForm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the node configuration element out of the message event stanza from
|
||||||
|
* the server as specified in the <a href="http://xmpp.org/extensions/xep-0060.html#schemas-event">configuration schema</a>.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class ConfigEventProvider extends EmbeddedExtensionProvider
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attMap, List<? extends PacketExtension> content)
|
||||||
|
{
|
||||||
|
if (content.size() == 0)
|
||||||
|
return new ConfigurationEvent(attMap.get("node"));
|
||||||
|
else
|
||||||
|
return new ConfigurationEvent(attMap.get("node"), new ConfigureForm((DataForm)content.iterator().next()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.provider.EmbeddedExtensionProvider;
|
||||||
|
import org.jivesoftware.smackx.pubsub.EventElement;
|
||||||
|
import org.jivesoftware.smackx.pubsub.EventElementType;
|
||||||
|
import org.jivesoftware.smackx.pubsub.NodeExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the event element out of the message stanza from
|
||||||
|
* the server as specified in the <a href="http://xmpp.org/extensions/xep-0060.html#schemas-event">event schema</a>.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class EventProvider extends EmbeddedExtensionProvider
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attMap, List<? extends PacketExtension> content)
|
||||||
|
{
|
||||||
|
return new EventElement(EventElementType.valueOf(content.get(0).getElementName()), (NodeExtension)content.get(0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
||||||
|
import org.jivesoftware.smack.provider.ProviderManager;
|
||||||
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
import org.jivesoftware.smackx.pubsub.Item;
|
||||||
|
import org.jivesoftware.smackx.pubsub.PayloadItem;
|
||||||
|
import org.jivesoftware.smackx.pubsub.SimplePayload;
|
||||||
|
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 {@link PacketExtensionProvider} is registered in
|
||||||
|
* <b>smack.providers</b> for its element name and namespace. If no provider is registered, it will return a {@link SimplePayload}.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class ItemProvider implements PacketExtensionProvider
|
||||||
|
{
|
||||||
|
public PacketExtension parseExtension(XmlPullParser parser) throws Exception
|
||||||
|
{
|
||||||
|
String id = parser.getAttributeValue(null, "id");
|
||||||
|
String elem = parser.getName();
|
||||||
|
|
||||||
|
int tag = parser.next();
|
||||||
|
|
||||||
|
if (tag == XmlPullParser.END_TAG)
|
||||||
|
{
|
||||||
|
return new Item(id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String payloadElemName = parser.getName();
|
||||||
|
String payloadNS = parser.getNamespace();
|
||||||
|
|
||||||
|
if (ProviderManager.getInstance().getExtensionProvider(payloadElemName, payloadNS) == null)
|
||||||
|
{
|
||||||
|
boolean done = false;
|
||||||
|
String payloadText = null;
|
||||||
|
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
if (tag == XmlPullParser.END_TAG && parser.getName().equals(elem))
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
else if (!((tag == XmlPullParser.START_TAG) && parser.isEmptyElementTag()))
|
||||||
|
{
|
||||||
|
if (payloadText == null)
|
||||||
|
payloadText = parser.getText();
|
||||||
|
else
|
||||||
|
payloadText += parser.getText();
|
||||||
|
}
|
||||||
|
tag = parser.next();
|
||||||
|
}
|
||||||
|
return new PayloadItem<SimplePayload>(id, new SimplePayload(payloadElemName, payloadNS, payloadText));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new PayloadItem<PacketExtension>(id, PacketParserUtils.parsePacketExtension(payloadElemName, payloadNS, parser));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.provider.EmbeddedExtensionProvider;
|
||||||
|
import org.jivesoftware.smackx.pubsub.ItemsExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the <b>items</b> element out of the message event stanza from
|
||||||
|
* the server as specified in the <a href="http://xmpp.org/extensions/xep-0060.html#schemas-event">items schema</a>.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class ItemsProvider extends EmbeddedExtensionProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends PacketExtension> content)
|
||||||
|
{
|
||||||
|
return new ItemsExtension(ItemsExtension.ItemsElementType.items, attributeMap.get("node"), content, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smack.provider.IQProvider;
|
||||||
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSub;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the root pubsub packet extensions of the {@link IQ} packet and returns
|
||||||
|
* a {@link PubSub} instance.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class PubSubProvider implements IQProvider
|
||||||
|
{
|
||||||
|
public IQ parseIQ(XmlPullParser parser) throws Exception
|
||||||
|
{
|
||||||
|
PubSub pubsub = new PubSub();
|
||||||
|
String namespace = parser.getNamespace();
|
||||||
|
pubsub.setPubSubNamespace(PubSubNamespace.valueOfFromXmlns(namespace));
|
||||||
|
boolean done = false;
|
||||||
|
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
int eventType = parser.next();
|
||||||
|
|
||||||
|
if (eventType == XmlPullParser.START_TAG)
|
||||||
|
{
|
||||||
|
PacketExtension ext = PacketParserUtils.parsePacketExtension(parser.getName(), namespace, parser);
|
||||||
|
|
||||||
|
if (ext != null)
|
||||||
|
{
|
||||||
|
pubsub.addExtension(ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (eventType == XmlPullParser.END_TAG)
|
||||||
|
{
|
||||||
|
if (parser.getName().equals("pubsub"))
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pubsub;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.provider.EmbeddedExtensionProvider;
|
||||||
|
import org.jivesoftware.smackx.pubsub.RetractItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the <b>retract</b> element out of the message event stanza from
|
||||||
|
* the server as specified in the <a href="http://xmpp.org/extensions/xep-0060.html#schemas-event">retract schema</a>.
|
||||||
|
* This element is a child of the <b>items</b> element.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class RetractEventProvider extends EmbeddedExtensionProvider
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends PacketExtension> content)
|
||||||
|
{
|
||||||
|
return new RetractItem(attributeMap.get("id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.provider.EmbeddedExtensionProvider;
|
||||||
|
import org.jivesoftware.smackx.pubsub.NodeExtension;
|
||||||
|
import org.jivesoftware.smackx.pubsub.PubSubElementType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses simple elements that only contain a <b>node</b> attribute. This is common amongst many of the
|
||||||
|
* elements defined in the pubsub specification. For this common case a {@link NodeExtension} is returned.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class SimpleNodeProvider extends EmbeddedExtensionProvider
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends PacketExtension> content)
|
||||||
|
{
|
||||||
|
return new NodeExtension(PubSubElementType.valueOfFromElemName(currentElement, currentNamespace), attributeMap.get("node"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
||||||
|
import org.jivesoftware.smackx.pubsub.Subscription;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the <b>subscription</b> element out of the pubsub IQ message from
|
||||||
|
* the server as specified in the <a href="http://xmpp.org/extensions/xep-0060.html#schemas-pubsub">subscription schema</a>.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class SubscriptionProvider implements PacketExtensionProvider
|
||||||
|
{
|
||||||
|
public PacketExtension parseExtension(XmlPullParser parser) throws Exception
|
||||||
|
{
|
||||||
|
String jid = parser.getAttributeValue(null, "jid");
|
||||||
|
String nodeId = parser.getAttributeValue(null, "node");
|
||||||
|
String subId = parser.getAttributeValue(null, "subid");
|
||||||
|
String state = parser.getAttributeValue(null, "subscription");
|
||||||
|
boolean isRequired = false;
|
||||||
|
|
||||||
|
int tag = parser.next();
|
||||||
|
|
||||||
|
if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("subscribe-options"))
|
||||||
|
{
|
||||||
|
tag = parser.next();
|
||||||
|
|
||||||
|
if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("required"))
|
||||||
|
isRequired = true;
|
||||||
|
|
||||||
|
while (parser.next() != XmlPullParser.END_TAG && parser.getName() != "subscribe-options");
|
||||||
|
}
|
||||||
|
while (parser.getEventType() != XmlPullParser.END_TAG) parser.next();
|
||||||
|
return new Subscription(jid, nodeId, subId, (state == null ? null : Subscription.State.valueOf(state)), isRequired);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.provider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smackx.provider.EmbeddedExtensionProvider;
|
||||||
|
import org.jivesoftware.smackx.pubsub.Subscription;
|
||||||
|
import org.jivesoftware.smackx.pubsub.SubscriptionsExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the <b>subscriptions</b> element out of the pubsub IQ message from
|
||||||
|
* the server as specified in the <a href="http://xmpp.org/extensions/xep-0060.html#schemas-pubsub">subscriptions schema</a>.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class SubscriptionsProvider extends EmbeddedExtensionProvider
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends PacketExtension> content)
|
||||||
|
{
|
||||||
|
return new SubscriptionsExtension(attributeMap.get("node"), (List<Subscription>)content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
43
source/org/jivesoftware/smackx/pubsub/util/NodeUtils.java
Normal file
43
source/org/jivesoftware/smackx/pubsub/util/NodeUtils.java
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.util;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
|
import org.jivesoftware.smackx.Form;
|
||||||
|
import org.jivesoftware.smackx.pubsub.ConfigureForm;
|
||||||
|
import org.jivesoftware.smackx.pubsub.FormNode;
|
||||||
|
import org.jivesoftware.smackx.pubsub.PubSubElementType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility for extracting information from packets.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class NodeUtils
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get a {@link ConfigureForm} from a packet.
|
||||||
|
*
|
||||||
|
* @param packet
|
||||||
|
* @param elem
|
||||||
|
* @return The configuration form
|
||||||
|
*/
|
||||||
|
public static ConfigureForm getFormFromPacket(Packet packet, PubSubElementType elem)
|
||||||
|
{
|
||||||
|
FormNode config = (FormNode)packet.getExtension(elem.getElementName(), elem.getNamespace().getXmlns());
|
||||||
|
Form formReply = config.getForm();
|
||||||
|
return new ConfigureForm(formReply);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
67
source/org/jivesoftware/smackx/pubsub/util/XmlUtils.java
Normal file
67
source/org/jivesoftware/smackx/pubsub/util/XmlUtils.java
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/**
|
||||||
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.util;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import javax.xml.transform.OutputKeys;
|
||||||
|
import javax.xml.transform.Transformer;
|
||||||
|
import javax.xml.transform.TransformerFactory;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple utility for pretty printing xml.
|
||||||
|
*
|
||||||
|
* @author Robin Collier
|
||||||
|
*/
|
||||||
|
public class XmlUtils
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param header Just a title for the stanza for readability. Single word no spaces since
|
||||||
|
* it is inserted as the root element in the output.
|
||||||
|
* @param xml The string to pretty print
|
||||||
|
*/
|
||||||
|
static public void prettyPrint(String header, String xml)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||||
|
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||||
|
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");
|
||||||
|
|
||||||
|
if (header != null)
|
||||||
|
{
|
||||||
|
xml = "\n<" + header + ">" + xml + "</" + header + '>';
|
||||||
|
}
|
||||||
|
transformer.transform(new StreamSource(new StringReader(xml)), new StreamResult(System.out));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
System.out.println("Something wrong with xml in \n---------------\n" + xml + "\n---------------");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void appendAttribute(StringBuilder builder, String att, String value)
|
||||||
|
{
|
||||||
|
builder.append(" ");
|
||||||
|
builder.append(att);
|
||||||
|
builder.append("='");
|
||||||
|
builder.append(value);
|
||||||
|
builder.append("'");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
45
test/org/jivesoftware/smackx/pubsub/CarExtension.java
Normal file
45
test/org/jivesoftware/smackx/pubsub/CarExtension.java
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-05-05
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
|
||||||
|
class CarExtension implements PacketExtension
|
||||||
|
{
|
||||||
|
private String color;
|
||||||
|
private int numTires;
|
||||||
|
|
||||||
|
public CarExtension(String col, int num)
|
||||||
|
{
|
||||||
|
color = col;
|
||||||
|
numTires = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColor()
|
||||||
|
{
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumTires()
|
||||||
|
{
|
||||||
|
return numTires;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElementName()
|
||||||
|
{
|
||||||
|
return "car";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespace()
|
||||||
|
{
|
||||||
|
return "pubsub:test:vehicle";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXML()
|
||||||
|
{
|
||||||
|
return "<" + getElementName() + " xmlns='" + getNamespace() + "'><paint color='" +
|
||||||
|
getColor() + "'/><tires num='" + getNumTires() + "'/></" + getElementName() + ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-05-05
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
public class CarExtensionProvider implements PacketExtensionProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
public PacketExtension parseExtension(XmlPullParser parser) throws Exception
|
||||||
|
{
|
||||||
|
String color = null;
|
||||||
|
int numTires = 0;
|
||||||
|
|
||||||
|
for (int i=0; i<2; i++)
|
||||||
|
{
|
||||||
|
while (parser.next() != XmlPullParser.START_TAG);
|
||||||
|
|
||||||
|
if (parser.getName().equals("paint"))
|
||||||
|
{
|
||||||
|
color = parser.getAttributeValue(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numTires = Integer.parseInt(parser.getAttributeValue(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (parser.next() != XmlPullParser.END_TAG);
|
||||||
|
return new CarExtension(color, numTires);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
72
test/org/jivesoftware/smackx/pubsub/EntityUseCases.java
Normal file
72
test/org/jivesoftware/smackx/pubsub/EntityUseCases.java
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-04-09
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.packet.DiscoverInfo;
|
||||||
|
import org.jivesoftware.smackx.packet.DiscoverItems;
|
||||||
|
import org.jivesoftware.smackx.packet.DiscoverInfo.Identity;
|
||||||
|
import org.jivesoftware.smackx.pubsub.test.SingleUserTestCase;
|
||||||
|
import org.jivesoftware.smackx.pubsub.util.XmlUtils;
|
||||||
|
|
||||||
|
public class EntityUseCases extends SingleUserTestCase
|
||||||
|
{
|
||||||
|
public void testDiscoverPubsubInfo() throws Exception
|
||||||
|
{
|
||||||
|
DiscoverInfo supportedFeatures = getManager().getSupportedFeatures();
|
||||||
|
assertNotNull(supportedFeatures);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDiscoverNodeInfo() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode myNode = getManager().createNode("DiscoNode" + System.currentTimeMillis());
|
||||||
|
DiscoverInfo info = myNode.discoverInfo();
|
||||||
|
assertTrue(info.getIdentities().hasNext());
|
||||||
|
Identity ident = info.getIdentities().next();
|
||||||
|
|
||||||
|
assertEquals("leaf", ident.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDiscoverNodeItems() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode myNode = getRandomPubnode(getManager(), true, false);
|
||||||
|
myNode.send(new Item());
|
||||||
|
myNode.send(new Item());
|
||||||
|
myNode.send(new Item());
|
||||||
|
myNode.send(new Item());
|
||||||
|
DiscoverItems items = myNode.discoverItems();
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for(Iterator it = items.getItems(); it.hasNext(); it.next(),count++);
|
||||||
|
|
||||||
|
assertEquals(4, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDiscoverSubscriptions() throws Exception
|
||||||
|
{
|
||||||
|
getManager().getSubscriptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDiscoverNodeSubscriptions() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode myNode = getRandomPubnode(getManager(), true, true);
|
||||||
|
myNode.subscribe(getConnection(0).getUser());
|
||||||
|
List<Subscription> subscriptions = myNode.getSubscriptions();
|
||||||
|
|
||||||
|
assertTrue(subscriptions.size() < 3);
|
||||||
|
|
||||||
|
for (Subscription subscription : subscriptions)
|
||||||
|
{
|
||||||
|
assertNull(subscription.getNode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRetrieveAffiliation() throws Exception
|
||||||
|
{
|
||||||
|
getManager().getAffiliations();
|
||||||
|
}
|
||||||
|
}
|
130
test/org/jivesoftware/smackx/pubsub/OwnerUseCases.java
Normal file
130
test/org/jivesoftware/smackx/pubsub/OwnerUseCases.java
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-04-09
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smackx.pubsub.test.SingleUserTestCase;
|
||||||
|
|
||||||
|
public class OwnerUseCases extends SingleUserTestCase
|
||||||
|
{
|
||||||
|
public void testCreateInstantNode() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode node = getManager().createNode();
|
||||||
|
assertNotNull(node);
|
||||||
|
assertNotNull(node.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateNamedNode() throws Exception
|
||||||
|
{
|
||||||
|
String id = "TestNamedNode" + System.currentTimeMillis();
|
||||||
|
LeafNode node = getManager().createNode(id);
|
||||||
|
assertEquals(id, node.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateConfiguredNode() throws Exception
|
||||||
|
{
|
||||||
|
// Generate reasonably unique for multiple tests
|
||||||
|
String id = "TestConfigNode" + System.currentTimeMillis();
|
||||||
|
|
||||||
|
// Create and configure a node
|
||||||
|
ConfigureForm form = new ConfigureForm(FormType.submit);
|
||||||
|
form.setAccessModel(AccessModel.open);
|
||||||
|
form.setDeliverPayloads(false);
|
||||||
|
form.setNotifyRetract(true);
|
||||||
|
form.setPersistentItems(true);
|
||||||
|
form.setPublishModel(PublishModel.open);
|
||||||
|
|
||||||
|
LeafNode node = (LeafNode)getManager().createNode(id, form);
|
||||||
|
|
||||||
|
ConfigureForm currentForm = node.getNodeConfiguration();
|
||||||
|
assertEquals(AccessModel.open, currentForm.getAccessModel());
|
||||||
|
assertFalse(currentForm.isDeliverPayloads());
|
||||||
|
assertTrue(currentForm.isNotifyRetract());
|
||||||
|
assertTrue(currentForm.isPersistItems());
|
||||||
|
assertEquals(PublishModel.open, currentForm.getPublishModel());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateAndUpdateConfiguredNode() throws Exception
|
||||||
|
{
|
||||||
|
// Generate reasonably unique for multiple tests
|
||||||
|
String id = "TestConfigNode2" + System.currentTimeMillis();
|
||||||
|
|
||||||
|
// Create and configure a node
|
||||||
|
ConfigureForm form = new ConfigureForm(FormType.submit);
|
||||||
|
form.setAccessModel(AccessModel.open);
|
||||||
|
form.setDeliverPayloads(false);
|
||||||
|
form.setNotifyRetract(true);
|
||||||
|
form.setPersistentItems(true);
|
||||||
|
form.setPublishModel(PublishModel.open);
|
||||||
|
|
||||||
|
LeafNode myNode = (LeafNode)getManager().createNode(id, form);
|
||||||
|
ConfigureForm config = myNode.getNodeConfiguration();
|
||||||
|
|
||||||
|
assertEquals(AccessModel.open, config.getAccessModel());
|
||||||
|
assertFalse(config.isDeliverPayloads());
|
||||||
|
assertTrue(config.isNotifyRetract());
|
||||||
|
assertTrue(config.isPersistItems());
|
||||||
|
assertEquals(PublishModel.open, config.getPublishModel());
|
||||||
|
|
||||||
|
ConfigureForm submitForm = new ConfigureForm(config.createAnswerForm());
|
||||||
|
submitForm.setAccessModel(AccessModel.whitelist);
|
||||||
|
submitForm.setDeliverPayloads(true);
|
||||||
|
submitForm.setNotifyRetract(false);
|
||||||
|
submitForm.setPersistentItems(false);
|
||||||
|
submitForm.setPublishModel(PublishModel.publishers);
|
||||||
|
myNode.sendConfigurationForm(submitForm);
|
||||||
|
|
||||||
|
ConfigureForm newConfig = myNode.getNodeConfiguration();
|
||||||
|
assertEquals(AccessModel.whitelist, newConfig.getAccessModel());
|
||||||
|
assertTrue(newConfig.isDeliverPayloads());
|
||||||
|
assertFalse(newConfig.isNotifyRetract());
|
||||||
|
assertFalse(newConfig.isPersistItems());
|
||||||
|
assertEquals(PublishModel.publishers, newConfig.getPublishModel());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetDefaultConfig() throws Exception
|
||||||
|
{
|
||||||
|
ConfigureForm form = getManager().getDefaultConfiguration();
|
||||||
|
assertNotNull(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteNode() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode myNode = getManager().createNode();
|
||||||
|
assertNotNull(getManager().getNode(myNode.getId()));
|
||||||
|
|
||||||
|
getManager(0).deleteNode(myNode.getId());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
assertNull(getManager().getNode(myNode.getId()));
|
||||||
|
fail("Node should not exist");
|
||||||
|
}
|
||||||
|
catch (XMPPException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPurgeItems() throws XMPPException
|
||||||
|
{
|
||||||
|
LeafNode node = getRandomPubnode(getManager(), true, false);
|
||||||
|
|
||||||
|
node.send(new Item());
|
||||||
|
node.send(new Item());
|
||||||
|
node.send(new Item());
|
||||||
|
node.send(new Item());
|
||||||
|
node.send(new Item());
|
||||||
|
|
||||||
|
Collection<? extends Item> items = node.getItems();
|
||||||
|
assertTrue(items.size() == 5);
|
||||||
|
|
||||||
|
node.deleteAllItems();
|
||||||
|
items = node.getItems();
|
||||||
|
|
||||||
|
// Pubsub service may keep the last notification (in spec), so 0 or 1 may be returned on get items.
|
||||||
|
assertTrue(items.size() < 2);
|
||||||
|
}
|
||||||
|
}
|
150
test/org/jivesoftware/smackx/pubsub/PublisherUseCases.java
Normal file
150
test/org/jivesoftware/smackx/pubsub/PublisherUseCases.java
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-04-09
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.packet.XMPPError;
|
||||||
|
import org.jivesoftware.smack.packet.XMPPError.Condition;
|
||||||
|
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||||
|
import org.jivesoftware.smackx.pubsub.test.SingleUserTestCase;
|
||||||
|
|
||||||
|
public class PublisherUseCases extends SingleUserTestCase
|
||||||
|
{
|
||||||
|
public void testSendNodeTrNot() throws Exception
|
||||||
|
{
|
||||||
|
getPubnode(false, false).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSendNodeTrPay_WithOutPayload() throws XMPPException
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(false, true);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
node.send(new Item());
|
||||||
|
fail("Exception should be thrown when there is no payload");
|
||||||
|
}
|
||||||
|
catch (XMPPException e) {
|
||||||
|
XMPPError err = e.getXMPPError();
|
||||||
|
assertTrue(err.getType().equals(XMPPError.Type.MODIFY));
|
||||||
|
assertTrue(err.getCondition().equals(Condition.bad_request.toString()));
|
||||||
|
assertNotNull(err.getExtension("payload-required", PubSubNamespace.ERROR.getXmlns()));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
node.send(new Item("test" + System.currentTimeMillis()));
|
||||||
|
fail("Exception should be thrown when there is no payload");
|
||||||
|
}
|
||||||
|
catch (XMPPException e) {
|
||||||
|
XMPPError err = e.getXMPPError();
|
||||||
|
assertTrue(err.getType().equals(XMPPError.Type.MODIFY));
|
||||||
|
assertTrue(err.getCondition().equals(Condition.bad_request.toString()));
|
||||||
|
assertNotNull(err.getExtension("payload-required", PubSubNamespace.ERROR.getXmlns()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSendNodeTrPay_WithPayload() throws XMPPException
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(false, true);
|
||||||
|
node.send(new PayloadItem<SimplePayload>(null,
|
||||||
|
new SimplePayload("book", "pubsub:test:book", "<book xmlns='pubsub:test:book'><title>Lord of the Rings</title></book>")));
|
||||||
|
node.send(new PayloadItem<SimplePayload>("test" + System.currentTimeMillis(),
|
||||||
|
new SimplePayload("book", "pubsub:test:book", "<book xmlns='pubsub:test:book'><title>Two Towers</title></book>")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSendNodePerNot() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(true, false);
|
||||||
|
node.send(new Item());
|
||||||
|
node.send(new Item("test" + System.currentTimeMillis()));
|
||||||
|
node.send(new PayloadItem<SimplePayload>(null,
|
||||||
|
new SimplePayload("book", "pubsub:test:book", "<book xmlns='pubsub:test:book'><title>Lord of the Rings</title></book>")));
|
||||||
|
node.send(new PayloadItem<SimplePayload>("test" + System.currentTimeMillis(),
|
||||||
|
new SimplePayload("book", "pubsub:test:book", "<book xmlns='pubsub:test:book'><title>Two Towers</title></book>")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSendPerPay_WithPayload() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(true, true);
|
||||||
|
node.send(new PayloadItem<SimplePayload>(null,
|
||||||
|
new SimplePayload("book", "pubsub:test:book", "<book xmlns='pubsub:test:book'><title>Lord of the Rings</title></book>")));
|
||||||
|
node.send(new PayloadItem<SimplePayload>("test" + System.currentTimeMillis(),
|
||||||
|
new SimplePayload("book", "pubsub:test:book", "<book xmlns='pubsub:test:book'><title>Two Towers</title></book>")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSendPerPay_NoPayload() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(true, true);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
node.send(new Item());
|
||||||
|
fail("Exception should be thrown when there is no payload");
|
||||||
|
}
|
||||||
|
catch (XMPPException e) {
|
||||||
|
XMPPError err = e.getXMPPError();
|
||||||
|
assertTrue(err.getType().equals(XMPPError.Type.MODIFY));
|
||||||
|
assertTrue(err.getCondition().equals(Condition.bad_request.toString()));
|
||||||
|
assertNotNull(err.getExtension("payload-required", PubSubNamespace.ERROR.getXmlns()));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
node.send(new Item("test" + System.currentTimeMillis()));
|
||||||
|
fail("Exception should be thrown when there is no payload");
|
||||||
|
}
|
||||||
|
catch (XMPPException e) {
|
||||||
|
XMPPError err = e.getXMPPError();
|
||||||
|
assertTrue(err.getType().equals(XMPPError.Type.MODIFY));
|
||||||
|
assertTrue(err.getCondition().equals(Condition.bad_request.toString()));
|
||||||
|
assertNotNull(err.getExtension("payload-required", PubSubNamespace.ERROR.getXmlns()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteItems() throws XMPPException
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(true, false);
|
||||||
|
|
||||||
|
node.send(new Item("1"));
|
||||||
|
node.send(new Item("2"));
|
||||||
|
node.send(new Item("3"));
|
||||||
|
node.send(new Item("4"));
|
||||||
|
|
||||||
|
node.deleteItem("1");
|
||||||
|
Collection<? extends Item> items = node.getItems();
|
||||||
|
|
||||||
|
assertTrue(items.size() == 3);
|
||||||
|
assertEquals(items.iterator().next().getId(), "2");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPersistItems() throws XMPPException
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(true, false);
|
||||||
|
|
||||||
|
node.send(new Item("1"));
|
||||||
|
node.send(new Item("2"));
|
||||||
|
node.send(new Item("3"));
|
||||||
|
node.send(new Item("4"));
|
||||||
|
|
||||||
|
Collection<? extends Item> items = node.getItems();
|
||||||
|
|
||||||
|
assertTrue(items.size() == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testItemOverwritten() throws XMPPException
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(true, false);
|
||||||
|
|
||||||
|
node.send(new PayloadItem<SimplePayload>("1", new SimplePayload("test", null, "<test/>")));
|
||||||
|
node.send(new PayloadItem<SimplePayload>("1", new SimplePayload("test2", null, "<test2/>")));
|
||||||
|
|
||||||
|
List<? extends Item> items = node.getItems();
|
||||||
|
assertEquals(1, items.size());
|
||||||
|
assertEquals("1", items.get(0).getId());
|
||||||
|
}
|
||||||
|
}
|
224
test/org/jivesoftware/smackx/pubsub/SubscriberUseCases.java
Normal file
224
test/org/jivesoftware/smackx/pubsub/SubscriberUseCases.java
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-04-09
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smackx.FormField;
|
||||||
|
import org.jivesoftware.smackx.pubsub.test.SingleUserTestCase;
|
||||||
|
|
||||||
|
public class SubscriberUseCases extends SingleUserTestCase
|
||||||
|
{
|
||||||
|
public void testSubscribe() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(false, false);
|
||||||
|
Subscription sub = node.subscribe(getJid());
|
||||||
|
|
||||||
|
assertEquals(getJid(), sub.getJid());
|
||||||
|
assertNotNull(sub.getId());
|
||||||
|
assertEquals(node.getId(), sub.getNode());
|
||||||
|
assertEquals(Subscription.State.subscribed, sub.getState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSubscribeBadJid() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(false, false);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
node.subscribe("this@over.here");
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch (XMPPException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSubscribeWithOptions() throws Exception
|
||||||
|
{
|
||||||
|
SubscribeForm form = new SubscribeForm(FormType.submit);
|
||||||
|
form.setDeliverOn(true);
|
||||||
|
Calendar expire = Calendar.getInstance();
|
||||||
|
expire.set(2020, 1, 1);
|
||||||
|
form.setExpiry(expire.getTime());
|
||||||
|
LeafNode node = getPubnode(false, false);
|
||||||
|
node.subscribe(getJid(), form);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSubscribeConfigRequired() throws Exception
|
||||||
|
{
|
||||||
|
ConfigureForm form = new ConfigureForm(FormType.submit);
|
||||||
|
form.setAccessModel(AccessModel.open);
|
||||||
|
|
||||||
|
// Openfire specific field - nothing in the spec yet
|
||||||
|
FormField required = new FormField("pubsub#subscription_required");
|
||||||
|
required.setType(FormField.TYPE_BOOLEAN);
|
||||||
|
form.addField(required);
|
||||||
|
form.setAnswer("pubsub#subscription_required", true);
|
||||||
|
LeafNode node = (LeafNode)getManager().createNode("Pubnode" + System.currentTimeMillis(), form);
|
||||||
|
|
||||||
|
Subscription sub = node.subscribe(getJid());
|
||||||
|
|
||||||
|
assertEquals(getJid(), sub.getJid());
|
||||||
|
assertNotNull(sub.getId());
|
||||||
|
assertEquals(node.getId(), sub.getNode());
|
||||||
|
assertEquals(true, sub.isConfigRequired());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnsubscribe() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(false, false);
|
||||||
|
node.subscribe(getJid());
|
||||||
|
Collection<Subscription> subs = node.getSubscriptions();
|
||||||
|
|
||||||
|
node.unsubscribe(getJid());
|
||||||
|
Collection<Subscription> afterSubs = node.getSubscriptions();
|
||||||
|
assertEquals(subs.size()-1, afterSubs.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnsubscribeWithMultipleNoSubId() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(false, false);
|
||||||
|
node.subscribe(getBareJID(0));
|
||||||
|
node.subscribe(getBareJID(0));
|
||||||
|
node.subscribe(getBareJID(0));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
node.unsubscribe(getBareJID(0));
|
||||||
|
fail("Unsubscribe with no subid should fail");
|
||||||
|
}
|
||||||
|
catch (XMPPException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnsubscribeWithMultipleWithSubId() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(false, false);
|
||||||
|
node.subscribe(getJid());
|
||||||
|
Subscription sub = node.subscribe(getJid());
|
||||||
|
node.subscribe(getJid());
|
||||||
|
node.unsubscribe(getJid(), sub.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetOptions() throws Exception
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(false, false);
|
||||||
|
Subscription sub = node.subscribe(getJid());
|
||||||
|
SubscribeForm form = node.getSubscriptionOptions(getJid(), sub.getId());
|
||||||
|
assertNotNull(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void testSubscribeWithConfig() throws Exception
|
||||||
|
// {
|
||||||
|
// LeafNode node = getPubnode(false, false);
|
||||||
|
//
|
||||||
|
// Subscription sub = node.subscribe(getBareJID(0));
|
||||||
|
//
|
||||||
|
// assertEquals(getBareJID(0), sub.getJid());
|
||||||
|
// assertNotNull(sub.getId());
|
||||||
|
// assertEquals(node.getId(), sub.getNode());
|
||||||
|
// assertEquals(true, sub.isConfigRequired());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
public void testGetItems() throws XMPPException
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(true, false);
|
||||||
|
|
||||||
|
node.send((Item)null);
|
||||||
|
node.send((Item)null);
|
||||||
|
node.send((Item)null);
|
||||||
|
node.send((Item)null);
|
||||||
|
node.send((Item)null);
|
||||||
|
|
||||||
|
Collection<? extends Item> items = node.getItems();
|
||||||
|
assertTrue(items.size() == 5);
|
||||||
|
|
||||||
|
long curTime = System.currentTimeMillis();
|
||||||
|
node.send(new Item("1-" + curTime));
|
||||||
|
node.send(new Item("2-" + curTime));
|
||||||
|
node.send(new Item("3-" + curTime));
|
||||||
|
node.send(new Item("4-" + curTime));
|
||||||
|
node.send(new Item("5-" + curTime));
|
||||||
|
|
||||||
|
items = node.getItems();
|
||||||
|
assertTrue(items.size() == 10);
|
||||||
|
|
||||||
|
LeafNode payloadNode = getPubnode(true, true);
|
||||||
|
|
||||||
|
Map<String , String> idPayload = new HashMap<String, String>();
|
||||||
|
idPayload.put("6-" + curTime, "<a/>");
|
||||||
|
idPayload.put("7-" + curTime, "<a href=\"/up/here\"/>");
|
||||||
|
idPayload.put("8-" + curTime, "<entity>text<inner></inner></entity>");
|
||||||
|
idPayload.put("9-" + curTime, "<entity><inner><text></text></inner></entity>");
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> payload : idPayload.entrySet())
|
||||||
|
{
|
||||||
|
payloadNode.send(new PayloadItem<SimplePayload>(payload.getKey(), new SimplePayload("a", "pubsub:test", payload.getValue())));
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadNode.send(new PayloadItem<SimplePayload>("6-" + curTime, new SimplePayload("a", "pubsub:test", "<a xmlns='pubsub:test'/>")));
|
||||||
|
payloadNode.send(new PayloadItem<SimplePayload>("7-" + curTime, new SimplePayload("a", "pubsub:test", "<a xmlns='pubsub:test' href=\"/up/here\"/>")));
|
||||||
|
payloadNode.send(new PayloadItem<SimplePayload>("8-" + curTime, new SimplePayload("entity", "pubsub:test", "<entity xmlns='pubsub:test'>text<inner></inner></entity>")));
|
||||||
|
payloadNode.send(new PayloadItem<SimplePayload>("9-" + curTime, new SimplePayload("entity", "pubsub:test", "<entity xmlns='pubsub:test'><inner><text></text></inner></entity>")));
|
||||||
|
|
||||||
|
Collection<PayloadItem<SimplePayload>> payloadItems = payloadNode.getItems();
|
||||||
|
assertTrue(payloadItems.size() == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getSpecifiedItems() throws XMPPException
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(true, true);
|
||||||
|
|
||||||
|
node.send(new PayloadItem<SimplePayload>("1", new SimplePayload("a", "pubsub:test", "<a xmlns='pubsub:test' href='/1'/>")));
|
||||||
|
node.send(new PayloadItem<SimplePayload>("2", new SimplePayload("a", "pubsub:test", "<a xmlns='pubsub:test' href='/2'/>")));
|
||||||
|
node.send(new PayloadItem<SimplePayload>("3", new SimplePayload("a", "pubsub:test", "<a xmlns='pubsub:test' href='/3'/>")));
|
||||||
|
node.send(new PayloadItem<SimplePayload>("4", new SimplePayload("a", "pubsub:test", "<a xmlns='pubsub:test' href='/4'/>")));
|
||||||
|
node.send(new PayloadItem<SimplePayload>("5", new SimplePayload("a", "pubsub:test", "<a xmlns='pubsub:test' href='/5'/>")));
|
||||||
|
|
||||||
|
Collection<String> ids = new ArrayList<String>(3);
|
||||||
|
ids.add("1");
|
||||||
|
ids.add("3");
|
||||||
|
ids.add("4");
|
||||||
|
|
||||||
|
List<PayloadItem<SimplePayload>> items = node.getItems(ids);
|
||||||
|
assertEquals(3, items.size());
|
||||||
|
assertEquals(items.get(0).getId(), "1");
|
||||||
|
assertEquals(items.get(0).getPayload().toXML(), "<a xmlns='pubsub:test' href='/1'/>");
|
||||||
|
assertEquals(items.get(1).getId(), "3");
|
||||||
|
assertEquals(items.get(1).getPayload().toXML(), "<a xmlns='pubsub:test' href='/3'/>");
|
||||||
|
assertEquals(items.get(2).getId(), "5");
|
||||||
|
assertEquals(items.get(2).getPayload().toXML(), "<a xmlns='pubsub:test' href='/5'/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetLastNItems() throws XMPPException
|
||||||
|
{
|
||||||
|
LeafNode node = getPubnode(true, false);
|
||||||
|
|
||||||
|
node.send(new Item("1"));
|
||||||
|
node.send(new Item("2"));
|
||||||
|
node.send(new Item("3"));
|
||||||
|
node.send(new Item("4"));
|
||||||
|
node.send(new Item("5"));
|
||||||
|
|
||||||
|
List<Item> items = node.getItems(2);
|
||||||
|
assertEquals(2, items.size());
|
||||||
|
assertEquals(items.get(0).getId(), "4");
|
||||||
|
assertEquals(items.get(1).getId(), "5");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getJid()
|
||||||
|
{
|
||||||
|
return getConnection(0).getUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
test/org/jivesoftware/smackx/pubsub/TestAPI.java
Normal file
22
test/org/jivesoftware/smackx/pubsub/TestAPI.java
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-04-09
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smackx.pubsub.test.SingleUserTestCase;
|
||||||
|
|
||||||
|
public class TestAPI extends SingleUserTestCase
|
||||||
|
{
|
||||||
|
public void testGetNonexistentNode()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
getManager().getNode("" + System.currentTimeMillis());
|
||||||
|
assertTrue(false);
|
||||||
|
}
|
||||||
|
catch (XMPPException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
575
test/org/jivesoftware/smackx/pubsub/TestEvents.java
Normal file
575
test/org/jivesoftware/smackx/pubsub/TestEvents.java
Normal file
|
@ -0,0 +1,575 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-04-22
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.packet.XMPPError.Type;
|
||||||
|
import org.jivesoftware.smack.test.SmackTestCase;
|
||||||
|
import org.jivesoftware.smackx.pubsub.listener.ItemDeleteListener;
|
||||||
|
import org.jivesoftware.smackx.pubsub.listener.ItemEventListener;
|
||||||
|
import org.jivesoftware.smackx.pubsub.listener.NodeConfigListener;
|
||||||
|
|
||||||
|
public class TestEvents extends SmackTestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public TestEvents(String str)
|
||||||
|
{
|
||||||
|
super(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxConnections()
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getService()
|
||||||
|
{
|
||||||
|
return "pubsub." + getServiceName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateAndGetNode() throws Exception
|
||||||
|
{
|
||||||
|
String nodeId = "MyTestNode";
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
|
||||||
|
LeafNode creatorNode = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
creatorNode = (LeafNode)creatorMgr.getNode(nodeId);
|
||||||
|
}
|
||||||
|
catch (XMPPException e)
|
||||||
|
{
|
||||||
|
if (e.getXMPPError().getType() == Type.CANCEL && e.getXMPPError().getCondition().equals("item-not-found"))
|
||||||
|
creatorNode = creatorMgr.createNode(nodeId);
|
||||||
|
else
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode = (LeafNode)subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
assertNotNull(subNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConfigureAndNotify() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId = "TestNode" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
|
||||||
|
LeafNode creatorNode = getPubnode(creatorMgr, nodeId, false, true);
|
||||||
|
|
||||||
|
BlockingQueue<NodeConfigCoordinator> queue = new ArrayBlockingQueue<NodeConfigCoordinator>(3);
|
||||||
|
|
||||||
|
// Setup event receiver
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode = (LeafNode)subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
NodeConfigListener sub1Handler = new NodeConfigCoordinator(queue, "sub1");
|
||||||
|
subNode.subscribe(getConnection(1).getUser());
|
||||||
|
subNode.addConfigurationListener(sub1Handler);
|
||||||
|
|
||||||
|
ConfigureForm currentConfig = creatorNode.getNodeConfiguration();
|
||||||
|
ConfigureForm form = new ConfigureForm(currentConfig.createAnswerForm());
|
||||||
|
form.setPersistentItems(true);
|
||||||
|
form.setDeliverPayloads(false);
|
||||||
|
form.setNotifyConfig(true);
|
||||||
|
creatorNode.sendConfigurationForm(form);
|
||||||
|
|
||||||
|
ConfigurationEvent event = queue.poll(5, TimeUnit.SECONDS).event;
|
||||||
|
assertEquals(nodeId, event.getNode());
|
||||||
|
assertNull(event.getConfiguration());
|
||||||
|
|
||||||
|
currentConfig = creatorNode.getNodeConfiguration();
|
||||||
|
form = new ConfigureForm(currentConfig.createAnswerForm());
|
||||||
|
form.setDeliverPayloads(true);
|
||||||
|
creatorNode.sendConfigurationForm(form);
|
||||||
|
|
||||||
|
event = queue.poll(5, TimeUnit.SECONDS).event;
|
||||||
|
assertEquals(nodeId, event.getNode());
|
||||||
|
assertNotNull(event.getConfiguration());
|
||||||
|
assertTrue(event.getConfiguration().isPersistItems());
|
||||||
|
assertTrue(event.getConfiguration().isDeliverPayloads());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSendAndReceiveNoPayload() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId = "TestNode" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
LeafNode creatorNode = getPubnode(creatorMgr, nodeId, true, false);
|
||||||
|
|
||||||
|
BlockingQueue<ItemEventCoordinator<Item>> queue = new ArrayBlockingQueue<ItemEventCoordinator<Item>>(3);
|
||||||
|
ItemEventCoordinator<Item> creatorHandler = new ItemEventCoordinator<Item>(queue, "creator");
|
||||||
|
creatorNode.addItemEventListener(creatorHandler);
|
||||||
|
|
||||||
|
// Setup event receiver
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode = (LeafNode)subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
ItemEventCoordinator<Item> sub1Handler = new ItemEventCoordinator<Item>(queue, "sub1");
|
||||||
|
subNode.addItemEventListener(sub1Handler);
|
||||||
|
Subscription sub1 = subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
// Send event
|
||||||
|
String itemId = String.valueOf(System.currentTimeMillis());
|
||||||
|
creatorNode.send(new Item(itemId));
|
||||||
|
|
||||||
|
for(int i=0; i<2; i++)
|
||||||
|
{
|
||||||
|
ItemEventCoordinator<Item> coord = queue.take();
|
||||||
|
assertEquals(1, coord.events.getItems().size());
|
||||||
|
assertEquals(itemId, coord.events.getItems().iterator().next().getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPublishAndReceiveNoPayload() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId = "TestNode" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
LeafNode creatorNode = getPubnode(creatorMgr, nodeId, true, false);
|
||||||
|
|
||||||
|
BlockingQueue<ItemEventCoordinator<Item>> queue = new ArrayBlockingQueue<ItemEventCoordinator<Item>>(3);
|
||||||
|
|
||||||
|
// Setup event receiver
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode = (LeafNode)subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
ItemEventCoordinator<Item> sub1Handler = new ItemEventCoordinator<Item>(queue, "sub1");
|
||||||
|
subNode.addItemEventListener(sub1Handler);
|
||||||
|
Subscription sub1 = subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
// Send event
|
||||||
|
String itemId = String.valueOf(System.currentTimeMillis());
|
||||||
|
creatorNode.publish(new Item(itemId));
|
||||||
|
|
||||||
|
ItemEventCoordinator<Item> coord = queue.take();
|
||||||
|
assertEquals(1, coord.events.getItems().size());
|
||||||
|
assertEquals(itemId, coord.events.getItems().get(0).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSendAndReceiveSimplePayload() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId = "TestNode" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
LeafNode creatorNode = getPubnode(creatorMgr, nodeId, true, true);
|
||||||
|
|
||||||
|
BlockingQueue<ItemEventCoordinator<PayloadItem<SimplePayload>>> queue = new ArrayBlockingQueue<ItemEventCoordinator<PayloadItem<SimplePayload>>>(3);
|
||||||
|
|
||||||
|
// Setup event receiver
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode = (LeafNode)subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
ItemEventCoordinator<PayloadItem<SimplePayload>> sub1Handler = new ItemEventCoordinator<PayloadItem<SimplePayload>>(queue, "sub1");
|
||||||
|
subNode.addItemEventListener(sub1Handler);
|
||||||
|
Subscription sub1 = subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
// Send event
|
||||||
|
String itemId = String.valueOf(System.currentTimeMillis());
|
||||||
|
String payloadString = "<book xmlns=\"pubsub:test:book\"><author>Sir Arthur Conan Doyle</author></book>";
|
||||||
|
creatorNode.send(new PayloadItem<SimplePayload>(itemId, new SimplePayload("book", "pubsub:test:book", payloadString)));
|
||||||
|
|
||||||
|
ItemEventCoordinator<PayloadItem<SimplePayload>> coord = queue.take();
|
||||||
|
assertEquals(1, coord.events.getItems().size());
|
||||||
|
PayloadItem<SimplePayload> item = coord.events.getItems().get(0);
|
||||||
|
assertEquals(itemId, item.getId());
|
||||||
|
assertTrue(item.getPayload() instanceof SimplePayload);
|
||||||
|
assertEquals(payloadString, item.getPayload().toXML());
|
||||||
|
assertEquals("book", item.getPayload().getElementName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For this test, the following extension needs to be added to the meta-inf/smack.providers file
|
||||||
|
*
|
||||||
|
* <extensionProvider>
|
||||||
|
* <elementName>car</elementName>
|
||||||
|
* <namespace>pubsub:test:vehicle</namespace>
|
||||||
|
* <className>org.jivesoftware.smackx.pubsub.CarExtensionProvider</className>
|
||||||
|
* </extensionProvider>
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
public void testSendAndReceiveCarPayload() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId = "TestNode" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
Node creatorNode = getPubnode(creatorMgr, nodeId, true, true);
|
||||||
|
|
||||||
|
BlockingQueue<ItemEventCoordinator> queue = new ArrayBlockingQueue<ItemEventCoordinator>(3);
|
||||||
|
|
||||||
|
// Setup event receiver
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
Node subNode = subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
ItemEventCoordinator sub1Handler = new ItemEventCoordinator(queue, "sub1");
|
||||||
|
subNode.addItemEventListener(sub1Handler);
|
||||||
|
Subscription sub1 = subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
// Send event
|
||||||
|
String itemId = String.valueOf(System.currentTimeMillis());
|
||||||
|
String payloadString = "<car xmlns='pubsub:test:vehicle'><paint color='green'/><tires num='4'/></car>";
|
||||||
|
creatorNode.send(new Item(itemId, new SimplePayload("car", "pubsub:test:vehicle", payloadString)));
|
||||||
|
|
||||||
|
ItemEventCoordinator coord = queue.take();
|
||||||
|
assertEquals(1, coord.events.getItems().size());
|
||||||
|
Item item = coord.events.getItems().get(0);
|
||||||
|
assertEquals(itemId, item.getId());
|
||||||
|
assertTrue(item.getPayload() instanceof CarExtension);
|
||||||
|
|
||||||
|
CarExtension car = (CarExtension)item.getPayload();
|
||||||
|
assertEquals("green", car.getColor());
|
||||||
|
assertEquals(4, car.getNumTires());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void testSendAndReceiveMultipleSubs() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId = "TestNode" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
LeafNode creatorNode = getPubnode(creatorMgr, nodeId, true, false);
|
||||||
|
|
||||||
|
BlockingQueue<ItemEventCoordinator<Item>> queue = new ArrayBlockingQueue<ItemEventCoordinator<Item>>(3);
|
||||||
|
ItemEventCoordinator<Item> creatorHandler = new ItemEventCoordinator<Item>(queue, "creator");
|
||||||
|
creatorNode.addItemEventListener(creatorHandler);
|
||||||
|
|
||||||
|
// Setup event receiver
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode = (LeafNode)subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
ItemEventCoordinator<Item> sub1Handler = new ItemEventCoordinator<Item>(queue, "sub1");
|
||||||
|
subNode.addItemEventListener(sub1Handler);
|
||||||
|
Subscription sub1 = subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
ItemEventCoordinator<Item> sub2Handler = new ItemEventCoordinator<Item>(queue, "sub2");
|
||||||
|
subNode.addItemEventListener(sub2Handler);
|
||||||
|
Subscription sub2 = subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
// Send event
|
||||||
|
String itemId = String.valueOf(System.currentTimeMillis());
|
||||||
|
creatorNode.send(new Item(itemId));
|
||||||
|
|
||||||
|
for(int i=0; i<3; i++)
|
||||||
|
{
|
||||||
|
ItemEventCoordinator<Item> coord = queue.take();
|
||||||
|
assertEquals(1, coord.events.getItems().size());
|
||||||
|
assertEquals(itemId, coord.events.getItems().iterator().next().getId());
|
||||||
|
|
||||||
|
if (coord.id.equals("sub1") || coord.id.equals("sub2"))
|
||||||
|
{
|
||||||
|
assertEquals(2, coord.events.getSubscriptions().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSendAndReceiveMultipleItems() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId = "TestNode" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
|
||||||
|
LeafNode creatorNode = getPubnode(creatorMgr, nodeId, true, false);
|
||||||
|
|
||||||
|
BlockingQueue<ItemEventCoordinator<Item>> queue = new ArrayBlockingQueue<ItemEventCoordinator<Item>>(3);
|
||||||
|
ItemEventCoordinator<Item> creatorHandler = new ItemEventCoordinator<Item>(queue, "creator");
|
||||||
|
creatorNode.addItemEventListener(creatorHandler);
|
||||||
|
creatorNode.subscribe(getConnection(0).getUser());
|
||||||
|
|
||||||
|
// Setup event receiver
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode = (LeafNode)subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
ItemEventCoordinator<Item> sub1Handler = new ItemEventCoordinator<Item>(queue, "sub1");
|
||||||
|
subNode.addItemEventListener(sub1Handler);
|
||||||
|
Subscription sub1 = subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
ItemEventCoordinator<Item> sub2Handler = new ItemEventCoordinator<Item>(queue, "sub2");
|
||||||
|
subNode.addItemEventListener(sub2Handler);
|
||||||
|
Subscription sub2 = subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
assertEquals(Subscription.State.subscribed, sub1.getState());
|
||||||
|
assertEquals(Subscription.State.subscribed, sub2.getState());
|
||||||
|
|
||||||
|
// Send event
|
||||||
|
String itemId = String.valueOf(System.currentTimeMillis());
|
||||||
|
|
||||||
|
Collection<Item> items = new ArrayList<Item>(3);
|
||||||
|
items.add(new Item("First-" + itemId));
|
||||||
|
items.add(new Item("Second-" + itemId));
|
||||||
|
items.add(new Item("Third-" + itemId));
|
||||||
|
creatorNode.send(items);
|
||||||
|
|
||||||
|
for(int i=0; i<3; i++)
|
||||||
|
{
|
||||||
|
ItemEventCoordinator<Item> coord = queue.poll(5, TimeUnit.SECONDS);
|
||||||
|
if (coord == creatorHandler)
|
||||||
|
assertEquals(1, coord.events.getSubscriptions().size());
|
||||||
|
else
|
||||||
|
assertEquals(2, coord.events.getSubscriptions().size());
|
||||||
|
assertEquals(3, coord.events.getItems().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSendAndReceiveDelayed() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId = "TestNode" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
|
||||||
|
LeafNode creatorNode = getPubnode(creatorMgr, nodeId, true, false);
|
||||||
|
|
||||||
|
// Send event
|
||||||
|
String itemId = String.valueOf("DelayId-" + System.currentTimeMillis());
|
||||||
|
String payloadString = "<book xmlns='pubsub:test:book'><author>Sir Arthur Conan Doyle</author></book>";
|
||||||
|
creatorNode.send(new PayloadItem<SimplePayload>(itemId, new SimplePayload("book", "pubsub:test:book", payloadString)));
|
||||||
|
|
||||||
|
Thread.sleep(1000);
|
||||||
|
|
||||||
|
BlockingQueue<ItemEventCoordinator<PayloadItem<SimplePayload>>> queue = new ArrayBlockingQueue<ItemEventCoordinator<PayloadItem<SimplePayload>>>(3);
|
||||||
|
|
||||||
|
// Setup event receiver
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode = (LeafNode)subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
ItemEventCoordinator<PayloadItem<SimplePayload>> sub1Handler = new ItemEventCoordinator<PayloadItem<SimplePayload>>(queue, "sub1");
|
||||||
|
subNode.addItemEventListener(sub1Handler);
|
||||||
|
Subscription sub1 = subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
ItemEventCoordinator<PayloadItem<SimplePayload>> coord = queue.take();
|
||||||
|
assertTrue(coord.events.isDelayed());
|
||||||
|
assertNotNull(coord.events.getPublishedDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteItemAndNotify() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId = "TestNode" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
|
||||||
|
LeafNode creatorNode = getPubnode(creatorMgr, nodeId, true, false);
|
||||||
|
|
||||||
|
BlockingQueue<ItemDeleteCoordinator> queue = new ArrayBlockingQueue<ItemDeleteCoordinator>(3);
|
||||||
|
|
||||||
|
// Setup event receiver
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode = (LeafNode)subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
ItemDeleteCoordinator sub1Handler = new ItemDeleteCoordinator(queue, "sub1");
|
||||||
|
subNode.addItemDeleteListener(sub1Handler);
|
||||||
|
subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
// Send event
|
||||||
|
String itemId = String.valueOf(System.currentTimeMillis());
|
||||||
|
|
||||||
|
Collection<Item> items = new ArrayList<Item>(3);
|
||||||
|
String id1 = "First-" + itemId;
|
||||||
|
String id2 = "Second-" + itemId;
|
||||||
|
String id3 = "Third-" + itemId;
|
||||||
|
items.add(new Item(id1));
|
||||||
|
items.add(new Item(id2));
|
||||||
|
items.add(new Item(id3));
|
||||||
|
creatorNode.send(items);
|
||||||
|
|
||||||
|
creatorNode.deleteItem(id1);
|
||||||
|
|
||||||
|
ItemDeleteCoordinator coord = queue.poll(5, TimeUnit.SECONDS);
|
||||||
|
assertEquals(1, coord.event.getItemIds().size());
|
||||||
|
assertEquals(id1, coord.event.getItemIds().get(0));
|
||||||
|
|
||||||
|
creatorNode.deleteItem(Arrays.asList(id2, id3));
|
||||||
|
|
||||||
|
coord = queue.poll(5, TimeUnit.SECONDS);
|
||||||
|
assertEquals(2, coord.event.getItemIds().size());
|
||||||
|
assertTrue(coord.event.getItemIds().contains(id2));
|
||||||
|
assertTrue(coord.event.getItemIds().contains(id3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPurgeAndNotify() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId = "TestNode" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
|
||||||
|
LeafNode creatorNode = getPubnode(creatorMgr, nodeId, true, false);
|
||||||
|
|
||||||
|
BlockingQueue<ItemDeleteCoordinator> queue = new ArrayBlockingQueue<ItemDeleteCoordinator>(3);
|
||||||
|
|
||||||
|
// Setup event receiver
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode = (LeafNode)subMgr.getNode(nodeId);
|
||||||
|
|
||||||
|
ItemDeleteCoordinator sub1Handler = new ItemDeleteCoordinator(queue, "sub1");
|
||||||
|
subNode.addItemDeleteListener(sub1Handler);
|
||||||
|
subNode.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
// Send event
|
||||||
|
String itemId = String.valueOf(System.currentTimeMillis());
|
||||||
|
|
||||||
|
Collection<Item> items = new ArrayList<Item>(3);
|
||||||
|
String id1 = "First-" + itemId;
|
||||||
|
String id2 = "Second-" + itemId;
|
||||||
|
String id3 = "Third-" + itemId;
|
||||||
|
items.add(new Item(id1));
|
||||||
|
items.add(new Item(id2));
|
||||||
|
items.add(new Item(id3));
|
||||||
|
creatorNode.send(items);
|
||||||
|
|
||||||
|
creatorNode.deleteAllItems();
|
||||||
|
|
||||||
|
ItemDeleteCoordinator coord = queue.poll(5, TimeUnit.SECONDS);
|
||||||
|
assertNull(nodeId, coord.event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListenerMultipleNodes() throws Exception
|
||||||
|
{
|
||||||
|
// Setup event source
|
||||||
|
String nodeId1 = "Node-1-" + System.currentTimeMillis();
|
||||||
|
PubSubManager creatorMgr = new PubSubManager(getConnection(0), getService());
|
||||||
|
String nodeId2 = "Node-2-" + System.currentTimeMillis();
|
||||||
|
|
||||||
|
LeafNode creatorNode1 = getPubnode(creatorMgr, nodeId1, true, false);
|
||||||
|
LeafNode creatorNode2 = getPubnode(creatorMgr, nodeId2, true, false);
|
||||||
|
|
||||||
|
BlockingQueue<ItemEventCoordinator<Item>> queue = new ArrayBlockingQueue<ItemEventCoordinator<Item>>(3);
|
||||||
|
|
||||||
|
PubSubManager subMgr = new PubSubManager(getConnection(1), getService());
|
||||||
|
LeafNode subNode1 = (LeafNode)subMgr.getNode(nodeId1);
|
||||||
|
LeafNode subNode2 = (LeafNode)subMgr.getNode(nodeId2);
|
||||||
|
|
||||||
|
subNode1.addItemEventListener(new ItemEventCoordinator<Item>(queue, "sub1"));
|
||||||
|
subNode2.addItemEventListener(new ItemEventCoordinator<Item>(queue, "sub2"));
|
||||||
|
|
||||||
|
subNode1.subscribe(getConnection(1).getUser());
|
||||||
|
subNode2.subscribe(getConnection(1).getUser());
|
||||||
|
|
||||||
|
creatorNode1.send(new Item("item1"));
|
||||||
|
creatorNode2.send(new Item("item2"));
|
||||||
|
boolean check1 = false;
|
||||||
|
boolean check2 = false;
|
||||||
|
|
||||||
|
for (int i=0; i<2; i++)
|
||||||
|
{
|
||||||
|
ItemEventCoordinator<Item> event = queue.take();
|
||||||
|
|
||||||
|
if (event.id.equals("sub1"))
|
||||||
|
{
|
||||||
|
assertEquals(event.events.getNodeId(), nodeId1);
|
||||||
|
check1 = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assertEquals(event.events.getNodeId(), nodeId2);
|
||||||
|
check2 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(check1);
|
||||||
|
assertTrue(check2);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemEventCoordinator <T extends Item> implements ItemEventListener<T>
|
||||||
|
{
|
||||||
|
private BlockingQueue<ItemEventCoordinator<T>> theQueue;
|
||||||
|
private ItemPublishEvent<T> events;
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
ItemEventCoordinator(BlockingQueue<ItemEventCoordinator<T>> queue, String id)
|
||||||
|
{
|
||||||
|
theQueue = queue;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handlePublishedItems(ItemPublishEvent<T> items)
|
||||||
|
{
|
||||||
|
events = items;
|
||||||
|
theQueue.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "ItemEventCoordinator: " + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class NodeConfigCoordinator implements NodeConfigListener
|
||||||
|
{
|
||||||
|
private BlockingQueue<NodeConfigCoordinator> theQueue;
|
||||||
|
private String id;
|
||||||
|
private ConfigurationEvent event;
|
||||||
|
|
||||||
|
NodeConfigCoordinator(BlockingQueue<NodeConfigCoordinator> queue, String id)
|
||||||
|
{
|
||||||
|
theQueue = queue;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleNodeConfiguration(ConfigurationEvent config)
|
||||||
|
{
|
||||||
|
event = config;
|
||||||
|
theQueue.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "NodeConfigCoordinator: " + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemDeleteCoordinator implements ItemDeleteListener
|
||||||
|
{
|
||||||
|
private BlockingQueue<ItemDeleteCoordinator> theQueue;
|
||||||
|
private String id;
|
||||||
|
private ItemDeleteEvent event;
|
||||||
|
|
||||||
|
ItemDeleteCoordinator(BlockingQueue<ItemDeleteCoordinator> queue, String id)
|
||||||
|
{
|
||||||
|
theQueue = queue;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleDeletedItems(ItemDeleteEvent delEvent)
|
||||||
|
{
|
||||||
|
event = delEvent;
|
||||||
|
theQueue.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void handlePurge()
|
||||||
|
{
|
||||||
|
event = null;
|
||||||
|
theQueue.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "ItemDeleteCoordinator: " + id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static private LeafNode getPubnode(PubSubManager manager, String id, boolean persistItems, boolean deliverPayload)
|
||||||
|
throws XMPPException
|
||||||
|
{
|
||||||
|
ConfigureForm form = new ConfigureForm(FormType.submit);
|
||||||
|
form.setPersistentItems(persistItems);
|
||||||
|
form.setDeliverPayloads(deliverPayload);
|
||||||
|
form.setAccessModel(AccessModel.open);
|
||||||
|
return (LeafNode)manager.createNode(id, form);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
101
test/org/jivesoftware/smackx/pubsub/TestMessageContent.java
Normal file
101
test/org/jivesoftware/smackx/pubsub/TestMessageContent.java
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-08-05
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
public class TestMessageContent extends TestCase
|
||||||
|
{
|
||||||
|
String payloadXmlWithNS = "<book xmlns='pubsub:test:book'><author name='Stephen King'/></book>";
|
||||||
|
|
||||||
|
public void testItemWithId()
|
||||||
|
{
|
||||||
|
Item item = new Item("123");
|
||||||
|
assertEquals("<item id='123'/>", item.toXML());
|
||||||
|
assertEquals("item", item.getElementName());
|
||||||
|
assertNull(item.getNamespace());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testItemWithNoId()
|
||||||
|
{
|
||||||
|
Item item = new Item();
|
||||||
|
assertEquals("<item/>", item.toXML());
|
||||||
|
|
||||||
|
Item itemNull = new Item(null);
|
||||||
|
assertEquals("<item/>", itemNull.toXML());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSimplePayload()
|
||||||
|
{
|
||||||
|
SimplePayload payloadNS = new SimplePayload("book", "pubsub:test:book", payloadXmlWithNS);
|
||||||
|
|
||||||
|
assertEquals(payloadXmlWithNS, payloadNS.toXML());
|
||||||
|
|
||||||
|
String payloadXmlWithNoNS = "<book><author name='Stephen King'/></book>";
|
||||||
|
SimplePayload payloadNoNS = new SimplePayload("book", null, "<book><author name='Stephen King'/></book>");
|
||||||
|
|
||||||
|
assertEquals(payloadXmlWithNoNS, payloadNoNS.toXML());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPayloadItemWithId()
|
||||||
|
{
|
||||||
|
SimplePayload payload = new SimplePayload("book", "pubsub:test:book", payloadXmlWithNS);
|
||||||
|
PayloadItem<SimplePayload> item = new PayloadItem<SimplePayload>("123", payload);
|
||||||
|
|
||||||
|
String xml = "<item id='123'>" + payloadXmlWithNS + "</item>";
|
||||||
|
assertEquals(xml, item.toXML());
|
||||||
|
assertEquals("item", item.getElementName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPayloadItemWithNoId()
|
||||||
|
{
|
||||||
|
SimplePayload payload = new SimplePayload("book", "pubsub:test:book", payloadXmlWithNS);
|
||||||
|
PayloadItem<SimplePayload> item = new PayloadItem<SimplePayload>(null, payload);
|
||||||
|
|
||||||
|
String xml = "<item>" + payloadXmlWithNS + "</item>";
|
||||||
|
assertEquals(xml, item.toXML());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPayloadItemWithIdNoPayload()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PayloadItem<SimplePayload> item = new PayloadItem<SimplePayload>("123", null);
|
||||||
|
fail("Should have thrown IllegalArgumentException");
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPayloadItemWithNoIdNoPayload()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PayloadItem<SimplePayload> item = new PayloadItem<SimplePayload>(null, null);
|
||||||
|
fail("Should have thrown IllegalArgumentException");
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRetractItem()
|
||||||
|
{
|
||||||
|
RetractItem item = new RetractItem("1234");
|
||||||
|
|
||||||
|
assertEquals("<retract id='1234'/>", item.toXML());
|
||||||
|
assertEquals("retract", item.getElementName());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new RetractItem(null);
|
||||||
|
fail("Should have thrown IllegalArgumentException");
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
74
test/org/jivesoftware/smackx/pubsub/test/PubSubTestCase.java
Normal file
74
test/org/jivesoftware/smackx/pubsub/test/PubSubTestCase.java
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-05-05
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.test;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.test.SmackTestCase;
|
||||||
|
import org.jivesoftware.smackx.pubsub.AccessModel;
|
||||||
|
import org.jivesoftware.smackx.pubsub.ConfigureForm;
|
||||||
|
import org.jivesoftware.smackx.pubsub.FormType;
|
||||||
|
import org.jivesoftware.smackx.pubsub.LeafNode;
|
||||||
|
import org.jivesoftware.smackx.pubsub.PubSubManager;
|
||||||
|
|
||||||
|
abstract public class PubSubTestCase extends SmackTestCase
|
||||||
|
{
|
||||||
|
private PubSubManager[] manager;
|
||||||
|
|
||||||
|
public PubSubTestCase(String arg0)
|
||||||
|
{
|
||||||
|
super(arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PubSubTestCase()
|
||||||
|
{
|
||||||
|
super("PubSub Test Case");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected LeafNode getRandomPubnode(PubSubManager pubMgr, boolean persistItems, boolean deliverPayload) throws XMPPException
|
||||||
|
{
|
||||||
|
ConfigureForm form = new ConfigureForm(FormType.submit);
|
||||||
|
form.setPersistentItems(persistItems);
|
||||||
|
form.setDeliverPayloads(deliverPayload);
|
||||||
|
form.setAccessModel(AccessModel.open);
|
||||||
|
return (LeafNode)pubMgr.createNode("/test/Pubnode" + System.currentTimeMillis(), form);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected LeafNode getPubnode(PubSubManager pubMgr, boolean persistItems, boolean deliverPayload, String nodeId) throws XMPPException
|
||||||
|
{
|
||||||
|
LeafNode node = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
node = (LeafNode)pubMgr.getNode(nodeId);
|
||||||
|
}
|
||||||
|
catch (XMPPException e)
|
||||||
|
{
|
||||||
|
ConfigureForm form = new ConfigureForm(FormType.submit);
|
||||||
|
form.setPersistentItems(persistItems);
|
||||||
|
form.setDeliverPayloads(deliverPayload);
|
||||||
|
form.setAccessModel(AccessModel.open);
|
||||||
|
node = (LeafNode)pubMgr.createNode(nodeId, form);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PubSubManager getManager(int idx)
|
||||||
|
{
|
||||||
|
if (manager == null)
|
||||||
|
{
|
||||||
|
manager = new PubSubManager[getMaxConnections()];
|
||||||
|
|
||||||
|
for(int i=0; i<manager.length; i++)
|
||||||
|
{
|
||||||
|
manager[i] = new PubSubManager(getConnection(i), getService());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return manager[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getService()
|
||||||
|
{
|
||||||
|
return "pubsub." + getServiceName();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Created on 2009-05-05
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.pubsub.test;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smackx.pubsub.LeafNode;
|
||||||
|
import org.jivesoftware.smackx.pubsub.PubSubManager;
|
||||||
|
|
||||||
|
public class SingleUserTestCase extends PubSubTestCase
|
||||||
|
{
|
||||||
|
protected PubSubManager getManager()
|
||||||
|
{
|
||||||
|
return getManager(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected LeafNode getPubnode(boolean persistItems, boolean deliverPayload) throws XMPPException
|
||||||
|
{
|
||||||
|
return getRandomPubnode(getManager(), persistItems, deliverPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxConnections()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue