Commit b4497851 authored by Daniel Henninger's avatar Daniel Henninger Committed by dhenninger

Added support for MUC delegate interactions, additional features/identities...

Added support for MUC delegate interactions, additional features/identities for MUCs, and implementation of joiningRoom/destroyingRoom in CS's MUC delegate, and use of the new identity adding functionality.  Reviewer: Armando    Pending testing.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@10121 b35dd754-fafc-0310-a699-88a17e54d16e
parent db7e648a
package org.jivesoftware.openfire.clearspace; package org.jivesoftware.openfire.clearspace;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.component.InternalComponentManager;
import org.jivesoftware.openfire.muc.MUCEventDelegate; import org.jivesoftware.openfire.muc.MUCEventDelegate;
import org.xmpp.packet.IQ; import org.xmpp.packet.IQ;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import org.dom4j.Element;
import org.dom4j.DocumentHelper;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
* TODO: Comment me * Handles checking with Clearspace regarding whether a user can join a particular chatroom (based
* on their permissions with the document/whatever the chatroom is associated with), as well as setting
* up room configurations.
* *
* @author Armando Jagucki * @author Armando Jagucki
*/ */
public class ClearspaceMUCEventDelegate extends MUCEventDelegate { public class ClearspaceMUCEventDelegate extends MUCEventDelegate {
private String csMucDomain;
public ClearspaceMUCEventDelegate() {
csMucDomain = ClearspaceManager.MUC_SUBDOMAIN+"@"+XMPPServer.getInstance().getServerInfo().getXMPPDomain();
}
/** /**
* This event will be triggered when an entity joins an existing room. * This event will be triggered when an entity joins an existing room.
* <p/> * <p/>
...@@ -25,14 +35,39 @@ public class ClearspaceMUCEventDelegate extends MUCEventDelegate { ...@@ -25,14 +35,39 @@ public class ClearspaceMUCEventDelegate extends MUCEventDelegate {
* @return true if the user is allowed to join the room. * @return true if the user is allowed to join the room.
*/ */
public boolean joiningRoom(String roomName, JID userjid) { public boolean joiningRoom(String roomName, JID userjid) {
return false; // TODO: Implement // Packet should look like:
// <iq to="clearspace.example.org" from="clearspace-conference.example.org">
// <join-check xmlns="http://jivesoftware.com/clearspace">
// <userjid>username@example.org</userjid>
// <roomjid>DOC-1234@clearspace-conference.example.org</roomjid>
// </join-check>
// </iq>
IQ query = new IQ();
query.setFrom(csMucDomain);
Element cmd = DocumentHelper.createElement("join-check");
cmd.addElement("userjid").addText(userjid.toBareJID());
cmd.addElement("roomjid").addText(roomName+"@"+csMucDomain);
query.setChildElement(cmd);
IQ result = ClearspaceManager.getInstance().query(query, 15000);
if (result == null) {
// No answer was received, assume false for security reasons.
return false;
}
if (result.getType() != IQ.Type.error) {
// No error, that indicates that we were successful and the user is permitted.
return true;
}
// No successful return, not allowed.
return false;
} }
public Map<String, String> getRoomConfig(String roomName) { public Map<String, String> getRoomConfig(String roomName) {
Map<String, String> roomConfig = new HashMap<String, String>(); Map<String, String> roomConfig = new HashMap<String, String>();
// TODO: Get the config by connecting to CS through the component
InternalComponentManager internalComponentManager = InternalComponentManager.getInstance();
// TODO: Create query packet asking for the room config and in CS create a handler for that packet // TODO: Create query packet asking for the room config and in CS create a handler for that packet
IQ query = null; IQ query = null;
IQ result = ClearspaceManager.getInstance().query(query, 15000); IQ result = ClearspaceManager.getInstance().query(query, 15000);
...@@ -77,6 +112,7 @@ public class ClearspaceMUCEventDelegate extends MUCEventDelegate { ...@@ -77,6 +112,7 @@ public class ClearspaceMUCEventDelegate extends MUCEventDelegate {
* @return true if the user is allowed to destroy the room. * @return true if the user is allowed to destroy the room.
*/ */
public boolean destroyingRoom(String roomName, JID userjid) { public boolean destroyingRoom(String roomName, JID userjid) {
return false; // TODO: Implement // We never allow destroying a room as a user, so return false always.
return false;
} }
} }
...@@ -404,8 +404,8 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM ...@@ -404,8 +404,8 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM
muc.setMUCDelegate(new ClearspaceMUCEventDelegate()); muc.setMUCDelegate(new ClearspaceMUCEventDelegate());
// Set up additional features for Clearspace MUC service // Set up additional features for Clearspace MUC service
muc.addExtraFeature("clearspace:service"); muc.addExtraFeature("clearspace:service");
// Sets identity of conference service to Clearspace MUC service // Set up additional identity of conference service to Clearspace MUC service
muc.setDiscoIdentityType("clearspace"); muc.addExtraIdentity("conference", "Clearspace Chat Service", "text");
} }
// Starts the clearspace configuration task // Starts the clearspace configuration task
...@@ -432,7 +432,7 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM ...@@ -432,7 +432,7 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM
// Create and schedule a confi task every minute // Create and schedule a confi task every minute
configClearspaceTask = new ConfigClearspaceTask(); configClearspaceTask = new ConfigClearspaceTask();
// Wait some time to start the task until Openfire has binding address // Wait some time to start the task until Openfire has binding address
TaskEngine.getInstance().schedule(configClearspaceTask, JiveConstants.SECOND * 10, JiveConstants.MINUTE); TaskEngine.getInstance().schedule(configClearspaceTask, JiveConstants.SECOND * 10, JiveConstants.MINUTE);
Log.debug("Starting configuration Clearspace task in 10 seconds."); Log.debug("Starting configuration Clearspace task in 10 seconds.");
} }
...@@ -449,7 +449,7 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM ...@@ -449,7 +449,7 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM
} }
try { try {
XMPPServerInfo serverInfo = XMPPServer.getInstance().getServerInfo(); XMPPServerInfo serverInfo = XMPPServer.getInstance().getServerInfo();
String path = IM_URL_PREFIX + "configureComponent/"; String path = IM_URL_PREFIX + "configureComponent/";
...@@ -468,7 +468,7 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM ...@@ -468,7 +468,7 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM
Log.debug("Trying to configure Clearspace with: Domain: " + serverInfo.getXMPPDomain() + ", hosts: " + Log.debug("Trying to configure Clearspace with: Domain: " + serverInfo.getXMPPDomain() + ", hosts: " +
bindInterfaces.toString() + ", port: " + port); bindInterfaces.toString() + ", port: " + port);
executeRequest(POST, path, rootE.asXML()); executeRequest(POST, path, rootE.asXML());
//Done, Clearspace was configured correctly, clear the task //Done, Clearspace was configured correctly, clear the task
...@@ -529,7 +529,7 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM ...@@ -529,7 +529,7 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM
} else { } else {
bindInterfaces.add(bindInterface); bindInterfaces.add(bindInterface);
} }
return bindInterfaces; return bindInterfaces;
} }
...@@ -839,7 +839,7 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM ...@@ -839,7 +839,7 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM
* The returned packet will be handled by the server and routed to the entity that sent * The returned packet will be handled by the server and routed to the entity that sent
* the original IQ packet. Since this method block and listen to the replied IQ packet * the original IQ packet. Since this method block and listen to the replied IQ packet
* then the entity that sent the original IQ packet should ignore any reply related to * then the entity that sent the original IQ packet should ignore any reply related to
* the originating IQ packet. * the originating IQ packet.
* *
* @param packet IQ packet to send. * @param packet IQ packet to send.
* @param timeout milliseconds to wait before timing out. * @param timeout milliseconds to wait before timing out.
......
...@@ -91,6 +91,13 @@ public class IQOwnerHandler { ...@@ -91,6 +91,13 @@ public class IQOwnerHandler {
else { else {
Element destroyElement = element.element("destroy"); Element destroyElement = element.element("destroy");
if (destroyElement != null) { if (destroyElement != null) {
if (((MultiUserChatServiceImpl)room.getMUCService()).getMUCDelegate() != null) {
if (!((MultiUserChatServiceImpl)room.getMUCService()).getMUCDelegate().destroyingRoom(room.getName(), role.getUserAddress())) {
// Delegate said no, reject destroy request.
throw new ForbiddenException();
}
}
room.destroyRoom(destroyElement.attributeValue("jid"), destroyElement room.destroyRoom(destroyElement.attributeValue("jid"), destroyElement
.elementTextTrim("reason")); .elementTextTrim("reason"));
} }
......
...@@ -453,6 +453,12 @@ public class LocalMUCRoom implements MUCRoom { ...@@ -453,6 +453,12 @@ public class LocalMUCRoom implements MUCRoom {
UserAlreadyExistsException, RoomLockedException, ForbiddenException, UserAlreadyExistsException, RoomLockedException, ForbiddenException,
RegistrationRequiredException, ConflictException, ServiceUnavailableException, RegistrationRequiredException, ConflictException, ServiceUnavailableException,
NotAcceptableException { NotAcceptableException {
if (((MultiUserChatServiceImpl)mucService).getMUCDelegate() != null) {
if (!((MultiUserChatServiceImpl)mucService).getMUCDelegate().joiningRoom(this.getName(), user.getAddress())) {
// Delegate said no, reject join.
throw new UnauthorizedException();
}
}
LocalMUCRole joinRole = null; LocalMUCRole joinRole = null;
lock.writeLock().lock(); lock.writeLock().lock();
try { try {
......
...@@ -214,9 +214,9 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService ...@@ -214,9 +214,9 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService
private List<String> extraDiscoFeatures = new ArrayList<String>(); private List<String> extraDiscoFeatures = new ArrayList<String>();
/** /**
* Custom setting for "type" of conference service. * Additional identities to be added to the disco response for the service.
*/ */
private String discoIdentityType = "text"; private List<Element> extraDiscoIdentities = new ArrayList<Element>();
/** /**
* Create a new group chat server. * Create a new group chat server.
...@@ -1103,8 +1103,7 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService ...@@ -1103,8 +1103,7 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService
Element identity = DocumentHelper.createElement("identity"); Element identity = DocumentHelper.createElement("identity");
identity.addAttribute("category", "conference"); identity.addAttribute("category", "conference");
identity.addAttribute("name", getDescription()); identity.addAttribute("name", getDescription());
identity.addAttribute("type", discoIdentityType); identity.addAttribute("type", "text");
identities.add(identity); identities.add(identity);
// TODO: Should internationalize Public Chatroom Search, and make it configurable. // TODO: Should internationalize Public Chatroom Search, and make it configurable.
...@@ -1113,6 +1112,10 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService ...@@ -1113,6 +1112,10 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService
searchId.addAttribute("name", "Public Chatroom Search"); searchId.addAttribute("name", "Public Chatroom Search");
searchId.addAttribute("type", "chatroom"); searchId.addAttribute("type", "chatroom");
identities.add(searchId); identities.add(searchId);
if (!extraDiscoIdentities.isEmpty()) {
identities.addAll(extraDiscoIdentities);
}
} }
else if (name != null && node == null) { else if (name != null && node == null) {
// Answer the identity of a given room // Answer the identity of a given room
...@@ -1257,11 +1260,30 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService ...@@ -1257,11 +1260,30 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService
} }
/** /**
* Sets the type of the conference service, typically "text". * Adds an extra Disco identity to the list of identities returned for the conference service.
* @param type The type of the conference service, "text" is the default. * @param category Category for identity. e.g. conference
* @param name Descriptive name for identity. e.g. Public Chatrooms
* @param type Type for identity. e.g. text
*/ */
public void setDiscoIdentityType(String type) { public void addExtraIdentity(String category, String name, String type) {
discoIdentityType = type; Element identity = DocumentHelper.createElement("identity");
identity.addAttribute("category", category);
identity.addAttribute("name", name);
identity.addAttribute("type", type);
extraDiscoIdentities.add(identity);
}
/**
* Removes an extra Disco identity from the list of identities returned for the conference service.
* @param name Name of identity to remove.
*/
public void removeExtraIdentity(String name) {
for (Element elem : extraDiscoIdentities) {
if (name.equals(elem.attribute("name").getStringValue())) {
extraDiscoFeatures.remove(elem);
break;
}
}
} }
/** /**
...@@ -1272,6 +1294,14 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService ...@@ -1272,6 +1294,14 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService
mucEventDelegate = delegate; mucEventDelegate = delegate;
} }
/**
* Gets the MUC event delegate handler for this service.
* @return Handler for MUC events (delegate)
*/
public MUCEventDelegate getMUCDelegate() {
return mucEventDelegate;
}
public boolean hasInfo(String name, String node, JID senderJID) { public boolean hasInfo(String name, String node, JID senderJID) {
// Check if the service is disabled. Info is not available when disabled. // Check if the service is disabled. Info is not available when disabled.
if (!isServiceEnabled()) { if (!isServiceEnabled()) {
......
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