Commit 069be623 authored by Matt Tucker's avatar Matt Tucker Committed by matt

Refactoring.


git-svn-id: http://svn.igniterealtime.org/svn/repos/messenger/trunk@919 b35dd754-fafc-0310-a699-88a17e54d16e
parent ae341f28
......@@ -12,17 +12,41 @@
package org.jivesoftware.messenger;
import org.xmpp.packet.IQ;
import org.xmpp.packet.PacketError;
import org.xmpp.packet.JID;
import org.jivesoftware.messenger.container.BasicModule;
import org.jivesoftware.messenger.handler.IQHandler;
import org.jivesoftware.messenger.auth.UnauthorizedException;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.dom4j.Element;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* <p>Route iq packets throughout the server.</p>
* <p>Routing is based on the recipient and sender addresses. The typical
* packet will often be routed twice, once from the sender to some internal
* server component for handling or processing, and then back to the router
* to be delivered to it's final destination.</p>
* Routes iq packets throughout the server. Routing is based on the recipient
* and sender addresses. The typical packet will often be routed twice, once
* from the sender to some internal server component for handling or processing,
* and then back to the router to be delivered to it's final destination.
*
* @author Iain Shigeoka
*/
public interface IQRouter {
public class IQRouter extends BasicModule {
private RoutingTable routingTable;
private List<IQHandler> iqHandlers = new ArrayList<IQHandler>();
private Map<String, IQHandler> namespace2Handlers = new ConcurrentHashMap<String, IQHandler>();
private SessionManager sessionManager;
/**
* Creates a packet router.
*/
public IQRouter() {
super("XMPP IQ Router");
}
/**
* <p>Performs the actual packet routing.</p>
......@@ -37,5 +61,187 @@ public interface IQRouter {
* @param packet The packet to route
* @throws NullPointerException If the packet is null
*/
public void route(IQ packet);
public void route(IQ packet) {
if (packet == null) {
throw new NullPointerException();
}
Session session = sessionManager.getSession(packet.getFrom());
if (session == null || session.getStatus() == Session.STATUS_AUTHENTICATED
|| (isLocalServer(packet.getTo())
&& ("jabber:iq:auth".equals(packet.getChildElement().getNamespaceURI())
|| "jabber:iq:register".equals(packet.getChildElement().getNamespaceURI())))
) {
handle(packet);
}
else {
packet.setTo(sessionManager.getSession(packet.getFrom()).getAddress());
packet.setError(PacketError.Condition.not_authorized);
try {
sessionManager.getSession(packet.getFrom()).process(packet);
}
catch (UnauthorizedException ue) {
Log.error(ue);
}
}
}
/**
* <p>Adds a new IQHandler to the list of registered handler. The new IQHandler will be
* responsible for handling IQ packet whose namespace matches the namespace of the
* IQHandler.</p>
*
* An IllegalArgumentException may be thrown if the IQHandler to register was already provided
* by the server. The server provides a certain list of IQHandlers when the server is
* started up.
*
* @param handler the IQHandler to add to the list of registered handler.
*/
public void addHandler(IQHandler handler) {
if (iqHandlers.contains(handler)) {
throw new IllegalArgumentException("IQHandler already provided by the server");
}
// Register the handler as the handler of the namespace
namespace2Handlers.put(handler.getInfo().getNamespace(), handler);
}
/**
* <p>Removes an IQHandler from the list of registered handler. The IQHandler to remove was
* responsible for handling IQ packet whose namespace matches the namespace of the
* IQHandler.</p>
*
* An IllegalArgumentException may be thrown if the IQHandler to remove was already provided
* by the server. The server provides a certain list of IQHandlers when the server is
* started up.
*
* @param handler the IQHandler to remove from the list of registered handler.
*/
public void removeHandler(IQHandler handler) {
if (iqHandlers.contains(handler)) {
throw new IllegalArgumentException("Cannot remove an IQHandler provided by the server");
}
// Unregister the handler as the handler of the namespace
namespace2Handlers.remove(handler.getInfo().getNamespace());
}
public void initialize(XMPPServer server) {
super.initialize(server);
routingTable = server.getRoutingTable();
iqHandlers.addAll(server.getIQHandlers());
sessionManager = server.getSessionManager();
}
private boolean isLocalServer(JID recipientJID) {
return recipientJID == null || recipientJID.getDomain() == null
|| "".equals(recipientJID.getDomain()) || recipientJID.getResource() == null
|| "".equals(recipientJID.getResource());
}
private void handle(IQ packet) {
JID recipientJID = packet.getTo();
try {
if (isLocalServer(recipientJID)) {
Element childElement = packet.getChildElement();
String namespace = null;
if (childElement != null) {
namespace = childElement.getNamespaceURI();
}
if (namespace == null) {
// Do nothing. We can't handle queries outside of a valid namespace
Log.warn("Unknown packet " + packet);
}
else {
IQHandler handler = getHandler(namespace);
if (handler == null) {
IQ reply = IQ.createResultIQ(packet);
if (recipientJID == null) {
// Answer an error since the server can't handle the requested namespace
reply.setError(PacketError.Condition.service_unavailable);
}
else if (recipientJID.getNode() == null || "".equals(recipientJID.getNode())) {
// Answer an error if JID is of the form <domain>
reply.setError(PacketError.Condition.feature_not_implemented);
}
else {
// JID is of the form <node@domain>
try {
// Let a "service" handle this packet otherwise return an error
// Useful for MUC where node refers to a room and domain is the
// MUC service.
ChannelHandler route = routingTable.getRoute(recipientJID);
if (route instanceof BasicModule) {
route.process(packet);
return;
}
}
catch (NoSuchRouteException e) {
// do nothing
}
// Answer an error since the server can't handle packets sent to a node
reply.setError(PacketError.Condition.service_unavailable);
}
Session session = sessionManager.getSession(packet.getFrom());
if (session != null) {
session.getConnection().deliver(reply);
}
else {
Log.warn("Packet could not be delivered " + packet);
}
}
else {
handler.process(packet);
}
}
}
else {
// JID is of the form <node@domain/resource>
ChannelHandler route = routingTable.getRoute(recipientJID);
route.process(packet);
}
}
catch (NoSuchRouteException e) {
Log.info("Packet sent to unreachable address " + packet);
Session session = sessionManager.getSession(packet.getFrom());
if (session != null) {
try {
packet.setError(PacketError.Condition.service_unavailable);
session.getConnection().deliver(packet);
}
catch (UnauthorizedException ex) {
Log.error(LocaleUtils.getLocalizedString("admin.error.routing"), e);
}
}
}
catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error.routing"), e);
try {
Session session = sessionManager.getSession(packet.getFrom());
if (session != null) {
Connection conn = session.getConnection();
if (conn != null) {
conn.close();
}
}
}
catch (UnauthorizedException e1) {
// do nothing
}
}
}
private IQHandler getHandler(String namespace) {
IQHandler handler = namespace2Handlers.get(namespace);
if (handler == null) {
for (IQHandler handlerCandidate : iqHandlers) {
IQHandlerInfo handlerInfo = handlerCandidate.getInfo();
if (handlerInfo != null && namespace.equalsIgnoreCase(handlerInfo.getNamespace())) {
handler = handlerCandidate;
namespace2Handlers.put(namespace, handler);
break;
}
}
}
return handler;
}
}
......@@ -20,7 +20,7 @@ import org.xmpp.packet.Packet;
*
* @author Iain Shigeoka
*/
public interface PacketRouter extends IQRouter, MessageRouter, PresenceRouter {
public interface PacketRouter extends MessageRouter, PresenceRouter {
/**
* <p>Routes the given packet based on packet recipient and sender.</p>
......
......@@ -168,7 +168,7 @@ public class XMPPServer {
name = "127.0.0.1";
}
version = new Version(2, 1, 1, Version.ReleaseStatus.Beta, -1);
version = new Version(2, 1, 1, Version.ReleaseStatus.Release, -1);
if ("true".equals(JiveGlobals.getXMLProperty("setup"))) {
setupMode = false;
}
......@@ -234,7 +234,7 @@ public class XMPPServer {
loadModule(PresenceManagerImpl.class.getName());
loadModule(SessionManager.class.getName());
loadModule(PacketRouterImpl.class.getName());
loadModule(IQRouterImpl.class.getName());
loadModule(IQRouter.class.getName());
loadModule(MessageRouterImpl.class.getName());
loadModule(PresenceRouterImpl.class.getName());
loadModule(PacketTransporterImpl.class.getName());
......@@ -762,7 +762,7 @@ public class XMPPServer {
* @return the <code>IQRouter</code> registered with this server.
*/
public IQRouter getIQRouter() {
return (IQRouter) modules.get(IQRouterImpl.class);
return (IQRouter) modules.get(IQRouter.class);
}
/**
......
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.muc;
import org.xmpp.packet.Message;
import org.xmpp.packet.Presence;
import org.xmpp.packet.IQ;
/**
* Interface for any object that can accept chat messages and presence
* for delivery.
*
* @author Gaston Dombiak
*/
public interface ChatDeliverer {
/**
* Sends a packet to the user.
*
* @param packet The packet to send
*/
void send(Message packet);
/**
* Sends a packet to the user.
*
* @param packet The packet to send
*/
void send(Presence packet);
/**
* Sends a packet to the user.
*
* @param packet The packet to send
*/
void send(IQ packet);
}
......@@ -13,6 +13,7 @@ package org.jivesoftware.messenger.muc;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
import org.xmpp.packet.Packet;
import org.dom4j.Element;
/**
......@@ -24,56 +25,129 @@ import org.dom4j.Element;
*
* @author Gaston Dombiak
*/
public interface MUCRole extends ChatDeliverer {
/**
* Runs moderated discussions. Is allowed to kick users, grant and revoke voice, etc.
*/
int MODERATOR = 0;
/**
* A normal occupant of the room. An occupant who does not have administrative privileges; in
* a moderated room, a participant is further defined as having voice
*/
int PARTICIPANT = 1;
/**
* An occupant who does not have voice (can't speak in the room)
*/
int VISITOR = 2;
/**
* An occupant who does not permission to stay in the room (was banned)
*/
int NONE_ROLE = 3;
/**
* Owner of the room
*/
int OWNER = 10;
/**
* Administrator of the room
*/
int ADMINISTRATOR = 20;
/**
* A user who is on the "whitelist" for a members-only room or who is registered with an
* open room.
*/
int MEMBER = 30;
/**
* A user who has been banned from a room.
*/
int OUTCAST = 40;
/**
* A user who doesn't have an affiliation. This kind of users can register with members-only
* rooms and may enter an open room.
*/
int NONE = 50;
public interface MUCRole {
public enum Role {
/**
* Runs moderated discussions. Is allowed to kick users, grant and revoke voice, etc.
*/
moderator(0),
/**
* A normal occupant of the room. An occupant who does not have administrative privileges; in
* a moderated room, a participant is further defined as having voice
*/
participant(1),
/**
* An occupant who does not have voice (can't speak in the room)
*/
visitor(2),
/**
* An occupant who does not permission to stay in the room (was banned)
*/
none(3);
private int value;
Role(int value) {
this.value = value;
}
/**
* Returns the value for the role.
*
* @return the value.
*/
public int getValue() {
return value;
}
/**
* Returns the affiliation associated with the specified value.
*
* @param value the value.
* @return the associated affiliation.
*/
public static Role valueOf(int value) {
switch (value) {
case 0: return moderator;
case 1: return participant;
case 2: return visitor;
default: return none;
}
}
}
public enum Affiliation {
/**
* Owner of the room.
*/
owner(10),
/**
* Administrator of the room.
*/
admin(20),
/**
* A user who is on the "whitelist" for a members-only room or who is registered
* with an open room.
*/
member(30),
/**
* A user who has been banned from a room.
*/
outcast(40),
/**
* A user who doesn't have an affiliation. This kind of users can register with members-only
* rooms and may enter an open room.
*/
none(50);
private int value;
Affiliation(int value) {
this.value = value;
}
/**
* Returns the value for the role.
*
* @return the value.
*/
public int getValue() {
return value;
}
/**
* Returns the affiliation associated with the specified value.
*
* @param value the value.
* @return the associated affiliation.
*/
public static Affiliation valueOf(int value) {
switch (value) {
case 10: return owner;
case 20: return admin;
case 30: return member;
case 40: return outcast;
default: return none;
}
}
}
/**
* Obtain the current presence status of a user in a chatroom.
*
* @return The presence of the user in the room.
*/
Presence getPresence();
public Presence getPresence();
/**
* Returns the extended presence information that includes information about roles,
......@@ -82,14 +156,14 @@ public interface MUCRole extends ChatDeliverer {
* @return the extended presence information that includes information about roles,
* affiliations.
*/
Element getExtendedPresenceInformation();
public Element getExtendedPresenceInformation();
/**
* Set the current presence status of a user in a chatroom.
*
* @param presence The presence of the user in the room.
*/
void setPresence(Presence presence);
public void setPresence(Presence presence);
/**
* Call this method to promote or demote a user's role in a chatroom.
......@@ -103,78 +177,69 @@ public interface MUCRole extends ChatDeliverer {
* @throws NotAllowedException Thrown if trying to change the moderator role to an owner or
* administrator.
*/
void setRole(int newRole) throws NotAllowedException;
public void setRole(Role newRole) throws NotAllowedException;
/**
* Obtain the role state of the user.
*
* @return The role status of this user.
*/
int getRole();
/**
* Obtain the role state of the user as a String. This string representation will be
* incorporated into the extended packet information.
*
* @return The role status of this user.
*/
public String getRoleAsString();
public Role getRole();
/**
* Call this method to promote or demote a user's affiliation in a chatroom.
*
* @param newAffiliation The new affiliation that the user will play.
* @throws NotAllowedException Thrown if trying to ban an owner or an administrator.
* @param newAffiliation the new affiliation that the user will play.
* @throws NotAllowedException thrown if trying to ban an owner or an administrator.
*/
public void setAffiliation(int newAffiliation) throws NotAllowedException;
public void setAffiliation(Affiliation newAffiliation) throws NotAllowedException;
/**
* Obtain the affiliation state of the user.
*
* @return The affiliation status of this user.
*/
public int getAffiliation();
/**
* Obtain the affiliation state of the user as a String. This string representation will be
* incorporated into the extended packet information.
*
* @return The affiliation status of this user.
*/
public String getAffiliationAsString();
public Affiliation getAffiliation();
/**
* Obtain the nickname for the user in the chatroom.
*
* @return The user's nickname in the room or null if invisible.
*/
String getNickname();
public String getNickname();
/**
* Changes the nickname of the occupant within the room to the new nickname.
*
* @param nickname the new nickname of the occupant in the room.
*/
void changeNickname(String nickname);
public void changeNickname(String nickname);
/**
* Obtain the chat user that plays this role.
*
* @return The chatuser playing this role.
*/
MUCUser getChatUser();
public MUCUser getChatUser();
/**
* Obtain the chat room that hosts this user's role.
*
* @return The chatroom hosting this role.
*/
MUCRoom getChatRoom();
public MUCRoom getChatRoom();
/**
* Obtain the XMPPAddress representing this role in a room: room@server/nickname
*
* @return The Jabber ID that represents this role in the room.
*/
JID getRoleAddress();
}
public JID getRoleAddress();
/**
* Sends a packet to the user.
*
* @param packet The packet to send
*/
public void send(Packet packet);
}
\ No newline at end of file
......@@ -25,6 +25,7 @@ import org.jivesoftware.messenger.user.UserNotFoundException;
import org.xmpp.packet.Presence;
import org.xmpp.packet.Message;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
/**
......@@ -33,7 +34,7 @@ import org.xmpp.packet.JID;
*
* @author Gaston Dombiak
*/
public interface MUCRoom extends ChatDeliverer {
public interface MUCRoom {
/**
* Get the name of this room.
......@@ -182,7 +183,7 @@ public interface MUCRoom extends ChatDeliverer {
* @param bareJID The bare jid of the user of which you'd like to obtain his affiliation.
* @return the affiliation state of the user in the room.
*/
int getAffiliation(String bareJID);
MUCRole.Affiliation getAffiliation(String bareJID);
/**
* Joins the room using the given nickname.
......@@ -844,4 +845,11 @@ public interface MUCRoom extends ChatDeliverer {
* @param from the JID of the invitee that is rejecting the invitation.
*/
public void sendInvitationRejection(JID to, String reason, JID from);
/**
* Sends a packet to the user.
*
* @param packet The packet to send
*/
public void send(Packet packet);
}
\ No newline at end of file
......@@ -125,8 +125,8 @@ public class IQAdminHandler {
Element metaData;
if ("outcast".equals(affiliation)) {
// The client is requesting the list of outcasts
if (MUCRole.ADMINISTRATOR != senderRole.getAffiliation()
&& MUCRole.OWNER != senderRole.getAffiliation()) {
if (MUCRole.Affiliation.admin != senderRole.getAffiliation()
&& MUCRole.Affiliation.owner != senderRole.getAffiliation()) {
throw new ForbiddenException();
}
for (String jid : room.getOutcasts()) {
......@@ -140,8 +140,8 @@ public class IQAdminHandler {
// The client is requesting the list of members
// In a members-only room members can get the list of members
if (!room.isMembersOnly()
&& MUCRole.ADMINISTRATOR != senderRole.getAffiliation()
&& MUCRole.OWNER != senderRole.getAffiliation()) {
&& MUCRole.Affiliation.admin != senderRole.getAffiliation()
&& MUCRole.Affiliation.owner != senderRole.getAffiliation()) {
throw new ForbiddenException();
}
for (String jid : room.getMembers()) {
......@@ -151,7 +151,7 @@ public class IQAdminHandler {
try {
List<MUCRole> roles = room.getOccupantsByBareJID(jid);
MUCRole role = roles.get(0);
metaData.addAttribute("role", role.getRoleAsString());
metaData.addAttribute("role", role.getRole().toString());
metaData.addAttribute("nick", role.getNickname());
}
catch (UserNotFoundException e) {
......@@ -161,8 +161,8 @@ public class IQAdminHandler {
}
else if ("moderator".equals(roleAttribute)) {
// The client is requesting the list of moderators
if (MUCRole.ADMINISTRATOR != senderRole.getAffiliation()
&& MUCRole.OWNER != senderRole.getAffiliation()) {
if (MUCRole.Affiliation.admin != senderRole.getAffiliation()
&& MUCRole.Affiliation.owner != senderRole.getAffiliation()) {
throw new ForbiddenException();
}
for (MUCRole role : room.getModerators()) {
......@@ -170,12 +170,12 @@ public class IQAdminHandler {
metaData.addAttribute("role", "moderator");
metaData.addAttribute("jid", role.getChatUser().getAddress().toString());
metaData.addAttribute("nick", role.getNickname());
metaData.addAttribute("affiliation", role.getAffiliationAsString());
metaData.addAttribute("affiliation", role.getAffiliation().toString());
}
}
else if ("participant".equals(roleAttribute)) {
// The client is requesting the list of participants
if (MUCRole.MODERATOR != senderRole.getRole()) {
if (MUCRole.Role.moderator != senderRole.getRole()) {
throw new ForbiddenException();
}
for (MUCRole role : room.getParticipants()) {
......@@ -183,7 +183,7 @@ public class IQAdminHandler {
metaData.addAttribute("role", "participant");
metaData.addAttribute("jid", role.getChatUser().getAddress().toString());
metaData.addAttribute("nick", role.getNickname());
metaData.addAttribute("affiliation", role.getAffiliationAsString());
metaData.addAttribute("affiliation", role.getAffiliation().toString());
}
}
else {
......@@ -238,7 +238,7 @@ public class IQAdminHandler {
}
else if ("member".equals(target)) {
// Add the user as a member of the room based on the bare JID
boolean hadAffiliation = room.getAffiliation(jid.toBareJID()) != MUCRole.NONE;
boolean hadAffiliation = room.getAffiliation(jid.toBareJID()) != MUCRole.Affiliation.none;
presences.addAll(room.addMember(jid.toBareJID(), nick, senderRole));
// If the user had an affiliation don't send an invitation. Otherwise
// send an invitation if the room is members-only
......@@ -257,7 +257,7 @@ public class IQAdminHandler {
}
else {
// Kick the user from the room
if (MUCRole.MODERATOR != senderRole.getRole()) {
if (MUCRole.Role.moderator != senderRole.getRole()) {
throw new ForbiddenException();
}
presences.add(room.kickOccupant(jid,
......
......@@ -74,7 +74,7 @@ public class IQOwnerHandler {
*/
public void handleIQ(IQ packet, MUCRole role) throws ForbiddenException, ConflictException {
// Only owners can send packets with the namespace "http://jabber.org/protocol/muc#owner"
if (MUCRole.OWNER != role.getAffiliation()) {
if (MUCRole.Affiliation.owner != role.getAffiliation()) {
throw new ForbiddenException();
}
......@@ -159,7 +159,7 @@ public class IQOwnerHandler {
try {
List<MUCRole> roles = room.getOccupantsByBareJID(jid);
role = roles.get(0);
ownerMetaData.addAttribute("role", role.getRoleAsString());
ownerMetaData.addAttribute("role", role.getRole().toString());
ownerMetaData.addAttribute("nick", role.getNickname());
}
catch (UserNotFoundException e) {
......@@ -179,7 +179,7 @@ public class IQOwnerHandler {
try {
List<MUCRole> roles = room.getOccupantsByBareJID(jid);
role = roles.get(0);
adminMetaData.addAttribute("role", role.getRoleAsString());
adminMetaData.addAttribute("role", role.getRole().toString());
adminMetaData.addAttribute("nick", role.getNickname());
}
catch (UserNotFoundException e) {
......@@ -247,7 +247,7 @@ public class IQOwnerHandler {
}
else if ("member".equals(targetAffiliation)) {
// Add the new user as a member of the room
boolean hadAffiliation = room.getAffiliation(bareJID) != MUCRole.NONE;
boolean hadAffiliation = room.getAffiliation(bareJID) != MUCRole.Affiliation.none;
presences.addAll(room.addMember(bareJID, null, senderRole));
// If the user had an affiliation don't send an invitation. Otherwise
// send an invitation if the room is members-only
......
......@@ -223,16 +223,16 @@ public class MUCPersistenceManager {
rs = pstmt.executeQuery();
while (rs.next()) {
String jid = rs.getString(1);
int affiliation = rs.getInt(2);
MUCRole.Affiliation affiliation = MUCRole.Affiliation.valueOf(rs.getInt(2));
try {
switch (affiliation) {
case MUCRole.OWNER:
case owner:
room.addOwner(jid, room.getRole());
break;
case MUCRole.ADMINISTRATOR:
case admin:
room.addAdmin(jid, room.getRole());
break;
case MUCRole.OUTCAST:
case outcast:
room.addOutcast(jid, null, room.getRole());
break;
default:
......@@ -498,7 +498,7 @@ public class MUCPersistenceManager {
rs = pstmt.executeQuery();
while (rs.next()) {
String jid = rs.getString(2);
int affiliation = rs.getInt(3);
MUCRole.Affiliation affiliation = MUCRole.Affiliation.valueOf(rs.getInt(3));
room = (MUCRoomImpl) rooms.get(rs.getLong(1));
// Skip to the next position if the room does not exist
if (room == null) {
......@@ -506,13 +506,13 @@ public class MUCPersistenceManager {
}
try {
switch (affiliation) {
case MUCRole.OWNER:
case owner:
room.addOwner(jid, room.getRole());
break;
case MUCRole.ADMINISTRATOR:
case admin:
room.addAdmin(jid, room.getRole());
break;
case MUCRole.OUTCAST:
case outcast:
room.addOutcast(jid, null, room.getRole());
break;
default:
......@@ -676,13 +676,13 @@ public class MUCPersistenceManager {
* @param oldAffiliation the previous affiliation of the user in the room.
*/
public static void saveAffiliationToDB(MUCRoom room, String bareJID, String nickname,
int newAffiliation, int oldAffiliation)
MUCRole.Affiliation newAffiliation, MUCRole.Affiliation oldAffiliation)
{
if (!room.isPersistent() || !room.wasSavedToDB()) {
return;
}
if (MUCRole.NONE == oldAffiliation) {
if (MUCRole.MEMBER == newAffiliation) {
if (MUCRole.Affiliation.none == oldAffiliation) {
if (MUCRole.Affiliation.member == newAffiliation) {
// Add the user to the members table
Connection con = null;
PreparedStatement pstmt = null;
......@@ -713,7 +713,7 @@ public class MUCPersistenceManager {
pstmt = con.prepareStatement(ADD_AFFILIATION);
pstmt.setLong(1, room.getID());
pstmt.setString(2, bareJID);
pstmt.setInt(3, newAffiliation);
pstmt.setInt(3, newAffiliation.getValue());
pstmt.executeUpdate();
}
catch (SQLException sqle) {
......@@ -728,7 +728,9 @@ public class MUCPersistenceManager {
}
}
else {
if (MUCRole.MEMBER == newAffiliation && MUCRole.MEMBER == oldAffiliation) {
if (MUCRole.Affiliation.member == newAffiliation &&
MUCRole.Affiliation.member == oldAffiliation)
{
// Update the member's data in the member table.
Connection con = null;
PreparedStatement pstmt = null;
......@@ -750,7 +752,7 @@ public class MUCPersistenceManager {
catch (Exception e) { Log.error(e); }
}
}
else if (MUCRole.MEMBER == newAffiliation) {
else if (MUCRole.Affiliation.member == newAffiliation) {
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
......@@ -780,7 +782,7 @@ public class MUCPersistenceManager {
DbConnectionManager.closeTransactionConnection(con, abortTransaction);
}
}
else if (MUCRole.MEMBER == oldAffiliation) {
else if (MUCRole.Affiliation.member == oldAffiliation) {
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
......@@ -795,7 +797,7 @@ public class MUCPersistenceManager {
pstmt = con.prepareStatement(ADD_AFFILIATION);
pstmt.setLong(1, room.getID());
pstmt.setString(2, bareJID);
pstmt.setInt(3, newAffiliation);
pstmt.setInt(3, newAffiliation.getValue());
pstmt.executeUpdate();
}
catch (SQLException sqle) {
......@@ -815,7 +817,7 @@ public class MUCPersistenceManager {
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(UPDATE_AFFILIATION);
pstmt.setInt(1, newAffiliation);
pstmt.setInt(1, newAffiliation.getValue());
pstmt.setLong(2, room.getID());
pstmt.setString(3, bareJID);
pstmt.executeUpdate();
......@@ -840,9 +842,11 @@ public class MUCPersistenceManager {
* @param bareJID The bareJID of the user to remove his affiliation.
* @param oldAffiliation the previous affiliation of the user in the room.
*/
public static void removeAffiliationFromDB(MUCRoom room, String bareJID, int oldAffiliation) {
public static void removeAffiliationFromDB(MUCRoom room, String bareJID,
MUCRole.Affiliation oldAffiliation)
{
if (room.isPersistent() && room.wasSavedToDB()) {
if (MUCRole.MEMBER == oldAffiliation) {
if (MUCRole.Affiliation.member == oldAffiliation) {
// Remove the user from the members table
Connection con = null;
PreparedStatement pstmt = null;
......
......@@ -21,17 +21,13 @@ import org.jivesoftware.messenger.muc.MUCUser;
import org.jivesoftware.messenger.muc.MultiUserChatServer;
import org.jivesoftware.messenger.muc.NotAllowedException;
import org.jivesoftware.util.ElementUtil;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Presence;
import org.xmpp.packet.*;
/**
* Simple in-memory implementation of a role in a chatroom
*
* @author Gaston Dombiak
*/
// TODO Review name of this class that represents role and affiliation at the same time.!!!!
public class MUCRoleImpl implements MUCRole {
/**
......@@ -60,14 +56,14 @@ public class MUCRoleImpl implements MUCRole {
private MultiUserChatServer server;
/**
* The role ID.
* The role.
*/
private int role;
private MUCRole.Role role;
/**
* The affiliation ID.
* The affiliation.
*/
private int affiliation;
private MUCRole.Affiliation affiliation;
/**
* The router used to send packets from this role.
......@@ -97,7 +93,7 @@ public class MUCRoleImpl implements MUCRole {
* @param packetRouter the packet router for sending messages from this role.
*/
public MUCRoleImpl(MultiUserChatServer chatserver, MUCRoomImpl chatroom, String nickname,
int role, int affiliation, MUCUserImpl chatuser, Presence presence,
MUCRole.Role role, MUCRole.Affiliation affiliation, MUCUserImpl chatuser, Presence presence,
PacketRouter packetRouter)
{
this.room = chatroom;
......@@ -137,49 +133,36 @@ public class MUCRoleImpl implements MUCRole {
}
}
public void setRole(int newRole) throws NotAllowedException {
public void setRole(MUCRole.Role newRole) throws NotAllowedException {
// Don't allow to change the role to an owner or admin unless the new role is moderator
if (MUCRole.OWNER == affiliation || MUCRole.ADMINISTRATOR == affiliation) {
if (MUCRole.MODERATOR != newRole) {
if (MUCRole.Affiliation.owner == affiliation || MUCRole.Affiliation.admin == affiliation) {
if (MUCRole.Role.moderator != newRole) {
throw new NotAllowedException();
}
}
// A moderator cannot be kicked from a room
if (MUCRole.MODERATOR == role && MUCRole.NONE_ROLE == newRole) {
if (MUCRole.Role.moderator == role && MUCRole.Role.none == newRole) {
throw new NotAllowedException();
}
// TODO A moderator MUST NOT be able to revoke voice from a user whose affiliation is at or
// above the moderator's level.
// TODO above the moderator's level.
role = newRole;
if (MUCRole.NONE_ROLE == role) {
if (MUCRole.Role.none == role) {
presence.setType(Presence.Type.unavailable);
presence.setStatus(null);
}
calculateExtendedInformation();
}
public int getRole() {
public MUCRole.Role getRole() {
return role;
}
public String getRoleAsString() {
if (MUCRole.MODERATOR == role) {
return "moderator";
}
else if (MUCRole.PARTICIPANT == role) {
return "participant";
}
else if (MUCRole.VISITOR == role) {
return "visitor";
}
return "none";
}
public void setAffiliation(int newAffiliation) throws NotAllowedException {
public void setAffiliation(MUCRole.Affiliation newAffiliation) throws NotAllowedException {
// Don't allow to ban an owner or an admin
if (MUCRole.OWNER == affiliation || MUCRole.ADMINISTRATOR == affiliation) {
if (MUCRole.OUTCAST == newAffiliation) {
if (MUCRole.Affiliation.owner == affiliation || MUCRole.Affiliation.admin== affiliation) {
if (MUCRole.Affiliation.outcast == newAffiliation) {
throw new NotAllowedException();
}
}
......@@ -188,26 +171,10 @@ public class MUCRoleImpl implements MUCRole {
calculateExtendedInformation();
}
public int getAffiliation() {
public MUCRole.Affiliation getAffiliation() {
return affiliation;
}
public String getAffiliationAsString() {
if (MUCRole.OWNER == affiliation) {
return "owner";
}
else if (MUCRole.ADMINISTRATOR == affiliation) {
return "admin";
}
else if (MUCRole.MEMBER == affiliation) {
return "member";
}
else if (MUCRole.OUTCAST == affiliation) {
return "outcast";
}
return "none";
}
public String getNickname() {
return nick;
}
......@@ -235,17 +202,7 @@ public class MUCRoleImpl implements MUCRole {
presence.setFrom(jid);
}
public void send(Presence packet) {
packet.setTo(user.getAddress());
router.route(packet);
}
public void send(Message packet) {
packet.setTo(user.getAddress());
router.route(packet);
}
public void send(IQ packet) {
public void send(Packet packet) {
packet.setTo(user.getAddress());
router.route(packet);
}
......@@ -256,7 +213,7 @@ public class MUCRoleImpl implements MUCRole {
*/
private void calculateExtendedInformation() {
ElementUtil.setProperty(extendedInformation, "x.item:jid", user.getAddress().toString());
ElementUtil.setProperty(extendedInformation, "x.item:affiliation", getAffiliationAsString());
ElementUtil.setProperty(extendedInformation, "x.item:role", getRoleAsString());
ElementUtil.setProperty(extendedInformation, "x.item:affiliation", affiliation.toString());
ElementUtil.setProperty(extendedInformation, "x.item:role", role.toString());
}
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.spi;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import org.jivesoftware.messenger.*;
import org.jivesoftware.messenger.auth.UnauthorizedException;
import org.jivesoftware.messenger.container.BasicModule;
import org.jivesoftware.messenger.handler.IQHandler;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;
import org.dom4j.Element;
/**
* Generic presence routing base class.
*
* @author Iain Shigeoka
*/
public class IQRouterImpl extends BasicModule implements IQRouter {
private RoutingTable routingTable;
private List<IQHandler> iqHandlers = new ArrayList<IQHandler>();
private Map<String, IQHandler> namespace2Handlers = new ConcurrentHashMap<String, IQHandler>();
private SessionManager sessionManager;
/**
* Creates a packet router.
*/
public IQRouterImpl() {
super("XMPP IQ Router");
}
public void route(IQ packet) {
if (packet == null) {
throw new NullPointerException();
}
Session session = sessionManager.getSession(packet.getFrom());
if (session == null || session.getStatus() == Session.STATUS_AUTHENTICATED
|| (isLocalServer(packet.getTo())
&& ("jabber:iq:auth".equals(packet.getChildElement().getNamespaceURI())
|| "jabber:iq:register".equals(packet.getChildElement().getNamespaceURI())))
) {
handle(packet);
}
else {
packet.setTo(sessionManager.getSession(packet.getFrom()).getAddress());
packet.setError(PacketError.Condition.not_authorized);
try {
sessionManager.getSession(packet.getFrom()).process(packet);
}
catch (UnauthorizedException ue) {
Log.error(ue);
}
}
}
private boolean isLocalServer(JID recipientJID) {
return recipientJID == null || recipientJID.getDomain() == null
|| "".equals(recipientJID.getDomain()) || recipientJID.getResource() == null
|| "".equals(recipientJID.getResource());
}
private void handle(IQ packet) {
JID recipientJID = packet.getTo();
try {
if (isLocalServer(recipientJID)) {
Element childElement = packet.getChildElement();
String namespace = null;
if (childElement != null) {
namespace = childElement.getNamespaceURI();
}
if (namespace == null) {
// Do nothing. We can't handle queries outside of a valid namespace
Log.warn("Unknown packet " + packet);
}
else {
IQHandler handler = getHandler(namespace);
if (handler == null) {
IQ reply = IQ.createResultIQ(packet);
if (recipientJID == null) {
// Answer an error since the server can't handle the requested namespace
reply.setError(PacketError.Condition.service_unavailable);
}
else if (recipientJID.getNode() == null || "".equals(recipientJID.getNode())) {
// Answer an error if JID is of the form <domain>
reply.setError(PacketError.Condition.feature_not_implemented);
}
else {
// JID is of the form <node@domain>
try {
// Let a "service" handle this packet otherwise return an error
// Useful for MUC where node refers to a room and domain is the
// MUC service.
ChannelHandler route = routingTable.getRoute(recipientJID);
if (route instanceof BasicModule) {
route.process(packet);
return;
}
}
catch (NoSuchRouteException e) {
// do nothing
}
// Answer an error since the server can't handle packets sent to a node
reply.setError(PacketError.Condition.service_unavailable);
}
Session session = sessionManager.getSession(packet.getFrom());
if (session != null) {
session.getConnection().deliver(reply);
}
else {
Log.warn("Packet could not be delivered " + packet);
}
}
else {
handler.process(packet);
}
}
}
else {
// JID is of the form <node@domain/resource>
ChannelHandler route = routingTable.getRoute(recipientJID);
route.process(packet);
}
}
catch (NoSuchRouteException e) {
Log.info("Packet sent to unreachable address " + packet);
Session session = sessionManager.getSession(packet.getFrom());
if (session != null) {
try {
packet.setError(PacketError.Condition.service_unavailable);
session.getConnection().deliver(packet);
}
catch (UnauthorizedException ex) {
Log.error(LocaleUtils.getLocalizedString("admin.error.routing"), e);
}
}
}
catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error.routing"), e);
try {
Session session = sessionManager.getSession(packet.getFrom());
if (session != null) {
Connection conn = session.getConnection();
if (conn != null) {
conn.close();
}
}
}
catch (UnauthorizedException e1) {
// do nothing
}
}
}
private IQHandler getHandler(String namespace) {
IQHandler handler = namespace2Handlers.get(namespace);
if (handler == null) {
for (IQHandler handlerCandidate : iqHandlers) {
IQHandlerInfo handlerInfo = handlerCandidate.getInfo();
if (handlerInfo != null && namespace.equalsIgnoreCase(handlerInfo.getNamespace())) {
handler = handlerCandidate;
namespace2Handlers.put(namespace, handler);
break;
}
}
}
return handler;
}
/**
* <p>Adds a new IQHandler to the list of registered handler. The new IQHandler will be
* responsible for handling IQ packet whose namespace matches the namespace of the
* IQHandler.</p>
*
* An IllegalArgumentException may be thrown if the IQHandler to register was already provided
* by the server. The server provides a certain list of IQHandlers when the server is
* started up.
*
* @param handler the IQHandler to add to the list of registered handler.
*/
public void addHandler(IQHandler handler) {
if (iqHandlers.contains(handler)) {
throw new IllegalArgumentException("IQHandler already provided by the server");
}
// Register the handler as the handler of the namespace
namespace2Handlers.put(handler.getInfo().getNamespace(), handler);
}
/**
* <p>Removes an IQHandler from the list of registered handler. The IQHandler to remove was
* responsible for handling IQ packet whose namespace matches the namespace of the
* IQHandler.</p>
*
* An IllegalArgumentException may be thrown if the IQHandler to remove was already provided
* by the server. The server provides a certain list of IQHandlers when the server is
* started up.
*
* @param handler the IQHandler to remove from the list of registered handler.
*/
public void removeHandler(IQHandler handler) {
if (iqHandlers.contains(handler)) {
throw new IllegalArgumentException("Cannot remove an IQHandler provided by the server");
}
// Unregister the handler as the handler of the namespace
namespace2Handlers.remove(handler.getInfo().getNamespace());
}
public void initialize(XMPPServer server) {
super.initialize(server);
routingTable = server.getRoutingTable();
iqHandlers.addAll(server.getIQHandlers());
sessionManager = server.getSessionManager();
}
}
......@@ -24,6 +24,7 @@ import org.xmpp.packet.IQ;
* @author Iain Shigeoka
*/
public class PacketRouterImpl extends BasicModule implements PacketRouter {
private IQRouter iqRouter;
private PresenceRouter presenceRouter;
private MessageRouter messageRouter;
......
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