mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-12-27 13:07:58 +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 {
|
||||
|
||||
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 nickname = null;
|
||||
|
@ -86,15 +91,22 @@ public class MultiUserChat {
|
|||
private PacketListener declinesListener;
|
||||
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 {
|
||||
XMPPConnection.addConnectionListener(new ConnectionEstablishedListener() {
|
||||
public void connectionEstablished(XMPPConnection connection) {
|
||||
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(
|
||||
"http://jabber.org/protocol/muc");
|
||||
public void connectionEstablished(final XMPPConnection connection) {
|
||||
// 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.
|
||||
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,9 +148,7 @@ public class MultiUserChat {
|
|||
String from = presence.getFrom();
|
||||
if (presence.getType() == Presence.Type.AVAILABLE) {
|
||||
synchronized (participantsMap) {
|
||||
if (!participantsMap.containsKey(from)) {
|
||||
participantsMap.put(from, presence);
|
||||
}
|
||||
participantsMap.put(from, presence);
|
||||
}
|
||||
}
|
||||
else if (presence.getType() == Presence.Type.UNAVAILABLE) {
|
||||
|
@ -169,6 +179,69 @@ public class MultiUserChat {
|
|||
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.
|
||||
*
|
||||
|
@ -198,7 +271,7 @@ public class MultiUserChat {
|
|||
* (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)
|
||||
*/
|
||||
public void create(String nickname) throws XMPPException {
|
||||
public synchronized void create(String nickname) throws XMPPException {
|
||||
if (nickname == null || nickname.equals("")) {
|
||||
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
|
||||
this.nickname = nickname;
|
||||
joined = true;
|
||||
userHasJoined();
|
||||
|
||||
// Look for confirmation of room creation from the server
|
||||
MUCUser mucUser = getMUCUserExtension(presence);
|
||||
|
@ -393,6 +467,7 @@ public class MultiUserChat {
|
|||
}
|
||||
this.nickname = nickname;
|
||||
joined = true;
|
||||
userHasJoined();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -422,6 +497,7 @@ public class MultiUserChat {
|
|||
participantsMap = new HashMap();
|
||||
nickname = null;
|
||||
joined = false;
|
||||
userHasLeft();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -716,12 +792,10 @@ public class MultiUserChat {
|
|||
ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(
|
||||
room,
|
||||
"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();) {
|
||||
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
|
||||
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>
|
||||
* 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) {
|
||||
// Get the participant's presence
|
||||
Presence presence = (Presence) participantsMap.get(participant);
|
||||
Presence presence = getParticipantPresence(participant);
|
||||
// Get the MUC User extension
|
||||
MUCUser mucUser = getMUCUserExtension(presence);
|
||||
if (mucUser != null) {
|
||||
|
@ -978,6 +1065,31 @@ public class MultiUserChat {
|
|||
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.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue