Adds support for "Modifying room subject" . SMACK-99

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@2313 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Gaston Dombiak 2004-05-18 17:48:25 +00:00 committed by gdombiak
parent 28bedcb31b
commit af9f7dd469
1 changed files with 198 additions and 49 deletions

View File

@ -73,19 +73,23 @@ public class MultiUserChat {
private final static String discoNamespace = "http://jabber.org/protocol/muc";
private final static String discoNode = "http://jabber.org/protocol/muc#rooms";
private static Map joinedRooms = new WeakHashMap();
private XMPPConnection connection;
private String room;
private String subject;
private String nickname = null;
private boolean joined = false;
private Map participantsMap = new HashMap();
private List invitationRejectionListeners = new ArrayList();
private List subjectUpdatedListeners = new ArrayList();
private PacketFilter presenceFilter;
private PacketListener presenceListener;
private PacketFilter subjectFilter;
private PacketListener subjectListener;
private PacketFilter messageFilter;
private PacketFilter declinesFilter;
private PacketListener declinesListener;
@ -129,54 +133,7 @@ public class MultiUserChat {
public MultiUserChat(XMPPConnection connection, String room) {
this.connection = connection;
this.room = room;
// Create a collector for all incoming messages.
messageFilter =
new AndFilter(new FromContainsFilter(room), new PacketTypeFilter(Message.class));
messageFilter = new AndFilter(messageFilter, new PacketFilter() {
public boolean accept(Packet packet) {
Message msg = (Message) packet;
return msg.getType() == Message.Type.GROUP_CHAT;
}
});
messageCollector = connection.createPacketCollector(messageFilter);
// Create a listener for all presence updates.
presenceFilter =
new AndFilter(new FromContainsFilter(room), new PacketTypeFilter(Presence.class));
presenceListener = new PacketListener() {
public void processPacket(Packet packet) {
Presence presence = (Presence) packet;
String from = presence.getFrom();
if (presence.getType() == Presence.Type.AVAILABLE) {
synchronized (participantsMap) {
participantsMap.put(from, presence);
}
}
else if (presence.getType() == Presence.Type.UNAVAILABLE) {
synchronized (participantsMap) {
participantsMap.remove(from);
}
}
}
};
connection.addPacketListener(presenceListener, presenceFilter);
// Listens for all messages that include a MUCUser extension and fire the invitation
// rejection listeners if the message includes an invitation rejection.
declinesFilter = new PacketExtensionFilter("x", "http://jabber.org/protocol/muc#user");
declinesListener = new PacketListener() {
public void processPacket(Packet packet) {
// Get the MUC User extension
MUCUser mucUser = getMUCUserExtension(packet);
// Check if the MUCUser informs that the invitee has declined the invitation
if (mucUser.getDecline() != null) {
// Fire event for invitation rejection listeners
fireInvitationRejectionListeners(
mucUser.getDecline().getFrom(),
mucUser.getDecline().getReason());
}
};
};
connection.addPacketListener(declinesListener, declinesFilter);
init();
}
/**
@ -298,6 +255,9 @@ public class MultiUserChat {
// Wait up to a certain number of seconds for a reply.
Presence presence =
(Presence) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Stop queuing results
response.cancel();
if (presence == null) {
throw new XMPPException("No response from server.");
}
@ -459,6 +419,9 @@ public class MultiUserChat {
connection.sendPacket(joinPresence);
// Wait up to a certain number of seconds for a reply.
Presence presence = (Presence) response.nextResult(timeout);
// Stop queuing results
response.cancel();
if (presence == null) {
throw new XMPPException("No response from server.");
}
@ -663,6 +626,11 @@ public class MultiUserChat {
else if (answer.getError() != null) {
throw new XMPPException(answer.getError());
}
// Reset participant information.
participantsMap = new HashMap();
nickname = null;
joined = false;
userHasLeft();
}
/**
@ -777,6 +745,63 @@ public class MultiUserChat {
listeners[i].invitationDeclined(invitee, reason);
}
}
/**
* Adds a listener to subject change notifications. The listener will be fired anytime
* the room's subject changes.
*
* @param listener a subject updated listener.
*/
public void addSubjectUpdatedListener(SubjectUpdatedListener listener) {
synchronized (subjectUpdatedListeners) {
if (!subjectUpdatedListeners.contains(listener)) {
subjectUpdatedListeners.add(listener);
}
}
}
/**
* Removes a listener from subject change notifications. The listener will be fired
* anytime the room's subject changes.
*
* @param listener a subject updated listener.
*/
public void removeSubjectUpdatedListener(SubjectUpdatedListener listener) {
synchronized (subjectUpdatedListeners) {
subjectUpdatedListeners.remove(listener);
}
}
/**
* Fires subject updated listeners.
*/
private void fireSubjectUpdatedListeners(String subject, String from) {
SubjectUpdatedListener[] listeners = null;
synchronized (subjectUpdatedListeners) {
listeners = new SubjectUpdatedListener[subjectUpdatedListeners.size()];
subjectUpdatedListeners.toArray(listeners);
}
for (int i = 0; i < listeners.length; i++) {
listeners[i].subjectUpdated(subject, from);
}
}
/**
* Returns the last known room's subject or <tt>null</tt> if the user hasn't joined the room
* or the room does not have a subject yet. In case the room has a subject, as soon as the
* user joins the room a message with the current room's subject will be received.<p>
*
* To be notified every time the room's subject change you should add a listener
* to this room. (@see addSubjectUpdatedListener(SubjectUpdatedListener))<p>
*
* To change the room's subject use <code>changeSubject(String)</code>.
*
* @return the room's subject or <tt>null</tt> if the user hasn't joined the room or the
* room does not have a subject yet.
*/
public String getSubject() {
return subject;
}
/**
* Returns the reserved room nickname for the user in the room. A user may have a reserved
@ -852,6 +877,9 @@ public class MultiUserChat {
// Wait up to a certain number of seconds for a reply.
Presence presence =
(Presence) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Stop queuing results
response.cancel();
if (presence == null) {
throw new XMPPException("No response from server.");
}
@ -1065,6 +1093,47 @@ public class MultiUserChat {
connection.addPacketListener(listener, messageFilter);
}
/**
* Changes the subject within the room. As a default, only users with a role of "moderator"
* are allowed to change the subject in a room. Although some rooms may be configured to
* allow a mere participant or even a visitor to change the subject.
*
* @param subject the new room's subject to set.
* @throws XMPPException if someone without appropriate privileges attempts to change the
* room subject will throw an error with code 403 (i.e. Forbidden)
*/
public void changeSubject(final String subject) throws XMPPException {
// TODO Implement way to listen to changes of subject made by other users
Message message = new Message(room, Message.Type.GROUP_CHAT);
message.setSubject(subject);
// Wait for an error or confirmation message back from the server.
PacketFilter responseFilter =
new AndFilter(
new FromContainsFilter(room),
new PacketTypeFilter(Message.class));
responseFilter = new AndFilter(responseFilter, new PacketFilter() {
public boolean accept(Packet packet) {
Message msg = (Message) packet;
return subject.equals(msg.getSubject());
}
});
PacketCollector response = connection.createPacketCollector(responseFilter);
// Send change subject packet.
connection.sendPacket(message);
// Wait up to a certain number of seconds for a reply.
Message answer =
(Message) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Stop queuing results
response.cancel();
if (answer == null) {
throw new XMPPException("No response from server.");
}
else if (answer.getError() != null) {
throw new XMPPException(answer.getError());
}
}
/**
* Notification message that the user has joined the room.
*/
@ -1104,8 +1173,88 @@ public class MultiUserChat {
return null;
}
private void init() {
// Create a collector for all incoming messages.
messageFilter =
new AndFilter(
new FromContainsFilter(room),
new MessageTypeFilter(Message.Type.GROUP_CHAT));
messageFilter = new AndFilter(messageFilter, new PacketFilter() {
public boolean accept(Packet packet) {
Message msg = (Message) packet;
return msg.getBody() != null;
}
});
messageCollector = connection.createPacketCollector(messageFilter);
// Create a listener for all subject updates.
subjectFilter =
new AndFilter(
new FromContainsFilter(room),
new MessageTypeFilter(Message.Type.GROUP_CHAT));
subjectFilter = new AndFilter(subjectFilter, new PacketFilter() {
public boolean accept(Packet packet) {
Message msg = (Message) packet;
return msg.getSubject() != null;
}
});
subjectListener = new PacketListener() {
public void processPacket(Packet packet) {
Message msg = (Message) packet;
// Update the room subject
subject = msg.getSubject();
// Fire event for subject updated listeners
fireSubjectUpdatedListeners(
msg.getSubject(),
msg.getFrom());
}
};
connection.addPacketListener(subjectListener, subjectFilter);
// Create a listener for all presence updates.
presenceFilter =
new AndFilter(new FromContainsFilter(room), new PacketTypeFilter(Presence.class));
presenceListener = new PacketListener() {
public void processPacket(Packet packet) {
Presence presence = (Presence) packet;
String from = presence.getFrom();
if (presence.getType() == Presence.Type.AVAILABLE) {
synchronized (participantsMap) {
participantsMap.put(from, presence);
}
}
else if (presence.getType() == Presence.Type.UNAVAILABLE) {
synchronized (participantsMap) {
participantsMap.remove(from);
}
}
}
};
connection.addPacketListener(presenceListener, presenceFilter);
// Listens for all messages that include a MUCUser extension and fire the invitation
// rejection listeners if the message includes an invitation rejection.
declinesFilter = new PacketExtensionFilter("x", "http://jabber.org/protocol/muc#user");
declinesListener = new PacketListener() {
public void processPacket(Packet packet) {
// Get the MUC User extension
MUCUser mucUser = getMUCUserExtension(packet);
// Check if the MUCUser informs that the invitee has declined the invitation
if (mucUser.getDecline() != null) {
// Fire event for invitation rejection listeners
fireInvitationRejectionListeners(
mucUser.getDecline().getFrom(),
mucUser.getDecline().getReason());
}
};
};
connection.addPacketListener(declinesListener, declinesFilter);
}
public void finalize() {
if (connection != null) {
messageCollector.cancel();
connection.removePacketListener(subjectListener);
connection.removePacketListener(presenceListener);
connection.removePacketListener(declinesListener);
}