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;
}
}
......@@ -11,37 +11,26 @@
package org.jivesoftware.openfire.disco;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.dom4j.tree.DefaultElement;
import org.jivesoftware.openfire.IQHandlerInfo;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.cluster.ClusterEventListener;
import org.jivesoftware.openfire.cluster.ClusterManager;
import org.jivesoftware.openfire.cluster.NodeID;
import org.jivesoftware.openfire.handler.IQHandler;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.openfire.user.User;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.cache.Cache;
import org.jivesoftware.util.cache.CacheFactory;
import org.jivesoftware.util.cache.ExternalizableUtil;
import org.jivesoftware.util.lock.LockManager;
import org.jivesoftware.util.resultsetmanager.ResultSet;
import org.jivesoftware.util.resultsetmanager.ResultSetImpl;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;
import org.xmpp.packet.PacketError.Condition;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
/**
* IQDiscoItemsHandler is responsible for handling disco#items requests. This class holds a map with
......@@ -65,18 +54,19 @@ import java.util.concurrent.locks.Lock;
*
* @author Gaston Dombiak
*/
public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProvider, ClusterEventListener {
public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProvider {
public static final String NAMESPACE_DISCO_ITEMS = "http://jabber.org/protocol/disco#items";
private Map<String,DiscoItemsProvider> entities = new HashMap<String,DiscoItemsProvider>();
private Map<String, Element> localServerItems = new HashMap<String, Element>();
private Cache<String, ClusteredServerItem> serverItems;
private Map<String, DiscoItemsProvider> serverNodeProviders = new ConcurrentHashMap<String, DiscoItemsProvider>();
private List<DiscoItem> serverItems = new ArrayList<DiscoItem>();
private Map<String, DiscoItemsProvider> serverNodeProviders =
new ConcurrentHashMap<String, DiscoItemsProvider>();
private IQHandlerInfo info;
private IQDiscoInfoHandler infoHandler;
public IQDiscoItemsHandler() {
super("XMPP Disco Items Handler");
info = new IQHandlerInfo("query", "http://jabber.org/protocol/disco#items");
info = new IQHandlerInfo("query", NAMESPACE_DISCO_ITEMS);
}
public IQHandlerInfo getInfo() {
......@@ -113,19 +103,72 @@ public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProv
String node = iq.attributeValue("node");
// Check if we have items associated with the requested name and node
Iterator<Element> itemsItr = itemsProvider.getItems(name, node, packet.getFrom());
Iterator<DiscoItem> itemsItr = itemsProvider.getItems(name, node,
packet.getFrom());
if (itemsItr != null) {
reply.setChildElement(iq.createCopy());
Element queryElement = reply.getChildElement();
// Add to the reply all the items provided by the DiscoItemsProvider
// See if the requesting entity would like to apply 'result set
// management'
final Element rsmElement = packet.getChildElement().element(
QName.get("set",
ResultSet.NAMESPACE_RESULT_SET_MANAGEMENT));
// apply RSM only if the element exists, and the (total) results
// set is not empty.
final boolean applyRSM = rsmElement != null
&& itemsItr.hasNext();
if (applyRSM) {
if (!ResultSet.isValidRSMRequest(rsmElement))
{
reply.setError(Condition.bad_request);
return reply;
}
// Calculate which results to include.
final List<DiscoItem> rsmResults;
final List<DiscoItem> allItems = new ArrayList<DiscoItem>();
while (itemsItr.hasNext()) {
allItems.add(itemsItr.next());
}
final ResultSet<DiscoItem> rs = new ResultSetImpl<DiscoItem>(
allItems);
try {
rsmResults = rs.applyRSMDirectives(rsmElement);
} catch (NullPointerException e) {
final IQ itemNotFound = IQ.createResultIQ(packet);
itemNotFound.setError(Condition.item_not_found);
return itemNotFound;
}
// add the applicable results to the IQ-result
for (DiscoItem item : rsmResults) {
final Element resultElement = item.getElement();
resultElement.setQName(new QName(resultElement
.getName(), queryElement.getNamespace()));
queryElement.add(resultElement.createCopy());
}
// overwrite the 'set' element.
queryElement.remove(queryElement.element(
QName.get("set",
ResultSet.NAMESPACE_RESULT_SET_MANAGEMENT)));
queryElement.add(rs.generateSetElementFromResults(rsmResults));
} else {
// don't apply RSM:
// Add to the reply all the items provided by the
// DiscoItemsProvider
Element item;
while (itemsItr.hasNext()) {
item = itemsItr.next();
item.setQName(new QName(item.getName(), queryElement.getNamespace()));
item = itemsItr.next().getElement();
item.setQName(new QName(item.getName(), queryElement
.getNamespace()));
queryElement.add(item.createCopy());
}
}
}
else {
// If the DiscoItemsProvider has no items for the requested name and node
// then answer a not found error
......@@ -196,7 +239,7 @@ public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProv
addComponentItem(discoItem.getJID(), discoItem.getNode(), discoItem.getName());
// Add the new item as a valid entity that could receive info and items disco requests
String host = new JID(discoItem.getJID()).getDomain();
String host = discoItem.getJID().getDomain();
infoHandler.setProvider(host, discoItem.getDiscoInfoProvider());
setProvider(host, discoItem.getDiscoItemsProvider());
}
......@@ -220,7 +263,7 @@ public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProv
removeComponentItem(discoItem.getJID());
// Remove the item as a valid entity that could receive info and items disco requests
String host = new JID(discoItem.getJID()).getDomain();
String host = discoItem.getJID().getDomain();
infoHandler.removeProvider(host);
removeProvider(host);
}
......@@ -257,7 +300,7 @@ public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProv
* @param jid the jid of the component.
* @param name the discovered name of the component.
*/
public void addComponentItem(String jid, String name) {
public void addComponentItem(JID jid, String name) {
addComponentItem(jid, null, name);
}
......@@ -269,31 +312,15 @@ public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProv
* @param node the node that complements the jid address.
* @param name the discovered name of the component.
*/
public void addComponentItem(String jid, String node, String name) {
Lock lock = LockManager.getLock(jid + "item");
try {
lock.lock();
ClusteredServerItem item = serverItems.get(jid);
if (item == null) {
// First time a node registers a server item for this component
item = new ClusteredServerItem();
public synchronized void addComponentItem(JID jid, String node, String name) {
// A component may send his disco#info many times and we only want to have one item
// for the component so remove any element under the requested jid
removeComponentItem(jid);
Element element = DocumentHelper.createElement("item");
element.addAttribute("jid", jid);
element.addAttribute("node", node);
element.addAttribute("name", name);
item.element = element;
}
if (item.nodes.add(XMPPServer.getInstance().getNodeID())) {
// Update the cache with latest info
serverItems.put(jid, item);
}
// Keep track of the new server item added by this JVM
localServerItems.put(jid, item.element);
}
finally {
lock.unlock();
}
// Create a new element based on the provided DiscoItem
final DiscoItem item = new DiscoItem(jid, name, node, null);
// Add the element to the list of items related to the server
serverItems.add(item);
}
/**
......@@ -301,37 +328,20 @@ public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProv
*
* @param jid the jid of the component being removed.
*/
public void removeComponentItem(String jid) {
Lock lock = LockManager.getLock(jid + "item");
try {
lock.lock();
ClusteredServerItem item = serverItems.get(jid);
if (item != null && item.nodes.remove(XMPPServer.getInstance().getNodeID())) {
// Update the cache with latest info
if (item.nodes.isEmpty()) {
serverItems.remove(jid);
}
else {
serverItems.put(jid, item);
}
public synchronized void removeComponentItem(JID jid) {
for (Iterator<DiscoItem> it = serverItems.iterator(); it.hasNext();) {
if (jid.equals(it.next().getJID())) {
it.remove();
}
}
finally {
lock.unlock();
}
// Remove locally added server item
localServerItems.remove(jid);
}
public void initialize(XMPPServer server) {
super.initialize(server);
serverItems = CacheFactory.createCache("Disco Server Items");
// Track the implementors of ServerItemsProvider so that we can collect the items
// provided by the server
infoHandler = server.getIQDiscoInfoHandler();
setProvider(server.getServerInfo().getName(), getServerItemsProvider());
// Listen to cluster events
ClusterManager.addListener(this);
}
public void start() throws IllegalStateException {
......@@ -343,82 +353,15 @@ public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProv
public Iterator<String> getFeatures() {
List<String> features = new ArrayList<String>();
features.add("http://jabber.org/protocol/disco#items");
features.add(NAMESPACE_DISCO_ITEMS);
// TODO Comment out this line when publishing of client items is implemented
//features.add("http://jabber.org/protocol/disco#publish");
return features.iterator();
}
public void joinedCluster() {
restoreCacheContent();
}
public void joinedCluster(byte[] nodeID) {
// Do nothing
}
public void leftCluster() {
if (!XMPPServer.getInstance().isShuttingDown()) {
restoreCacheContent();
}
}
public void leftCluster(byte[] nodeID) {
if (ClusterManager.isSeniorClusterMember()) {
NodeID leftNode = NodeID.getInstance(nodeID);
for (Map.Entry<String, ClusteredServerItem> entry : serverItems.entrySet()) {
String jid = entry.getKey();
Lock lock = LockManager.getLock(jid + "item");
try {
lock.lock();
ClusteredServerItem item = entry.getValue();
if (item.nodes.remove(leftNode)) {
// Update the cache with latest info
if (item.nodes.isEmpty()) {
serverItems.remove(jid);
}
else {
serverItems.put(jid, item);
}
}
}
finally {
lock.unlock();
}
}
}
}
public void markedAsSeniorClusterMember() {
// Do nothing
}
private void restoreCacheContent() {
for (Map.Entry<String, Element> entry : localServerItems.entrySet()) {
String jid = entry.getKey();
Element element = entry.getValue();
Lock lock = LockManager.getLock(jid + "item");
try {
lock.lock();
ClusteredServerItem item = serverItems.get(jid);
if (item == null) {
// First time a node registers a server item for this component
item = new ClusteredServerItem();
item.element = element;
}
if (item.nodes.add(XMPPServer.getInstance().getNodeID())) {
// Update the cache with latest info
serverItems.put(jid, item);
}
}
finally {
lock.unlock();
}
}
}
private DiscoItemsProvider getServerItemsProvider() {
return new DiscoItemsProvider() {
public Iterator<Element> getItems(String name, String node, JID senderJID) {
public Iterator<DiscoItem> getItems(String name, String node, JID senderJID) {
if (node != null) {
// Check if there is a provider for the requested node
if (serverNodeProviders.get(node) != null) {
......@@ -427,14 +370,9 @@ public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProv
return null;
}
if (name == null) {
List<Element> answer = new ArrayList<Element>();
for (ClusteredServerItem item : serverItems.values()) {
answer.add(item.element);
}
return answer.iterator();
return serverItems.iterator();
}
else {
List<Element> answer = new ArrayList<Element>();
final List<DiscoItem> answer = new ArrayList<DiscoItem>();
try {
User user = UserManager.getInstance().getUser(name);
RosterItem item = user.getRoster().getRosterItem(senderJID);
......@@ -443,9 +381,7 @@ public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProv
if (item.getSubStatus() == RosterItem.SUB_FROM ||
item.getSubStatus() == RosterItem.SUB_BOTH) {
for (Session session : SessionManager.getInstance().getSessions(name)) {
Element element = DocumentHelper.createElement("item");
element.addAttribute("jid", session.getAddress().toString());
answer.add(element);
answer.add(new DiscoItem(session.getAddress(), null, null, null));
}
}
return answer.iterator();
......@@ -454,25 +390,6 @@ public class IQDiscoItemsHandler extends IQHandler implements ServerFeaturesProv
return answer.iterator();
}
}
}
};
}
private static class ClusteredServerItem implements Externalizable {
private Element element;
private Set<NodeID> nodes = new HashSet<NodeID>();
public ClusteredServerItem() {
}
public void writeExternal(ObjectOutput out) throws IOException {
ExternalizableUtil.getInstance().writeSerializable(out, (DefaultElement) element);
ExternalizableUtil.getInstance().writeExternalizableCollection(out, nodes);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
element = (Element) ExternalizableUtil.getInstance().readSerializable(in);
ExternalizableUtil.getInstance().readExternalizableCollection(in, nodes, getClass().getClassLoader());
}
}
}
......@@ -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