Class OccupantManager
- java.lang.Object
-
- org.jivesoftware.openfire.muc.spi.OccupantManager
-
- All Implemented Interfaces:
MUCEventListener
public class OccupantManager extends Object implements MUCEventListener
Maintains an in-memory inventory of what XMPP entity (user) is in what chatroom, across the entire XMPP cluster. Each instance of this class takes responsibility of maintaining the in-memory representation of occupants of rooms for exactly one instance ofMultiUserChatService
. Some data duplication exists between the data managed by this class, and the data that is managed by the collection of MUCRoom instances that are part of the same MUC service. The MUCRoom managed data is shared across the cluster using a clustered data structure (a clusteredCache
). The content of such caches cannot survive certain events related to changes in the composition of the cluster (the local server joining or leaving the cluster). This introduces problems, as, for example, the occupants that are connected to the local server should see occupants connected to a cluster node that is now unavailable 'leave' the chatroom. This requires the local cluster node to retain knowledge, even after the clustered cache has been reset. This implementation therefore by design makes no use of such clustered caches to exchange data with other cluster nodes. Instead, this implementation relies on cluster tasks to share data between cluster nodes. To minimize data transfer and data duplication, the data managed by this implementation is kept to the bare minimum needed to perform post-cluster event maintenance. Apart from the responsibility of maintaining data for post-cluster event maintenance, this implementation adds some conveniences, that include:- A method (that operates on the maintained data) to determine what room names a particular user is in. As this implementation already maintains this data, obtaining it from this class is more convenient and more performant than obtaining it from the data that is maintained in the clustered data structure (as that is mapped 'by room')
- A 'last activity' timestamp for users on the local node (to be used to detect idle users
- Author:
- Guus der Kinderen, guus.der.kinderen@gmail.com
- See Also:
- OF-2224
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
OccupantManager.Occupant
Representation of a user that is an occupant of a chatroom.
-
Field Summary
Fields Modifier and Type Field Description static SystemProperty<Boolean>
PROPERTY_USE_NONBLOCKING_CLUSTERTASKS
Controls if blocking or non-blocking tasks are used when synchronizing MUC occupant data over an Openfire cluster.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description boolean
exists(OccupantManager.Occupant occupant)
Checks whether the occupant exists.boolean
exists(OccupantManager.Occupant occupant, NodeID exclude)
Checks whether the occupant exists, optionally excluding a specific node from evaluation.Set<OccupantManager.Occupant>
getFederatedOccupants()
Set<OccupantManager.Occupant>
getLocalOccupants()
Returns data that is maintained for occupants of the local cluster node.Map<NodeID,Set<OccupantManager.Occupant>>
getLocalOccupantsByNode()
Map<OccupantManager.Occupant,NodeID>
getNodeByLocalOccupant()
boolean
isForThisService(org.xmpp.packet.JID jid)
Verifies that a JID relates to the service for which this instance is operating, by comparing its domain part.Instant
lastActivityOnLocalNode(org.xmpp.packet.JID userJid)
Returns the most recent activity for a particular user that is assumed to be connected to the local cluster node.Set<OccupantManager.Occupant>
leftCluster()
Removes and returns all data that was maintained for cluster nodes other than the local node.Set<OccupantManager.Occupant>
leftCluster(NodeID nodeID)
Removes and returns all data that was maintained for a particular cluster node.void
messageReceived(org.xmpp.packet.JID roomJID, org.xmpp.packet.JID user, String nickname, org.xmpp.packet.Message message)
Event triggered when a room occupant sent a message to a room.void
nicknameChanged(org.xmpp.packet.JID roomJID, org.xmpp.packet.JID userJID, String oldNickname, String newNickname)
When an XMPP entity / user that is an occupant of a room changes its nickname, this event handler will ensure that the relevant data that is maintained in this instance of OccupantManager, as well as all instances for the same server on every other cluster node, is updated.int
numberOfUniqueUsers()
Counts all users that are in at least one room.void
occupantJoined(org.xmpp.packet.JID roomJID, org.xmpp.packet.JID userJID, String nickname)
When an XMPP entity / user is registered as a new occupant of a room, this event handler will ensure that this instance of OccupantManager, as well as all instances for the same server on every other cluster node, registers the relevant data that is needed to perform post-cluster event maintenance.void
occupantLeft(org.xmpp.packet.JID roomJID, org.xmpp.packet.JID userJID, String nickname)
When an XMPP entity / user is removed as an occupant of a room, this event handler will ensure that this instance of OccupantManager, as well as all instances for the same server on every other cluster node, updates the relevant data that it maintains to perform post-cluster event maintenance.void
occupantNickKicked(org.xmpp.packet.JID roomJID, String nickname)
When an XMPP entity / user is kicked out of a room because of nickname collision, this event handler will ensure that this instance of OccupantManager, as well as all instances for the same server on every other cluster node, updates the relevant data that it maintains to perform post-cluster event maintenance.Set<OccupantManager.Occupant>
occupantsForRoomByNode(String roomName, NodeID nodeID, boolean includeFederated)
Set<OccupantManager.Occupant>
occupantsForRoomExceptForNode(String roomName, NodeID nodeID, boolean includeFederated)
void
privateMessageRecieved(org.xmpp.packet.JID toJID, org.xmpp.packet.JID fromJID, org.xmpp.packet.Message message)
Event triggered when a room occupant sent a private message to another room uservoid
process(OccupantAddedTask task)
Updates the data maintained by this instance to perform post-cluster event maintenance, based on the data from the clustered task.void
process(OccupantKickedForNicknameTask task)
Updates the data maintained by this instance to perform post-cluster event maintenance, based on the data from the clustered task.void
process(OccupantRemovedTask task)
Updates the data maintained by this instance to perform post-cluster event maintenance, based on the data from the clustered task.void
process(OccupantUpdatedTask task)
Updates the data maintained by this instance to perform post-cluster event maintenance, based on the data from the clustered task.void
process(SyncLocalOccupantsAndSendJoinPresenceTask task)
Used by other nodes telling us about all of their occupants.void
registerActivity(org.xmpp.packet.JID userJid)
Registers activity for a particular user that is assumed to be connected to the local cluster node.OccupantAddedTask
registerOccupantJoinedLocally(org.xmpp.packet.JID roomJID, org.xmpp.packet.JID userJID, String nickname)
void
roomCreated(org.xmpp.packet.JID roomJID)
Event triggered when a new room was created.void
roomDestroyed(org.xmpp.packet.JID roomJID)
Event triggered when a room was destroyed.Set<String>
roomNamesForAddress(org.xmpp.packet.JID realJID)
Returns the name of all the rooms that a particular XMPP entity (user) is currently an occupant of.void
roomSubjectChanged(org.xmpp.packet.JID roomJID, org.xmpp.packet.JID user, String newSubject)
Event triggered when the subject of a room is changed.
-
-
-
Field Detail
-
PROPERTY_USE_NONBLOCKING_CLUSTERTASKS
public static final SystemProperty<Boolean> PROPERTY_USE_NONBLOCKING_CLUSTERTASKS
Controls if blocking or non-blocking tasks are used when synchronizing MUC occupant data over an Openfire cluster.
-
-
Method Detail
-
isForThisService
public boolean isForThisService(@Nonnull org.xmpp.packet.JID jid)
Verifies that a JID relates to the service for which this instance is operating, by comparing its domain part.- Parameters:
jid
- The JID to check- Returns:
- True if the JID relates to the service, otherwise false.
-
occupantJoined
public void occupantJoined(@Nonnull org.xmpp.packet.JID roomJID, @Nonnull org.xmpp.packet.JID userJID, @Nonnull String nickname)
When an XMPP entity / user is registered as a new occupant of a room, this event handler will ensure that this instance of OccupantManager, as well as all instances for the same server on every other cluster node, registers the relevant data that is needed to perform post-cluster event maintenance.- Specified by:
occupantJoined
in interfaceMUCEventListener
- Parameters:
roomJID
- the JID of the room where the occupant has joined.userJID
- The 'real' JID (not room-at-service-slash-nickname) of the XMPP user that joined.nickname
- nickname of the user in the room.
-
registerOccupantJoinedLocally
@Nonnull public OccupantAddedTask registerOccupantJoinedLocally(@Nonnull org.xmpp.packet.JID roomJID, @Nonnull org.xmpp.packet.JID userJID, @Nonnull String nickname)
-
nicknameChanged
public void nicknameChanged(@Nonnull org.xmpp.packet.JID roomJID, @Nonnull org.xmpp.packet.JID userJID, @Nonnull String oldNickname, @Nonnull String newNickname)
When an XMPP entity / user that is an occupant of a room changes its nickname, this event handler will ensure that the relevant data that is maintained in this instance of OccupantManager, as well as all instances for the same server on every other cluster node, is updated.- Specified by:
nicknameChanged
in interfaceMUCEventListener
- Parameters:
roomJID
- the JID of the room where the occupant has joined.userJID
- The 'real' JID (not room-at-service-slash-nickname) of the XMPP user that joined.oldNickname
- nickname of the user in the room prior to the change.newNickname
- nickname of the user in the room after the change.
-
occupantLeft
public void occupantLeft(org.xmpp.packet.JID roomJID, org.xmpp.packet.JID userJID, String nickname)
When an XMPP entity / user is removed as an occupant of a room, this event handler will ensure that this instance of OccupantManager, as well as all instances for the same server on every other cluster node, updates the relevant data that it maintains to perform post-cluster event maintenance.- Specified by:
occupantLeft
in interfaceMUCEventListener
- Parameters:
roomJID
- the JID of the room where the occupant has left.userJID
- The 'real' JID (not room-at-service-slash-nickname) of the XMPP user that left.nickname
- nickname that the user used in the room.
-
occupantNickKicked
public void occupantNickKicked(org.xmpp.packet.JID roomJID, String nickname)
When an XMPP entity / user is kicked out of a room because of nickname collision, this event handler will ensure that this instance of OccupantManager, as well as all instances for the same server on every other cluster node, updates the relevant data that it maintains to perform post-cluster event maintenance.- Specified by:
occupantNickKicked
in interfaceMUCEventListener
- Parameters:
roomJID
- the JID of the room where the occupant is kicked out.nickname
- nickname that the user used in the room.
-
process
public void process(@Nonnull OccupantAddedTask task)
Updates the data maintained by this instance to perform post-cluster event maintenance, based on the data from the clustered task.- Parameters:
task
- Cluster task that informs of a new occupant
-
process
public void process(@Nonnull OccupantUpdatedTask task)
Updates the data maintained by this instance to perform post-cluster event maintenance, based on the data from the clustered task.- Parameters:
task
- Cluster task that informs of an update for an existing occupant
-
process
public void process(@Nonnull OccupantRemovedTask task)
Updates the data maintained by this instance to perform post-cluster event maintenance, based on the data from the clustered task.- Parameters:
task
- Cluster task that informs of a removed occupant
-
process
public void process(@Nonnull OccupantKickedForNicknameTask task)
Updates the data maintained by this instance to perform post-cluster event maintenance, based on the data from the clustered task.- Parameters:
task
- Cluster task that informs of an occupant nickname that has been kicked out of a room
-
process
public void process(@Nonnull SyncLocalOccupantsAndSendJoinPresenceTask task)
Used by other nodes telling us about all of their occupants.- Parameters:
task
- Cluster task that informs of occupants on a remote node.
-
roomNamesForAddress
@Nonnull public Set<String> roomNamesForAddress(@Nonnull org.xmpp.packet.JID realJID)
Returns the name of all the rooms that a particular XMPP entity (user) is currently an occupant of.- Parameters:
realJID
- The XMPP address of a user- Returns:
- All room names that have the user as an occupant.
-
getLocalOccupants
@Nonnull public Set<OccupantManager.Occupant> getLocalOccupants()
Returns data that is maintained for occupants of the local cluster node. The returned occupants include occupants that are local to the XMPP domain as well as federated users.- Returns:
- all data maintained for the local cluster node.
-
registerActivity
public void registerActivity(@Nonnull org.xmpp.packet.JID userJid)
Registers activity for a particular user that is assumed to be connected to the local cluster node. This records a timestamp, that can be used to detect idle-ness.- Parameters:
userJid
- The address of the user for which to record activity.
-
lastActivityOnLocalNode
@Nullable public Instant lastActivityOnLocalNode(@Nonnull org.xmpp.packet.JID userJid)
Returns the most recent activity for a particular user that is assumed to be connected to the local cluster node. This returns a timestamp, that can be used to detect idle-ness.- Parameters:
userJid
- The address of the user for which to return a timestamp of last activity.- Returns:
- A timestamp, or null when there currently is no occupant by that JID on the local node.
-
numberOfUniqueUsers
public int numberOfUniqueUsers()
Counts all users that are in at least one room.- Returns:
- a user count
-
exists
public boolean exists(@Nonnull OccupantManager.Occupant occupant, @Nullable NodeID exclude)
Checks whether the occupant exists, optionally excluding a specific node from evaluation.- Parameters:
occupant
- The subject of the existence checkexclude
- An optional node to exclude from the check- Returns:
- True if the occupant was found, otherwise false.
-
exists
public boolean exists(@Nonnull OccupantManager.Occupant occupant)
Checks whether the occupant exists.- Parameters:
occupant
- The subject of the existence check- Returns:
- True if the occupant was found, otherwise false.
-
occupantsForRoomByNode
@Nonnull public Set<OccupantManager.Occupant> occupantsForRoomByNode(@Nonnull String roomName, @Nonnull NodeID nodeID, boolean includeFederated)
-
occupantsForRoomExceptForNode
@Nonnull public Set<OccupantManager.Occupant> occupantsForRoomExceptForNode(@Nonnull String roomName, @Nonnull NodeID nodeID, boolean includeFederated)
-
leftCluster
@Nonnull public Set<OccupantManager.Occupant> leftCluster(@Nonnull NodeID nodeID)
Removes and returns all data that was maintained for a particular cluster node. It is assumed that this method is used in reaction to that cluster node having left the cluster.- Parameters:
nodeID
- Identifier of the cluster node that left.- Returns:
- All data that this instance maintained for the cluster node.
-
leftCluster
@Nullable public Set<OccupantManager.Occupant> leftCluster()
Removes and returns all data that was maintained for cluster nodes other than the local node. It is assumed that this method is used in reaction to the local cluster node having left the cluster.- Returns:
- All data that this instance maintained for all cluster nodes except the local one.
-
getLocalOccupantsByNode
@Nonnull public Map<NodeID,Set<OccupantManager.Occupant>> getLocalOccupantsByNode()
-
getFederatedOccupants
public Set<OccupantManager.Occupant> getFederatedOccupants()
-
getNodeByLocalOccupant
@Nonnull public Map<OccupantManager.Occupant,NodeID> getNodeByLocalOccupant()
-
roomCreated
public void roomCreated(org.xmpp.packet.JID roomJID)
Description copied from interface:MUCEventListener
Event triggered when a new room was created.- Specified by:
roomCreated
in interfaceMUCEventListener
- Parameters:
roomJID
- JID of the room that was created.
-
roomDestroyed
public void roomDestroyed(@Nonnull org.xmpp.packet.JID roomJID)
Description copied from interface:MUCEventListener
Event triggered when a room was destroyed.- Specified by:
roomDestroyed
in interfaceMUCEventListener
- Parameters:
roomJID
- JID of the room that was destroyed.
-
messageReceived
public void messageReceived(org.xmpp.packet.JID roomJID, org.xmpp.packet.JID user, String nickname, org.xmpp.packet.Message message)
Description copied from interface:MUCEventListener
Event triggered when a room occupant sent a message to a room.- Specified by:
messageReceived
in interfaceMUCEventListener
- Parameters:
roomJID
- the JID of the room that received the message.user
- the JID of the user that sent the message.nickname
- nickname used by the user when sending the message.message
- the message sent by the room occupant.
-
privateMessageRecieved
public void privateMessageRecieved(org.xmpp.packet.JID toJID, org.xmpp.packet.JID fromJID, org.xmpp.packet.Message message)
Description copied from interface:MUCEventListener
Event triggered when a room occupant sent a private message to another room user- Specified by:
privateMessageRecieved
in interfaceMUCEventListener
- Parameters:
toJID
- the JID of who the message is to.fromJID
- the JID of who the message came from.message
- the message sent to user.
-
roomSubjectChanged
public void roomSubjectChanged(org.xmpp.packet.JID roomJID, org.xmpp.packet.JID user, String newSubject)
Description copied from interface:MUCEventListener
Event triggered when the subject of a room is changed.- Specified by:
roomSubjectChanged
in interfaceMUCEventListener
- Parameters:
roomJID
- the JID of the room that had its subject changed.user
- the JID of the user that changed the subject.newSubject
- new room subject.
-
-