public void directedPresenceSent(Presence update, JID handlerJID, String jid) {
        if (update.getFrom() == null) {
            return;
        }
        if (localServer.isLocal(update.getFrom())) {
            boolean keepTrack = false;
            String name = update.getFrom().getNode();
            if (name != null && !name.isEmpty()) {
                // Keep track of all directed presences if roster service is disabled
                if (!RosterManager.isRosterServiceEnabled()) {
                    keepTrack = true;
                }
                else {
                    try {
                        Roster roster = rosterManager.getRoster(name);
                        // If the directed presence was sent to an entity that is not in the user's
                        // roster, keep a registry of this so that when the user goes offline we
                        // will be able to send the unavailable presence to the entity
                        RosterItem rosterItem = null;
                        try {
                            rosterItem = roster.getRosterItem(update.getTo());
                        }
                        catch (UserNotFoundException e) {
                            // Ignore
                        }
                        if (rosterItem == null ||
                                RosterItem.SUB_NONE == rosterItem.getSubStatus() ||
                                RosterItem.SUB_TO == rosterItem.getSubStatus()) {
                            keepTrack = true;
                        }
                    }
                    catch (UserNotFoundException e) {
                        Log.warn("Presence being sent from unknown user " + name, e);
                    }
                    catch (PacketException e) {
                        Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
                    }
                }
            }
            else if (update.getFrom().getResource() != null){
                // Keep always track of anonymous users directed presences
                keepTrack = true;
            }
            if (keepTrack) {
                String sender = update.getFrom().toString();
                Lock lock = directedPresencesCache.getLock(sender);
                lock.lock();
                try {
                    ConcurrentLinkedQueue<DirectedPresence> directedPresences = directedPresencesCache.get(sender);
                    if (Presence.Type.unavailable.equals(update.getType())) {
                        if (directedPresences != null) {
                            // It's a directed unavailable presence
                            for (DirectedPresence directedPresence : directedPresences) {
                                if (directedPresence.getHandler().equals(handlerJID)) {
                                    directedPresence.removeReceiver(jid);
                                    if (directedPresence.isEmpty()) {
                                        directedPresences.remove(directedPresence);
                                    }
                                    break;
                                }
                            }
                            if (directedPresences.isEmpty()) {
                                // Remove the user from the registry since the list of directed
                                // presences is empty
                                directedPresencesCache.remove(sender);
                                localDirectedPresences.remove(sender);
                            }
                            else {
                                directedPresencesCache.put(sender, directedPresences);
                                localDirectedPresences.put(sender, directedPresences);
                            }
                        }
                    }
                    else {
                        if (directedPresences == null) {
                            // We are using a set to avoid duplicate jids in case the user
                            // sends several directed presences to the same handler. The Map also
                            // ensures that if the user sends several presences to the same handler
                            // we will have only one entry in the Map
                            directedPresences = new ConcurrentLinkedQueue<>();
                        }
                        // Add the handler to the list of handler that processed the directed
                        // presence sent by the user. This handler will be used to send
                        // the unavailable presence when the user goes offline
                        DirectedPresence affectedDirectedPresence = null;
                        for (DirectedPresence directedPresence : directedPresences) {
                            if (directedPresence.getHandler().equals(handlerJID)) {
                                affectedDirectedPresence = directedPresence;
                                break;
                            }
                        }

                        if (affectedDirectedPresence == null) {
                            affectedDirectedPresence = new DirectedPresence(handlerJID);
                            directedPresences.add(affectedDirectedPresence);
                        }
                        affectedDirectedPresence.addReceiver(jid);

                        directedPresencesCache.put(sender, directedPresences);
                        localDirectedPresences.put(sender, directedPresences);
                    }
                } finally {
                    lock.unlock();
                }
            }
        }
    }
Notification method sent to this handler when a user has sent a directed
presence to an entity. If the sender of the presence is local (to this server)
and the target entity does not belong to the user's roster then update the
registry of sent directed presences by the user.

@param update  the directed Presence sent by the user to an entity.
@param handlerJID the JID of the handler that will receive/handle/process the sent packet.
@param jid     the recipient specified in the packet to handle.
xmppserver/src/main/java/org/jivesoftware/openfire/handler/PresenceUpdateHandler.java