private boolean manageSub(JID target, boolean isSending, Presence presence, Roster roster)
            throws UserAlreadyExistsException, SharedGroupException, IllegalArgumentException
    {
        RosterItem item = null;
        RosterItem.AskType oldAsk;
        RosterItem.SubType oldSub = null;
        RosterItem.RecvType oldRecv;
        Presence.Type type = presence.getType();
        boolean newItem = false;
        try {
            if (roster.isRosterItem(target)) {
                item = roster.getRosterItem(target);
                if (item.isShared()) {
                    throw new SharedGroupException("Target '" + target + "' is on the roster of '" + roster.getUsername() + "' as part of a shared group. As such, its presence subscription status cannot be modified with subscription requests.");
                }
            }
            else {
                if (Presence.Type.unsubscribed == type || Presence.Type.unsubscribe == type ||
                        Presence.Type.subscribed == type) {
                    // Do not create a roster item when processing a confirmation of
                    // an unsubscription or receiving an unsubscription request or a
                    // subscription approval from an unknown user
                    return false;
                }
                if (Presence.Type.subscribe != type) {
                    throw new IllegalArgumentException("manageSub asked to manage non-subscription presence");
                }
                item = roster.createRosterItem(target, false, true);
                newItem = true;
            }

            if (Presence.Type.subscribe == type && !isSending) {
                // For inbound <presence type='subscribe'/>, we should update the stored stanza here.
                item.setStoredSubscribeStanza(presence);
                RosterManager.getRosterItemProvider().updateItem(roster.getUsername(), item);
            }

            // Get a snapshot of the item state
            oldAsk = item.getAskStatus();
            oldSub = item.getSubStatus();
            oldRecv = item.getRecvStatus();
            // Update the item state based in the received presence type
            updateState(item, type, isSending);
            // Update the roster IF the item state has changed
            if (oldAsk != item.getAskStatus() || oldSub != item.getSubStatus() || oldRecv != item.getRecvStatus()) {
                if (oldRecv == RosterItem.RECV_SUBSCRIBE && item.getRecvStatus() != RosterItem.RECV_SUBSCRIBE) {
                    // No longer asking for a subscription. Clean up the original subscription request stanza.
                    item.setStoredSubscribeStanza(null);
                }
                roster.updateRosterItem(item);
            }
            else if (newItem) {
                // Do not push items with a state of "None + Pending In"
                if (item.getSubStatus() != RosterItem.SUB_NONE ||
                        item.getRecvStatus() != RosterItem.RECV_SUBSCRIBE) {
                    roster.broadcast(item, false);
                }
            }
        }
        catch (UserNotFoundException e) {
            // Should be there because we just checked that it's an item
            Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
        }
        return oldSub != item.getSubStatus();
    }
Manage the subscription request. This method updates a user's roster
state, storing any changes made, and updating the roster owner if changes
occurred.

@param target    The roster target's jid (the item's jid to be changed)
@param isSending True if the request is being sent by the owner
@param presence      The subscription stanza
@param roster    The Roster that is updated.
@return {@code true} if the subscription state has changed.
xmppserver/src/main/java/org/jivesoftware/openfire/handler/PresenceSubscribeHandler.java