Commit 93f63ed9 authored by guus's avatar guus

Currently, there's an interface defining a DiscoItem object. There's no...

Currently, there's an interface defining a DiscoItem object. There's no implementation of it, other than in-line implementations in methods (the same goes for the sub-interface, DiscoServerItem). Where manipulations of DiscoItem objects are done, Dom4J Element instances are used instead. The DiscoItem interface has been replaced by an implementation of that interface (again, same goes for the sub-interface, which is now a subclass). As I assumed there would not be other implementations of the same interface (which would give you 'another kind' of DiscoItem objects, but what's the point?), I removed the interface completely.

As a result of the changed representation, the DiscoItemsProvider interface now declares a method that returns an Iterator of DiscoItem objects, instead of Elements. This caused changes in a number of classes.

Result Set Management functionality has been added, which causes all disco#items request to be result set managable (this is, for instance, useful for large listings or MUC rooms).

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/branches/rsm@9166 b35dd754-fafc-0310-a699-88a17e54d16e
parent 4bc5ef9d
......@@ -112,21 +112,17 @@ public class AdHocCommandHandler extends IQHandler
}
}
public Iterator<Element> getItems(String name, String node, JID senderJID) {
List<Element> answer = new ArrayList<Element>();
public Iterator<DiscoItem> getItems(String name, String node, JID senderJID) {
List<DiscoItem> answer = new ArrayList<DiscoItem>();
if (!NAMESPACE.equals(node)) {
answer = Collections.emptyList();
}
else {
Element item;
for (AdHocCommand command : manager.getCommands()) {
// Only include commands that the sender can invoke (i.e. has enough permissions)
if (command.hasPermission(senderJID)) {
item = DocumentHelper.createElement("item");
item.addAttribute("jid", serverName);
item.addAttribute("node", command.getCode());
item.addAttribute("name", command.getLabel());
final DiscoItem item = new DiscoItem(new JID(serverName),
command.getLabel(), command.getCode(), null);
answer.add(item);
}
}
......
......@@ -167,7 +167,7 @@ public class InternalComponentManager extends BasicModule implements ComponentMa
// Remove the disco item from the server for the component that is being removed
IQDiscoItemsHandler iqDiscoItemsHandler = XMPPServer.getInstance().getIQDiscoItemsHandler();
if (iqDiscoItemsHandler != null) {
iqDiscoItemsHandler.removeComponentItem(componentJID.toBareJID());
iqDiscoItemsHandler.removeComponentItem(componentJID);
}
// Ask the component to shutdown
......@@ -445,8 +445,8 @@ public class InternalComponentManager extends BasicModule implements ComponentMa
return;
}
try {
XMPPServer.getInstance().getIQDiscoItemsHandler().addComponentItem(packet.getFrom()
.toBareJID(),
XMPPServer.getInstance().getIQDiscoItemsHandler().addComponentItem(new JID(packet.getFrom()
.toBareJID()),
identity.attributeValue("name"));
if (component instanceof ComponentSession.ExternalComponent) {
ComponentSession.ExternalComponent externalComponent =
......
......@@ -11,51 +11,169 @@
package org.jivesoftware.openfire.disco;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jivesoftware.util.resultsetmanager.Result;
import org.xmpp.packet.JID;
/**
* An item is associated with an XMPP Entity, usually thought of a children of the parent
* entity and normally are addressable as a JID.<p>
* <p/>
* An item associated with an entity may not be addressable as a JID. In order to handle
* such items, Service Discovery uses an optional 'node' attribute that supplements the
* 'jid' attribute.
* <p>
* An item is associated with an XMPP Entity, usually thought of a children of
* the parent entity and normally are addressable as a JID.
* </p>
* <p>
* An item associated with an entity may not be addressable as a JID. In order
* to handle such items, Service Discovery uses an optional 'node' attribute
* that supplements the 'jid' attribute.
* </p>
*
* @author Gaston Dombiak
*/
public interface DiscoItem {
public class DiscoItem implements Result {
private final JID jid;
private final String name;
private final String node;
private final String action;
/**
* <p>
* Creates a new DiscoItem instance.
* </p>
*
* @param jid
* specifies the Jabber ID of the item "owner" or location
* (required).
* @param name
* specifies a natural-language name for the item (can be null).
* @param node
* specifies the particular node associated with the JID of the
* item "owner" or location (can be null).
* @param action
* specifies the action to be taken for the item.
* @throws IllegalArgumentException
* If a required parameter was null, or if the supplied 'action'
* parameter has another value than 'null', "update" or
* "remove".
*/
public DiscoItem(JID jid, String name, String node, String action) {
if (jid == null) {
throw new IllegalArgumentException("Argument 'jid' cannot be null.");
}
if (action != null && !action.equals("update")
&& !action.equals("remove")) {
throw new IllegalArgumentException(
"Argument 'jid' cannot have any other value than null, \"update\" or \"remove\".");
}
this.jid = jid;
this.name = name;
this.node = node;
this.action = action;
}
/**
* <p>
* Returns the entity's ID.
* </p>
*
* @return the entity's ID.
*/
public abstract String getJID();
public JID getJID() {
return jid;
}
/**
* Returns the node attribute that supplements the 'jid' attribute. A node is merely
* something that is associated with a JID and for which the JID can provide information.<p>
* <p/>
* Node attributes SHOULD be used only when trying to provide or query information which
* is not directly addressable.
* <p>
* Returns the node attribute that supplements the 'jid' attribute. A node
* is merely something that is associated with a JID and for which the JID
* can provide information.
* </p>
* <p>
* Node attributes SHOULD be used only when trying to provide or query
* information which is not directly addressable.
* </p>
*
* @return the node attribute that supplements the 'jid' attribute
*/
public abstract String getNode();
public String getNode() {
return node;
}
/**
* Returns the entity's name. The entity's name specifies in natural-language the name for the
* item.
* <p>
* Returns the entity's name. The entity's name specifies in
* natural-language the name for the item.
* </p>
*
* @return the entity's name.
*/
public abstract String getName();
public String getName() {
return name;
}
/**
* Returns the action (i.e. update or remove) that indicates what must be done with this item or
* null if none. An "update" action requests the server to create or update the item. Whilst a
* "remove" action requests to remove the item.
* <p>
* Returns the action (i.e. update or remove) that indicates what must be
* done with this item or null if none. An "update" action requests the
* server to create or update the item. Whilst a "remove" action requests to
* remove the item.
* </p>
*
* @return the action (i.e. update or remove) that indicates what must be done with this item or
* null if none.
* @return the action (i.e. update or remove) that indicates what must be
* done with this item or null if none.
*/
public abstract String getAction();
public String getAction() {
return action;
}
/**
* Returns a dom4j element that represents this DiscoItem object.
*
* @return element representing this object.
*/
public Element getElement() {
final Element element = DocumentHelper.createElement("item");
if (action != null) {
element.addAttribute("action", action);
}
if (jid != null) {
element.addAttribute("jid", jid.toString());
}
if (name != null) {
element.addAttribute("name", name);
}
if (node != null) {
element.addAttribute("node", node);
}
return element;
}
/*
* (non-Javadoc)
*
* @see org.jivesoftware.util.resultsetmanager.Result#getUID()
*/
public String getUID() {
final StringBuilder sb = new StringBuilder(jid.toString());
if (name != null) {
sb.append(name);
}
if (node != null) {
sb.append(node);
}
if (action != null) {
sb.append(action);
}
return sb.toString();
}
}
\ No newline at end of file
......@@ -11,11 +11,10 @@
package org.jivesoftware.openfire.disco;
import org.dom4j.Element;
import org.xmpp.packet.JID;
import java.util.Iterator;
import org.xmpp.packet.JID;
/**
* A DiscoItemsProvider is responsible for providing the items associated with a JID's name and
* node. For example, the room service could implement this interface in order to provide
......@@ -30,7 +29,7 @@ import java.util.Iterator;
public interface DiscoItemsProvider {
/**
* Returns an Iterator (of Element) with the target entity's items or null if none. Each Element
* Returns an Iterator (of DiscoItem) with the target entity's items or null if none. Each DiscoItem
* must include a JID attribute and may include the name and node attributes of the entity. In
* case that the sender of the disco request is not authorized to discover items an
* UnauthorizedException will be thrown.
......@@ -38,8 +37,8 @@ public interface DiscoItemsProvider {
* @param name the recipient JID's name.
* @param node the requested disco node.
* @param senderJID the XMPPAddress of user that sent the disco items request.
* @return an Iterator (of Element) with the target entity's items or null if none.
* @return an Iterator (of DiscoItem) with the target entity's items or null if none.
*/
public abstract Iterator<Element> getItems(String name, String node, JID senderJID);
public abstract Iterator<DiscoItem> getItems(String name, String node, JID senderJID);
}
......@@ -11,6 +11,8 @@
package org.jivesoftware.openfire.disco;
import org.xmpp.packet.JID;
/**
* Represent a DiscoItem provided by the server. Therefore, the DiscoServerItems are responsible
* for providing the DiscoInfoProvider and DiscoItemsProvider that will provide the information and
......@@ -26,7 +28,27 @@ package org.jivesoftware.openfire.disco;
*
* @author Gaston Dombiak
*/
public interface DiscoServerItem extends DiscoItem {
public class DiscoServerItem extends DiscoItem {
private final DiscoInfoProvider infoProvider;
private final DiscoItemsProvider itemsProvider;
public DiscoServerItem(JID jid, String name, String node, String action, DiscoInfoProvider infoProvider, DiscoItemsProvider itemsProvider) {
super(jid, name, node, action);
if (infoProvider == null)
{
throw new IllegalArgumentException("Argument 'infoProvider' cannot be null.");
}
if (itemsProvider == null)
{
throw new IllegalArgumentException("Argument 'itemsProvider' cannot be null.");
}
this.infoProvider = infoProvider;
this.itemsProvider = itemsProvider;
}
/**
* Returns the DiscoInfoProvider responsible for providing the information related to this item.
......@@ -35,7 +57,10 @@ public interface DiscoServerItem extends DiscoItem {
*
* @return the DiscoInfoProvider responsible for providing the information related to this item.
*/
public abstract DiscoInfoProvider getDiscoInfoProvider();
public DiscoInfoProvider getDiscoInfoProvider()
{
return infoProvider;
}
/**
* Returns the DiscoItemsProvider responsible for providing the items related to this item.
......@@ -44,5 +69,8 @@ public interface DiscoServerItem extends DiscoItem {
*
* @return the DiscoItemsProvider responsible for providing the items related to this item.
*/
public abstract DiscoItemsProvider getDiscoItemsProvider();
public DiscoItemsProvider getDiscoItemsProvider()
{
return itemsProvider;
}
}
......@@ -17,6 +17,7 @@ import org.jivesoftware.openfire.*;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.container.BasicModule;
import org.jivesoftware.openfire.disco.DiscoInfoProvider;
import org.jivesoftware.openfire.disco.DiscoItem;
import org.jivesoftware.openfire.disco.DiscoItemsProvider;
import org.jivesoftware.openfire.disco.DiscoServerItem;
import org.jivesoftware.openfire.disco.ServerItemsProvider;
......@@ -206,7 +207,7 @@ public class FileTransferProxy extends BasicModule
super.stop();
XMPPServer.getInstance().getIQDiscoItemsHandler()
.removeComponentItem(getAddress().toString());
.removeComponentItem(getAddress());
routingTable.removeComponentRoute(getAddress());
connectionManager.disable();
}
......@@ -284,31 +285,11 @@ public class FileTransferProxy extends BasicModule
return items.iterator();
}
items.add(new DiscoServerItem() {
public String getJID() {
return getServiceDomain();
}
public String getName() {
return "Socks 5 Bytestreams Proxy";
}
public String getAction() {
return null;
}
final DiscoServerItem item = new DiscoServerItem(new JID(
getServiceDomain()), "Socks 5 Bytestreams Proxy", null, null, this,
this);
items.add(item);
public String getNode() {
return null;
}
public DiscoInfoProvider getDiscoInfoProvider() {
return FileTransferProxy.this;
}
public DiscoItemsProvider getDiscoItemsProvider() {
return FileTransferProxy.this;
}
});
return items.iterator();
}
......@@ -338,9 +319,9 @@ public class FileTransferProxy extends BasicModule
return true;
}
public Iterator<Element> getItems(String name, String node, JID senderJID) {
public Iterator<DiscoItem> getItems(String name, String node, JID senderJID) {
// A proxy server has no items
return new ArrayList<Element>().iterator();
return new ArrayList<DiscoItem>().iterator();
}
public void process(Packet packet) throws UnauthorizedException, PacketException {
......
......@@ -159,22 +159,17 @@ public class IQOfflineMessagesHandler extends IQHandler implements ServerFeature
return NAMESPACE.equals(node) && userManager.isRegisteredUser(senderJID.getNode());
}
public Iterator<Element> getItems(String name, String node, JID senderJID) {
public Iterator<DiscoItem> getItems(String name, String node, JID senderJID) {
// Mark that offline messages shouldn't be sent when the user becomes available
stopOfflineFlooding(senderJID);
List<Element> answer = new ArrayList<Element>();
Element item;
List<DiscoItem> answer = new ArrayList<DiscoItem>();
for (OfflineMessage offlineMessage : messageStore.getMessages(senderJID.getNode(), false)) {
item = DocumentHelper.createElement("item");
item.addAttribute("jid", senderJID.toBareJID());
item.addAttribute("name", offlineMessage.getFrom().toString());
final DiscoItem item;
synchronized (dateFormat) {
item.addAttribute("node", dateFormat.format(offlineMessage.getCreationDate()));
item = new DiscoItem(senderJID, offlineMessage.getFrom().toString(), dateFormat.format(offlineMessage.getCreationDate()), null);
}
answer.add(item);
}
return answer.iterator();
}
......
......@@ -17,6 +17,7 @@ import org.jivesoftware.openfire.*;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.container.BasicModule;
import org.jivesoftware.openfire.disco.DiscoInfoProvider;
import org.jivesoftware.openfire.disco.DiscoItem;
import org.jivesoftware.openfire.disco.DiscoItemsProvider;
import org.jivesoftware.openfire.disco.DiscoServerItem;
import org.jivesoftware.openfire.disco.ServerItemsProvider;
......@@ -98,14 +99,14 @@ public class MediaProxyService extends BasicModule
XMPPServer.getInstance().getIQDiscoItemsHandler().addServerItemsProvider(this);
} else {
if (echo != null) echo.cancel();
XMPPServer.getInstance().getIQDiscoItemsHandler().removeComponentItem(getAddress().toString());
XMPPServer.getInstance().getIQDiscoItemsHandler().removeComponentItem(getAddress());
}
}
public void stop() {
super.stop();
mediaProxy.stopProxy();
XMPPServer.getInstance().getIQDiscoItemsHandler().removeComponentItem(getAddress().toString());
XMPPServer.getInstance().getIQDiscoItemsHandler().removeComponentItem(getAddress());
routingTable.removeComponentRoute(getAddress());
if (echo != null) echo.cancel();
}
......@@ -117,9 +118,9 @@ public class MediaProxyService extends BasicModule
return serviceName;
}
public Iterator<Element> getItems(String name, String node, JID senderJID) {
public Iterator<DiscoItem> getItems(String name, String node, JID senderJID) {
// A proxy server has no items
return new ArrayList<Element>().iterator();
return new ArrayList<DiscoItem>().iterator();
}
public void process(Packet packet) throws UnauthorizedException, PacketException {
......@@ -287,37 +288,17 @@ public class MediaProxyService extends BasicModule
return new JID(null, getServiceDomain(), null);
}
public Iterator<DiscoServerItem> getItems() {
public Iterator<DiscoServerItem> getItems()
{
List<DiscoServerItem> items = new ArrayList<DiscoServerItem>();
if (!isEnabled()) {
if (!isEnabled())
{
return items.iterator();
}
items.add(new DiscoServerItem() {
public String getJID() {
return getServiceDomain();
}
public String getName() {
return "Media Proxy Service";
}
public String getAction() {
return null;
}
public String getNode() {
return null;
}
public DiscoInfoProvider getDiscoInfoProvider() {
return MediaProxyService.this;
}
public DiscoItemsProvider getDiscoItemsProvider() {
return MediaProxyService.this;
}
});
final DiscoServerItem item = new DiscoServerItem(new JID(
getServiceDomain()), "Media Proxy Service", null, null, this, this);
items.add(item);
return items.iterator();
}
......
......@@ -19,6 +19,7 @@ import org.jivesoftware.openfire.cluster.ClusterEventListener;
import org.jivesoftware.openfire.cluster.ClusterManager;
import org.jivesoftware.openfire.container.BasicModule;
import org.jivesoftware.openfire.disco.DiscoInfoProvider;
import org.jivesoftware.openfire.disco.DiscoItem;
import org.jivesoftware.openfire.disco.DiscoItemsProvider;
import org.jivesoftware.openfire.disco.DiscoServerItem;
import org.jivesoftware.openfire.disco.ServerItemsProvider;
......@@ -1073,42 +1074,30 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
}
public Iterator<DiscoServerItem> getItems() {
// Check if the service is disabled. Info is not available when disabled.
if (!isServiceEnabled()) {
// Check if the service is disabled. Info is not available when
// disabled.
if (!isServiceEnabled())
{
return null;
}
ArrayList<DiscoServerItem> items = new ArrayList<DiscoServerItem>();
items.add(new DiscoServerItem() {
public String getJID() {
return getServiceDomain();
}
public String getName() {
final ArrayList<DiscoServerItem> items = new ArrayList<DiscoServerItem>();
final String name;
// Check if there is a system property that overrides the default value
String serviceName = JiveGlobals.getProperty("muc.service-name");
if (serviceName != null && serviceName.trim().length() > 0) {
return serviceName;
if (serviceName != null && serviceName.trim().length() > 0)
{
name = serviceName;
}
else
{
// Return the default service name based on the current locale
return LocaleUtils.getLocalizedString("muc.service-name");
name = LocaleUtils.getLocalizedString("muc.service-name");
}
public String getAction() {
return null;
}
public String getNode() {
return null;
}
public DiscoInfoProvider getDiscoInfoProvider() {
return MultiUserChatServerImpl.this;
}
public DiscoItemsProvider getDiscoItemsProvider() {
return MultiUserChatServerImpl.this;
}
});
final DiscoServerItem item = new DiscoServerItem(new JID(
getServiceDomain()), name, null, null, this, this);
items.add(item);
return items.iterator();
}
......@@ -1266,22 +1255,21 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
return false;
}
public Iterator<Element> getItems(String name, String node, JID senderJID) {
public Iterator<DiscoItem> getItems(String name, String node, JID senderJID) {
// Check if the service is disabled. Info is not available when disabled.
if (!isServiceEnabled()) {
return null;
}
List<Element> answer = new ArrayList<Element>();
if (name == null && node == null) {
Element item;
List<DiscoItem> answer = new ArrayList<DiscoItem>();
if (name == null && node == null)
{
// Answer all the public rooms as items
for (MUCRoom room : rooms.values()) {
if (canDiscoverRoom(room)) {
item = DocumentHelper.createElement("item");
item.addAttribute("jid", room.getRole().getRoleAddress().toString());
item.addAttribute("name", room.getNaturalLanguageName());
answer.add(item);
for (MUCRoom room : rooms.values())
{
if (canDiscoverRoom(room))
{
answer.add(new DiscoItem(room.getRole().getRoleAddress(),
room.getNaturalLanguageName(), null, null));
}
}
}
......@@ -1289,13 +1277,9 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
// Answer the room occupants as items if that info is publicly available
MUCRoom room = getChatRoom(name);
if (room != null && canDiscoverRoom(room)) {
Element item;
for (MUCRole role : room.getOccupants()) {
// TODO Should we filter occupants that are invisible (presence is not broadcasted)?
item = DocumentHelper.createElement("item");
item.addAttribute("jid", role.getRoleAddress().toString());
answer.add(item);
answer.add(new DiscoItem(role.getRoleAddress(), null, null, null));
}
}
}
......
......@@ -22,6 +22,7 @@ import org.jivesoftware.openfire.cluster.ClusterManager;
import org.jivesoftware.openfire.component.InternalComponentManager;
import org.jivesoftware.openfire.container.BasicModule;
import org.jivesoftware.openfire.disco.DiscoInfoProvider;
import org.jivesoftware.openfire.disco.DiscoItem;
import org.jivesoftware.openfire.disco.DiscoItemsProvider;
import org.jivesoftware.openfire.disco.DiscoServerItem;
import org.jivesoftware.openfire.disco.ServerItemsProvider;
......@@ -468,32 +469,10 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
public Iterator<DiscoServerItem> getItems() {
ArrayList<DiscoServerItem> items = new ArrayList<DiscoServerItem>();
items.add(new DiscoServerItem() {
public String getJID() {
return getServiceDomain();
}
public String getName() {
return "Publish-Subscribe service";
}
public String getAction() {
return null;
}
public String getNode() {
return null;
}
public DiscoInfoProvider getDiscoInfoProvider() {
return PubSubModule.this;
}
public DiscoItemsProvider getDiscoItemsProvider() {
return PubSubModule.this;
}
});
final DiscoServerItem item = new DiscoServerItem(new JID(
getServiceDomain()), "Publish-Subscribe service", null, null, this,
this);
items.add(item);
return items.iterator();
}
......@@ -636,18 +615,16 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
return false;
}
public Iterator<Element> getItems(String name, String node, JID senderJID) {
List<Element> answer = new ArrayList<Element>();
public Iterator<DiscoItem> getItems(String name, String node, JID senderJID) {
List<DiscoItem> answer = new ArrayList<DiscoItem>();
String serviceDomain = getServiceDomain();
if (name == null && node == null) {
Element item;
// Answer all first level nodes
for (Node pubNode : rootCollectionNode.getNodes()) {
if (canDiscoverNode(pubNode)) {
item = DocumentHelper.createElement("item");
item.addAttribute("jid", serviceDomain);
item.addAttribute("node", pubNode.getNodeID());
item.addAttribute("name", pubNode.getName());
final DiscoItem item = new DiscoItem(
new JID(serviceDomain), pubNode.getName(),
pubNode.getNodeID(), null);
answer.add(item);
}
}
......@@ -656,25 +633,21 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
Node pubNode = getNode(node);
if (pubNode != null && canDiscoverNode(pubNode)) {
if (pubNode.isCollectionNode()) {
Element item;
// Answer all nested nodes as items
for (Node nestedNode : pubNode.getNodes()) {
if (canDiscoverNode(nestedNode)) {
item = DocumentHelper.createElement("item");
item.addAttribute("jid", serviceDomain);
item.addAttribute("node", nestedNode.getNodeID());
item.addAttribute("name", nestedNode.getName());
final DiscoItem item = new DiscoItem(new JID(
serviceDomain), nestedNode.getName(),
nestedNode.getNodeID(), null);
answer.add(item);
}
}
}
else {
// This is a leaf node so answer the published items which exist on the service
Element item;
for (PublishedItem publishedItem : pubNode.getPublishedItems()) {
item = DocumentHelper.createElement("item");
item.addAttribute("jid", serviceDomain);
item.addAttribute("name", publishedItem.getID());
final DiscoItem item = new DiscoItem(new JID(
serviceDomain), publishedItem.getID(), null, null);
answer.add(item);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment