mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-30 07:52:06 +01:00
1. Allows to discover joined rooms of other users
2. Allows to retrieve the Presence of a given participant 3. Fixes a bug that prevented to update an existing participant's Presence git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@2309 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
6793015fe9
commit
e343c571a5
1 changed files with 128 additions and 16 deletions
|
@ -71,6 +71,11 @@ import org.jivesoftware.smackx.packet.*;
|
||||||
*/
|
*/
|
||||||
public class MultiUserChat {
|
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 XMPPConnection connection;
|
||||||
private String room;
|
private String room;
|
||||||
private String nickname = null;
|
private String nickname = null;
|
||||||
|
@ -86,15 +91,22 @@ public class MultiUserChat {
|
||||||
private PacketListener declinesListener;
|
private PacketListener declinesListener;
|
||||||
private PacketCollector messageCollector;
|
private PacketCollector messageCollector;
|
||||||
|
|
||||||
// Set on every established connection that this client supports the Multi-User Chat protocol.
|
|
||||||
// This information will be used when another client tries to discover whether this client
|
|
||||||
// supports MUC or not.
|
|
||||||
// Note: The ServiceDiscoveryManager class should have been already initialized
|
|
||||||
static {
|
static {
|
||||||
XMPPConnection.addConnectionListener(new ConnectionEstablishedListener() {
|
XMPPConnection.addConnectionListener(new ConnectionEstablishedListener() {
|
||||||
public void connectionEstablished(XMPPConnection connection) {
|
public void connectionEstablished(final XMPPConnection connection) {
|
||||||
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(
|
// Set on every established connection that this client supports the Multi-User
|
||||||
"http://jabber.org/protocol/muc");
|
// Chat protocol. This information will be used when another client tries to
|
||||||
|
// discover whether this client supports MUC or not.
|
||||||
|
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(discoNamespace);
|
||||||
|
// Set the NodeInformationProvider that will provide information about the
|
||||||
|
// joined rooms whenever a disco request is received
|
||||||
|
ServiceDiscoveryManager.getInstanceFor(connection).setNodeInformationProvider(
|
||||||
|
discoNode,
|
||||||
|
new NodeInformationProvider() {
|
||||||
|
public Iterator getNodeItems() {
|
||||||
|
return MultiUserChat.getJoinedRooms(connection);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -136,11 +148,9 @@ public class MultiUserChat {
|
||||||
String from = presence.getFrom();
|
String from = presence.getFrom();
|
||||||
if (presence.getType() == Presence.Type.AVAILABLE) {
|
if (presence.getType() == Presence.Type.AVAILABLE) {
|
||||||
synchronized (participantsMap) {
|
synchronized (participantsMap) {
|
||||||
if (!participantsMap.containsKey(from)) {
|
|
||||||
participantsMap.put(from, presence);
|
participantsMap.put(from, presence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (presence.getType() == Presence.Type.UNAVAILABLE) {
|
else if (presence.getType() == Presence.Type.UNAVAILABLE) {
|
||||||
synchronized (participantsMap) {
|
synchronized (participantsMap) {
|
||||||
participantsMap.remove(from);
|
participantsMap.remove(from);
|
||||||
|
@ -169,6 +179,69 @@ public class MultiUserChat {
|
||||||
connection.addPacketListener(declinesListener, declinesFilter);
|
connection.addPacketListener(declinesListener, declinesFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the specified user supports the Multi-User Chat protocol.
|
||||||
|
*
|
||||||
|
* @param connection the connection to use to perform the service discovery.
|
||||||
|
* @param user the user to check. A fully qualified xmpp ID, e.g. jdoe@example.com.
|
||||||
|
* @return a boolean indicating whether the specified user supports the MUC protocol.
|
||||||
|
*/
|
||||||
|
public static boolean isServiceEnabled(XMPPConnection connection, String user) {
|
||||||
|
try {
|
||||||
|
DiscoverInfo result =
|
||||||
|
ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(user);
|
||||||
|
return result.containsFeature(discoNamespace);
|
||||||
|
}
|
||||||
|
catch (XMPPException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an Iterator on the rooms where the user has joined using a given connection.
|
||||||
|
* The Iterator will contain Strings where each String represents a room
|
||||||
|
* (e.g. room@muc.jabber.org).
|
||||||
|
*
|
||||||
|
* @param connection the connection used to join the rooms.
|
||||||
|
* @return an Iterator on the rooms where the user has joined using a given connection.
|
||||||
|
*/
|
||||||
|
private static Iterator getJoinedRooms(XMPPConnection connection) {
|
||||||
|
ArrayList rooms = (ArrayList)joinedRooms.get(connection);
|
||||||
|
if (rooms != null) {
|
||||||
|
return rooms.iterator();
|
||||||
|
}
|
||||||
|
// Return an iterator on an empty collection (i.e. the user never joined a room)
|
||||||
|
return new ArrayList().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an Iterator on the rooms where the requested user has joined. The Iterator will
|
||||||
|
* contain Strings where each String represents a room (e.g. room@muc.jabber.org).
|
||||||
|
*
|
||||||
|
* @param connection the connection to use to perform the service discovery.
|
||||||
|
* @param user the user to check. A fully qualified xmpp ID, e.g. jdoe@example.com.
|
||||||
|
* @return an Iterator on the rooms where the requested user has joined.
|
||||||
|
*/
|
||||||
|
public static Iterator getJoinedRooms(XMPPConnection connection, String user) {
|
||||||
|
try {
|
||||||
|
ArrayList answer = new ArrayList();
|
||||||
|
// Send the disco packet to the user
|
||||||
|
DiscoverItems result =
|
||||||
|
ServiceDiscoveryManager.getInstanceFor(connection).discoverItems(user, discoNode);
|
||||||
|
// Collect the entityID for each returned item
|
||||||
|
for (Iterator items=result.getItems(); items.hasNext();) {
|
||||||
|
answer.add(((DiscoverItems.Item)items.next()).getEntityID());
|
||||||
|
}
|
||||||
|
return answer.iterator();
|
||||||
|
}
|
||||||
|
catch (XMPPException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
// Return an iterator on an empty collection
|
||||||
|
return new ArrayList().iterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the room this GroupChat object represents.
|
* Returns the name of the room this GroupChat object represents.
|
||||||
*
|
*
|
||||||
|
@ -198,7 +271,7 @@ public class MultiUserChat {
|
||||||
* (e.g. room already exists; user already joined to an existant room or
|
* (e.g. room already exists; user already joined to an existant room or
|
||||||
* 405 error if the user is not allowed to create the room)
|
* 405 error if the user is not allowed to create the room)
|
||||||
*/
|
*/
|
||||||
public void create(String nickname) throws XMPPException {
|
public synchronized void create(String nickname) throws XMPPException {
|
||||||
if (nickname == null || nickname.equals("")) {
|
if (nickname == null || nickname.equals("")) {
|
||||||
throw new IllegalArgumentException("Nickname must not be null or blank.");
|
throw new IllegalArgumentException("Nickname must not be null or blank.");
|
||||||
}
|
}
|
||||||
|
@ -234,6 +307,7 @@ public class MultiUserChat {
|
||||||
// Whether the room existed before or was created, the user has joined the room
|
// Whether the room existed before or was created, the user has joined the room
|
||||||
this.nickname = nickname;
|
this.nickname = nickname;
|
||||||
joined = true;
|
joined = true;
|
||||||
|
userHasJoined();
|
||||||
|
|
||||||
// Look for confirmation of room creation from the server
|
// Look for confirmation of room creation from the server
|
||||||
MUCUser mucUser = getMUCUserExtension(presence);
|
MUCUser mucUser = getMUCUserExtension(presence);
|
||||||
|
@ -393,6 +467,7 @@ public class MultiUserChat {
|
||||||
}
|
}
|
||||||
this.nickname = nickname;
|
this.nickname = nickname;
|
||||||
joined = true;
|
joined = true;
|
||||||
|
userHasJoined();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -422,6 +497,7 @@ public class MultiUserChat {
|
||||||
participantsMap = new HashMap();
|
participantsMap = new HashMap();
|
||||||
nickname = null;
|
nickname = null;
|
||||||
joined = false;
|
joined = false;
|
||||||
|
userHasLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -716,13 +792,11 @@ public class MultiUserChat {
|
||||||
ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(
|
ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(
|
||||||
room,
|
room,
|
||||||
"x-roomuser-item");
|
"x-roomuser-item");
|
||||||
// Look for the Identity whose category is "client" and return its name
|
// Look for an Identity that holds the reserved nickname and return its name
|
||||||
for (Iterator identities = result.getIdentities(); identities.hasNext();) {
|
for (Iterator identities = result.getIdentities(); identities.hasNext();) {
|
||||||
DiscoverInfo.Identity identity = (DiscoverInfo.Identity) identities.next();
|
DiscoverInfo.Identity identity = (DiscoverInfo.Identity) identities.next();
|
||||||
if ("client".equals(identity.getCategory())) {
|
|
||||||
return identity.getName();
|
return identity.getName();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// If no Identity was found then the user does not have a reserved room nickname
|
// If no Identity was found then the user does not have a reserved room nickname
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -849,6 +923,19 @@ public class MultiUserChat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the presence info for a particular participant, or <tt>null</tt> if the participant
|
||||||
|
* is not in the room.<p>
|
||||||
|
*
|
||||||
|
* @param participant the room occupant to search for his presence. The format of participant must
|
||||||
|
* be: roomName@service/nickname (e.g. darkcave@macbeth.shakespeare.lit/thirdwitch).
|
||||||
|
* @return the participant's current presence, or <tt>null</tt> if the user is unavailable
|
||||||
|
* or if no presence information is available.
|
||||||
|
*/
|
||||||
|
public Presence getParticipantPresence(String participant) {
|
||||||
|
return (Presence) participantsMap.get(participant);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the participant's full JID when joining a Non-Anonymous room or <tt>null</tt>
|
* Returns the participant's full JID when joining a Non-Anonymous room or <tt>null</tt>
|
||||||
* if the room is of type anonymous. If the room is of type semi-anonymous only the
|
* if the room is of type anonymous. If the room is of type semi-anonymous only the
|
||||||
|
@ -861,7 +948,7 @@ public class MultiUserChat {
|
||||||
*/
|
*/
|
||||||
public String getParticipantJID(String participant) {
|
public String getParticipantJID(String participant) {
|
||||||
// Get the participant's presence
|
// Get the participant's presence
|
||||||
Presence presence = (Presence) participantsMap.get(participant);
|
Presence presence = getParticipantPresence(participant);
|
||||||
// Get the MUC User extension
|
// Get the MUC User extension
|
||||||
MUCUser mucUser = getMUCUserExtension(presence);
|
MUCUser mucUser = getMUCUserExtension(presence);
|
||||||
if (mucUser != null) {
|
if (mucUser != null) {
|
||||||
|
@ -978,6 +1065,31 @@ public class MultiUserChat {
|
||||||
connection.addPacketListener(listener, messageFilter);
|
connection.addPacketListener(listener, messageFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification message that the user has joined the room.
|
||||||
|
*/
|
||||||
|
private synchronized void userHasJoined() {
|
||||||
|
// Update the list of joined rooms through this connection
|
||||||
|
ArrayList rooms = (ArrayList)joinedRooms.get(connection);
|
||||||
|
if (rooms == null) {
|
||||||
|
rooms = new ArrayList();
|
||||||
|
joinedRooms.put(connection, rooms);
|
||||||
|
}
|
||||||
|
rooms.add(room);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification message that the user has left the room.
|
||||||
|
*/
|
||||||
|
private synchronized void userHasLeft() {
|
||||||
|
// Update the list of joined rooms through this connection
|
||||||
|
ArrayList rooms = (ArrayList)joinedRooms.get(connection);
|
||||||
|
if (rooms == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rooms.remove(room);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the MUCUser packet extension included in the packet or <tt>null</tt> if none.
|
* Returns the MUCUser packet extension included in the packet or <tt>null</tt> if none.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue