Class 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 of MultiUserChatService. 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 clustered Cache). 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.
    • 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> getLocalOccupants()
      Returns data that is maintained for occupants of the local cluster node.
      Map<OccupantManager.Occupant,​Set<NodeID>> getNodesByOccupant()  
      Map<NodeID,​Set<OccupantManager.Occupant>> getOccupantsByNode()  
      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)  
      Set<OccupantManager.Occupant> occupantsForRoomExceptForNode​(String roomName, NodeID nodeID)  
      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 user
      void 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 interface MUCEventListener
        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 interface MUCEventListener
        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 interface MUCEventListener
        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 interface MUCEventListener
        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.
        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 check
        exclude - 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.
      • 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.
      • 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 interface MUCEventListener
        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 interface MUCEventListener
        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 interface MUCEventListener
        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 interface MUCEventListener
        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 interface MUCEventListener
        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.