Permalink
Browse files

VYSPER-317: store occupant presences, to provide them to later enteri…

…ng occupants

git-svn-id: https://svn.apache.org/repos/asf/mina/vysper/trunk@1345088 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
1 parent 6ddbfe7 commit 6a6a0c856139a6e0d31b56095ec22b0c8888e1e9 Bernd Fondermann committed Jun 1, 2012
@@ -19,23 +19,21 @@
*/
package org.apache.vysper.xmpp.modules.extension.xep0045_muc;
-import java.util.List;
-
-import org.apache.vysper.xml.fragment.Attribute;
import org.apache.vysper.xml.fragment.XMLElement;
-import org.apache.vysper.xml.fragment.XMLFragment;
import org.apache.vysper.xmpp.addressing.Entity;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.stanzas.X;
import org.apache.vysper.xmpp.stanza.PresenceStanzaType;
import org.apache.vysper.xmpp.stanza.Stanza;
import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import java.util.List;
+
/**
* Specialized {@link StanzaBuilder} for MUC
*
* @author The Apache MINA Project (dev@mina.apache.org)
*/
-public class MUCStanzaBuilder extends StanzaBuilder {
+public class MUCStanzaBuilder {
public static Stanza createPresenceStanza(Entity from, Entity to, PresenceStanzaType type, String xNamespaceUri,
List<XMLElement> innerElms) {
@@ -44,18 +42,16 @@ public static Stanza createPresenceStanza(Entity from, Entity to, PresenceStanza
public static Stanza createPresenceStanza(Entity from, Entity to, PresenceStanzaType type, String xNamespaceUri,
XMLElement... innerElms) {
- StanzaBuilder builder = StanzaBuilder.createPresenceStanza(from, to, null, type, null, null);
- builder.addPreparedElement(new X(xNamespaceUri, innerElms));
-
- return builder.build();
+ return createPresenceStanza(from, to, null, type, null, null, xNamespaceUri, innerElms).build();
}
- public MUCStanzaBuilder(String stanzaName, String namespaceURI, List<Attribute> attributes,
- List<XMLFragment> innerFragments) {
- super(stanzaName, namespaceURI, null, attributes, innerFragments);
- }
+ public static StanzaBuilder createPresenceStanza(Entity from, Entity to, String lang, PresenceStanzaType type,
+ String show, String status,
+ String xNamespaceUri, XMLElement... innerElms) {
+ StanzaBuilder builder = StanzaBuilder.createPresenceStanza(from, to, lang, type, show, status);
+ builder.addPreparedElement(new X(xNamespaceUri, innerElms));
- public MUCStanzaBuilder(String stanzaName, String namespaceURI) {
- super(stanzaName, namespaceURI);
+ return builder;
}
+
}
@@ -292,7 +292,7 @@ private Stanza changeAffiliation(IQStanza stanza, ServerRuntimeContext serverRun
MucUserItem presenceItem = new MucUserItem(target, null, newAffiliation, Role.None);
for (Occupant occupant : room.getOccupants()) {
- StanzaBuilder builder = MUCStanzaBuilder.createMessageStanza(room.getJID(), occupant.getJid(), null, null);
+ StanzaBuilder builder = StanzaBuilder.createMessageStanza(room.getJID(), occupant.getJid(), null, null);
builder.addPreparedElement(presenceItem);
relayStanza(occupant.getJid(), builder.build(), serverRuntimeContext);
@@ -115,6 +115,25 @@ protected Stanza executePresenceLogic(PresenceStanza stanza, ServerRuntimeContex
}
+ /**
+ * creates a presence available stanza, consisting of a combination of
+ * a. information about the occupant in the room, (in the http://jabber.org/protocol/muc#user namespace)
+ * b. information he sent with his latest presence message, e.g. show and status
+ */
+ private Stanza createPresenceStanzaFromLatest(Entity from, Entity to, String lang, PresenceStanzaType type,
+ PresenceStanza templatePresence,
+ String xNamespaceUri, XMLElement... innerElms) {
+ String show = null;
+ String status = null;
+ if (templatePresence != null) {
+ show = getInnerElementText(templatePresence, "show");
+ status = getInnerElementText(templatePresence, "status");
+ if (lang == null) lang = templatePresence.getXMLLang();
+ }
+ final StanzaBuilder presenceStanza = MUCStanzaBuilder.createPresenceStanza(from, to, lang, type, show, status, xNamespaceUri, innerElms);
+ return presenceStanza.build();
+ }
+
private String getInnerElementText(XMLElement element, String childName) {
try {
XMLElement childElm = element.getSingleInnerElementsNamed(childName);
@@ -144,9 +163,10 @@ private Stanza available(PresenceStanza stanza, Entity roomJid, Entity newOccupa
return createPresenceErrorStanza(roomJid, newOccupantJid, stanza.getID(), "auth", "not-authorized");
}
- if (room.isInRoom(newOccupantJid)) {
+ final Occupant occupant = room.findOccupantByJID(newOccupantJid);
+ if (occupant != null) {
// occupant is already in room
- Occupant occupant = room.findOccupantByJID(newOccupantJid);
+ room.recordLatestPresence(newOccupantJid, stanza);
if (nick.equals(occupant.getNick())) {
// nick unchanged, change show and status
logger.debug("{} has updated presence in room {}", newOccupantJid, roomJid);
@@ -218,6 +238,7 @@ private Stanza available(PresenceStanza stanza, Entity roomJid, Entity newOccupa
Occupant newOccupant;
try {
newOccupant = room.addOccupant(newOccupantJid, nick);
+ room.recordLatestPresence(newOccupantJid, stanza);
} catch(RuntimeException e) {
final String message = e.getMessage();
logger.debug("{} has not been added as occupant to room {}, reason: " + message, newOccupantJid, roomJid);
@@ -242,13 +263,14 @@ private Stanza available(PresenceStanza stanza, Entity roomJid, Entity newOccupa
}
// relay presence of all existing room occupants to the now joined occupant
- for (Occupant occupant : room.getOccupants()) {
- sendExistingOccupantToNewOccupant(newOccupant, occupant, room, serverRuntimeContext);
+ for (Occupant existingOccupant : room.getOccupants()) {
+ sendOccupantPresenceToNewOccupant(newOccupant, existingOccupant, room, serverRuntimeContext);
}
// relay presence of the newly added occupant to all existing occupants
- for (Occupant occupant : room.getOccupants()) {
- sendNewOccupantPresenceToExisting(newOccupant, occupant, room, serverRuntimeContext, nickRewritten);
+ for (Occupant existingOccupant : room.getOccupants()) {
+ sendNewOccupantPresenceToExisting(newOccupant, existingOccupant, room, serverRuntimeContext,
+ stanza, nickRewritten);
}
// send discussion history to user
@@ -300,8 +322,8 @@ private Stanza unavailable(PresenceStanza stanza, Entity roomJid, Entity occupan
return null;
}
- private void sendExistingOccupantToNewOccupant(Occupant newOccupant, Occupant existingOccupant, Room room,
- ServerRuntimeContext serverRuntimeContext) {
+ private void sendOccupantPresenceToNewOccupant(Occupant newOccupant, Occupant existingOccupant, Room room,
+ ServerRuntimeContext serverRuntimeContext) {
// <presence
// from='darkcave@chat.shakespeare.lit/firstwitch'
// to='hag66@shakespeare.lit/pda'>
@@ -315,17 +337,21 @@ private void sendExistingOccupantToNewOccupant(Occupant newOccupant, Occupant ex
return;
}
- Entity roomAndOccupantNick = new EntityImpl(room.getJID(), existingOccupant.getNick());
- Stanza presenceToNewOccupant = MUCStanzaBuilder.createPresenceStanza(roomAndOccupantNick, newOccupant.getJid(),
- null, NamespaceURIs.XEP0045_MUC_USER, new MucUserItem(existingOccupant.getAffiliation(),
- existingOccupant.getRole()));
+ final PresenceStanza latestPresence = room.getLatestPresence(existingOccupant.getJid());
+ Entity roomAndOccupantNick = new EntityImpl(room.getJID(), existingOccupant.getNick());
+ final MucUserItem mucUserItem = new MucUserItem(existingOccupant.getAffiliation(), existingOccupant.getRole());
+
+ Stanza presenceToNewOccupant = createPresenceStanzaFromLatest(roomAndOccupantNick, newOccupant.getJid(),
+ null, null, latestPresence, NamespaceURIs.XEP0045_MUC_USER, mucUserItem);
+
logger.debug("Room presence from {} sent to {}", newOccupant, roomAndOccupantNick);
relayStanza(newOccupant.getJid(), presenceToNewOccupant, serverRuntimeContext);
}
private void sendNewOccupantPresenceToExisting(Occupant newOccupant, Occupant existingOccupant, Room room,
- ServerRuntimeContext serverRuntimeContext, boolean nickRewritten) {
+ ServerRuntimeContext serverRuntimeContext,
+ PresenceStanza presence, boolean nickRewritten) {
Entity roomAndNewUserNick = new EntityImpl(room.getJID(), newOccupant.getNick());
List<XMLElement> inner = new ArrayList<XMLElement>();
@@ -350,8 +376,11 @@ private void sendNewOccupantPresenceToExisting(Occupant newOccupant, Occupant ex
Stanza presenceToExisting = MUCStanzaBuilder.createPresenceStanza(roomAndNewUserNick,
existingOccupant.getJid(), null, NamespaceURIs.XEP0045_MUC_USER, inner);
+ Stanza presenceToExistingX = createPresenceStanzaFromLatest(roomAndNewUserNick, existingOccupant.getJid(),
+ null, null, presence, NamespaceURIs.XEP0045_MUC_USER, inner.toArray(new XMLElement[0]));
+
logger.debug("Room presence from {} sent to {}", roomAndNewUserNick, existingOccupant);
- relayStanza(existingOccupant.getJid(), presenceToExisting, serverRuntimeContext);
+ relayStanza(existingOccupant.getJid(), presenceToExistingX, serverRuntimeContext);
}
private void sendChangeNickUnavailable(Occupant changer, String oldNick, Occupant receiver, Room room,
@@ -40,6 +40,7 @@
import org.apache.vysper.xmpp.modules.servicediscovery.management.ItemRequestListener;
import org.apache.vysper.xmpp.modules.servicediscovery.management.ServiceDiscoveryRequestException;
import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.stanza.PresenceStanza;
/**
* A chat room
@@ -64,6 +65,8 @@
// keep in a map to allow for quick access
private Map<Entity, Occupant> occupants = new ConcurrentHashMap<Entity, Occupant>();
+
+ private Map<Entity, PresenceStanza> occupantsLatestPresence = new ConcurrentHashMap<Entity, PresenceStanza>();
public Room(Entity jid, String name, RoomType... types) {
if (jid == null) {
@@ -150,22 +153,31 @@ public Occupant findOccupantByJID(Entity occupantJid) {
public Occupant findOccupantByNick(String nick) {
for (Occupant occupant : getOccupants()) {
- if (occupant.getNick().equals(nick))
- return occupant;
+ if (occupant.getNick().equals(nick)) return occupant;
}
return null;
}
+ public void recordLatestPresence(Entity occupantJid, PresenceStanza presenceStanza) {
+ if (!isInRoom(occupantJid)) return;
+ occupantsLatestPresence.put(occupantJid, presenceStanza);
+ }
+
+ public PresenceStanza getLatestPresence(Entity occupantJid) {
+ final PresenceStanza lastPresence = occupantsLatestPresence.get(occupantJid);
+ if (lastPresence == null || !isInRoom(occupantJid)) return null;
+ return lastPresence;
+ }
+
public Set<Occupant> getModerators() {
return getByRole(Role.Moderator);
}
private Set<Occupant> getByRole(Role role) {
Set<Occupant> matches = new HashSet<Occupant>();
for (Occupant occupant : getOccupants()) {
- if (role.equals(occupant.getRole()))
- matches.add(occupant);
+ if (role.equals(occupant.getRole())) matches.add(occupant);
}
return matches;
}
@@ -180,6 +192,7 @@ public boolean isInRoom(String nick) {
public void removeOccupant(Entity occupantJid) {
occupants.remove(occupantJid);
+ occupantsLatestPresence.remove(occupantJid);
}
public int getOccupantCount() {

0 comments on commit 6a6a0c8

Please sign in to comment.