private void processOccupantMessage(
        @Nonnull final Message packet,
        @Nonnull final MUCRoom room,
        @Nonnull final MUCOccupant preExistingOccupantData )
    {
        // Check and reject conflicting packets with conflicting roles In other words, another user already has this nickname
        if ( !preExistingOccupantData.getUserAddress().equals(packet.getFrom()) )
        {
            Log.debug("Rejecting conflicting stanza with conflicting roles: {}", packet.toXML());
            sendErrorPacket(packet, PacketError.Condition.conflict, "Another user uses this nickname.");
            return;
        }

        if (room.getRoomHistory().isSubjectChangeRequest(packet))
        {
            processChangeSubjectMessage(packet, room, preExistingOccupantData);
            return;
        }

        // An occupant is trying to send a private message, send public message, invite someone to the room or reject an invitation.
        final Message.Type type = packet.getType();
        String nickname = packet.getTo().getResource();
        if ( nickname == null || nickname.trim().isEmpty())
        {
            nickname = null;
        }

        // Public message (not addressed to a specific occupant)
        if ( nickname == null && Message.Type.groupchat == type )
        {
            processPublicMessage(packet, room, preExistingOccupantData);
            return;
        }

        // Private message (addressed to a specific occupant)
        if ( nickname != null && (Message.Type.chat == type || Message.Type.normal == type) )
        {
            processPrivateMessage(packet, room, preExistingOccupantData);
            return;
        }

        if ( nickname == null && Message.Type.normal == type )
        {
            // An occupant could be sending an invitation or declining an invitation
            final Element userInfo = packet.getChildElement("x", "http://jabber.org/protocol/muc#user");

            if ( userInfo != null && userInfo.element("invite") != null )
            {
                // An occupant is sending invitations
                processSendingInvitationMessage(packet, room, preExistingOccupantData);
                return;
            }

            if ( userInfo != null && userInfo.element("decline") != null )
            {
                // An occupant has declined an invitation
                processDecliningInvitationMessage(packet, room);
                return;
            }
        }

        Log.debug("Unable to process message: {}", packet.toXML());
        sendErrorPacket(packet, PacketError.Condition.bad_request, "Unable to process message.");
    }
Processes a Message stanza that was sent by a user that's in the room.

@param packet                  The stanza to process
@param room                    The room that the stanza was addressed to.
@param preExistingOccupantData The occupant data of this user in the addressed room prior to processing of this stanza, if any.
xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl.java