public void broadcast(final @Nonnull Presence presence, final boolean isJoinPresence)
    {
        Log.debug("Broadcasting presence update in room {} for occupant {}", this.getName(), presence.getFrom() );

        if (!presence.getFrom().asBareJID().equals(this.getJID())) {
            // At this point, the 'from' address of the to-be broadcast stanza can be expected to be the role-address
            // of the subject, or more broadly: it's bare JID representation should match that of the room. If that's not
            // the case then there's a bug in Openfire. Catch this here, as otherwise, privacy-sensitive data is leaked.
            // See: OF-2152
            throw new IllegalArgumentException("Broadcast presence stanza's 'from' JID " + presence.getFrom() + " does not match room JID: " + this.getJID());
        }

        // Three distinct flavors of the presence stanzas can be sent:
        // 1. The original stanza (that includes the real JID of the user), usable when the room is not semi-anon or when the occupant is a moderator.
        // 2. One that does not include the real JID of the user (if the room is semi-anon and the occupant isn't a moderator)
        // 3. One that is reflected to the joining user (this stanza has additional status codes, signalling 'self-presence')
        final Presence nonAnonPresence = presence.createCopy(); // create a copy, as the 'to' will be overwritten when dispatched!
        final Presence anonPresence = createAnonCopy(presence);
        final Presence selfPresence = createSelfPresenceCopy(presence, isJoinPresence);

        for (final MUCOccupant occupant : getOccupants())
        {
            try
            {
                Log.trace("Broadcasting presence update in room {} for occupant {} to occupant {}", this.getName(), presence.getFrom(), occupant );

                // Do not send broadcast presence to occupants hosted in other FMUC nodes.
                if (occupant.isRemoteFmuc()) {
                    Log.trace( "Not sending presence update of '{}' to {}: This occupant is on another FMUC node.", presence.getFrom(), occupant.getUserAddress() );
                    continue;
                }

                // Determine what stanza flavor to send to this occupant.
                final Presence toSend;
                if (occupant.getPresence().getFrom().equals(presence.getTo())) {
                    // This occupant is the subject of the stanza. Send the 'self-presence' stanza.
                    Log.trace( "Sending self-presence of '{}' to {}", presence.getFrom(), occupant.getUserAddress() );
                    toSend = selfPresence;
                } else if ( !canAnyoneDiscoverJID && Role.moderator != occupant.getRole() ) {
                    Log.trace( "Sending anonymized presence of '{}' to {}: The room is semi-anon, and this occupant is not a moderator.", presence.getFrom(), occupant.getUserAddress() );
                    toSend = anonPresence;
                } else {
                    Log.trace( "Sending presence of '{}' to {}", presence.getFrom(), occupant.getUserAddress() );
                    toSend = nonAnonPresence;
                }

                // Send stanza to this occupant.
                occupant.send(toSend);
            }
            catch ( Exception e )
            {
                Log.warn("An unexpected exception prevented a presence update from {} to be broadcast to {}.", presence.getFrom(), occupant.getUserAddress(), e);
            }
        }
    }
Broadcasts the presence stanza as captured by the argument to all occupants that are local to the local domain
(in other words, it excludes occupants that are connected via FMUC).

@param presence The presence stanza
@param isJoinPresence If the presence is sent in the context of joining the room.
xmppserver/src/main/java/org/jivesoftware/openfire/muc/MUCRoom.java