private void broadcast(@Nonnull final Message message, final boolean storeMsgInRoomHistory)
    {
        Log.debug("Broadcasting message in room {} for occupant {}", this.getName(), message.getFrom() );

        if (!message.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 sender, 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 message stanza's 'from' JID " + message.getFrom() + " does not match room JID: " + this.getJID());
        }

        // Add message to the room history
        if (storeMsgInRoomHistory) roomHistory.addMessage(message);
        // Send message to occupants connected to this JVM

        // Create a defensive copy of the message that will be broadcast, as the broadcast will modify it ('to' addresses
        // will be changed), and it's undesirable to see these modifications in post-processing (OF-2163).
        final Message mutatingCopy = message.createCopy();
        final Collection<MUCOccupant> occupants = getOccupants();
        for (final MUCOccupant occupant : occupants) {
            try
            {
                // Do not send broadcast messages to deaf occupants or occupants hosted in other FMUC nodes.
                if ( !occupant.isVoiceOnly() && !occupant.isRemoteFmuc() )
                {
                    occupant.send( mutatingCopy );
                }
            }
            catch ( Exception e )
            {
                Log.warn("An unexpected exception prevented a message from {} to be broadcast to {}.", message.getFrom(), occupant.getUserAddress(), e);
            }
        }
        if (isLogEnabled() && storeMsgInRoomHistory) {
            JID senderAddress = getSelfRepresentation().getOccupantJID(); // default to the room being the sender of the message.

            // convert the MUC nickname/role JID back into a real user JID
            if (message.getFrom() != null && message.getFrom().getResource() != null) {
                try {
                    // get the first MUCOccupant for the sender
                    senderAddress = getOccupantsByNickname(message.getFrom().getResource()).get(0).getUserAddress();
                } catch (UserNotFoundException e) {
                    // The room itself is sending the message
                    senderAddress = getSelfRepresentation().getOccupantJID();
                }
            }
            // Log the conversation
            mucService.logConversation(this, message, senderAddress);
        }
        mucService.messageBroadcastedTo(occupants.size());
    }
Broadcasts the message stanza as captured by the argument to all occupants that are local to the domain (in other
words, it excludes occupants that connected via FMUC).

This method also ensures that the broadcast message is logged to persistent storage, if that feature is enabled
for this room

@param message The message stanza
xmppserver/src/main/java/org/jivesoftware/openfire/muc/MUCRoom.java