uk.org.retep.xmpp.muc.room.JoinExistingRoomLogic Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2010, Peter T Mount
* All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
*
*
* GNU GENERAL PUBLIC LICENSE - CLASSPATH EXCEPTION
*
*
*
* Linking this library statically or dynamically with other modules
* is making a combined work based on this library. Thus, the terms
* and conditions of the GNU General Public License cover the whole
* combination.
*
*
*
* As a special exception, the copyright holders of this library give
* you permission to link this library with independent modules to
* produce an executable, regardless of the license terms of these
* independent modules, and to copy and distribute the resulting
* executable under terms of your choice, provided that you also meet,
* for each linked independent module, the terms and conditions of the
* license of that module.
*
*
*
* An independent module is a module which is either not derived from or based
* on this library, or a module who's classes extend those within this library
* as part of the implementation of the library.
*
*
*
* If you modify this library, you may extend this exception to your version
* of the library, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
*/
package uk.org.retep.xmpp.muc.room;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import org.jabber.protocol.nick.Nick;
import uk.org.retep.util.collections.CollectionUtils;
import uk.org.retep.util.messaging.MessageException;
import uk.org.retep.xmpp.JID;
import uk.org.retep.xmpp.XMPPException;
import uk.org.retep.xmpp.XMPPServer;
import uk.org.retep.xmpp.logic.AbstractXMPPLogic;
import uk.org.retep.xmpp.logic.XMPPLogic;
import uk.org.retep.xmpp.logic.XMPPProtocolLogic;
import uk.org.retep.xmpp.message.ErrorCondition;
import uk.org.retep.xmpp.message.Presence;
import uk.org.retep.xmpp.muc.MucRoom;
import uk.org.retep.xmpp.muc.MucRoomMember;
import uk.org.retep.xmpp.muc.MucService;
import uk.org.retep.xmpp.muc.beans.BasicMucRoomMember;
import static uk.org.retep.xmpp.XMPPConstants.*;
/**
* XEP-0045 7.1 - Joining a room
*
* This {@link XMPPLogic} is used when a room already exists
*
* @author peter
*/
public class JoinExistingRoomLogic
extends AbstractXMPPLogic
implements XMPPProtocolLogic
{
public static JoinExistingRoomLogic getInstance()
{
return Holder.getInstance();
}
private static final class Holder
{
private static JoinExistingRoomLogic INSTANCE = new JoinExistingRoomLogic();
public static JoinExistingRoomLogic getInstance()
{
return INSTANCE;
}
private Holder()
{
}
}
protected JoinExistingRoomLogic()
{
}
@Override
public Class> getProtocol()
{
return org.jabber.protocol.muc.X.class;
}
@Override
public XMPPLogic process( final XMPPServer server,
final MucService service,
final MucRoom room,
final Presence, ?> presence )
throws MessageException
{
// use presence.getTo() and not mucRoom.getJid() for the room JID
// to reduce cross-cluster locking
final JID chatRoomJid = presence.getTo();
// Who is entering the room
final JID realJid = presence.getFrom();
final MucRoomMember joiningMember = createMucRoomMember( server, service, room, presence, realJid, chatRoomJid );
// The requested nickName and run it through any rewrite policy
final String requestedNickName = joiningMember.getNickname();
final String nickName = service.getAuthenticator().enforceNicknamePolicy( room, chatRoomJid, requestedNickName );
try
{
// This will check for a nickname conflict, room full etc.
//Later reserved nicknames go here as well
final String oldNick = room.add( joiningMember, service.getAuthenticator() );
// XEP-0172 support - if supplied store the persistentNickname in the MucRoomMember
final Nick persistentNickname = CollectionUtils.getInstance( presence.getContent(), Nick.class );
if( persistentNickname != null )
{
// Don't use joiningMember as that may not be the same instance
// in the room (i.e. nickname change)
final MucRoomMember realMember = room.getMember( nickName );
if( realMember == null )
{
// Should not occur unless the member has just left
throw new XMPPException( ErrorCondition.INTERNAL_SERVER_ERROR );
}
else
{
realMember.setPersistentNickname( persistentNickname.getValue() );
}
}
if( oldNick != null )
{
return nicknameChangedBroadcast( server,
service,
room,
chatRoomJid,
joiningMember,
realJid,
requestedNickName,
nickName,
oldNick );
}
else
{
return enteredRoomBroadcast( server,
service,
room,
chatRoomJid,
joiningMember,
realJid,
requestedNickName,
nickName );
}
}
catch( XMPPException xe )
{
final ErrorCondition errorCode = xe.getError();
getLog().error( "%s: XMPPException[%s] - requested \"%s\" using \"%s\"",
chatRoomJid,
errorCode,
requestedNickName,
nickName );
if( errorCode == null )
{
throw xe;
}
else
{
server.send( presence.respondTo().
add( new org.jabber.protocol.muc.X() ).
setType( ERROR ).
setError( errorCode ) );
return null;
}
}
}
/**
* Called to create a {@link MucRoomMember} instance for a user joining a room.
*
*
* The default simply creates a {@link BasicMucRoomMember} instance.
*
*
* @param server {@link XMPPServer}
* @param service {@link MucService} being used
* @param room {@link MucRoom} may be null
* @param presence The received {@link Presence}
* @param realJid The real JID of the person entering the room
* @param chatRoomJid JID of the chat room
* @return MucRoomMember instance for the joining member
* @throws MessageException on failure
*/
protected MucRoomMember createMucRoomMember( @Nonnull final XMPPServer> server,
@Nonnull final MucService service,
@Nonnull final MucRoom room,
@Nonnull final Presence, ?> presence,
@Nonnull final JID realJid,
@Nonnull final JID chatRoomJid )
throws MessageException
{
return new BasicMucRoomMember( chatRoomJid.getResource(), realJid );
}
/**
* Called when a user changes their nickname within a room. It should return an XMPPLogic instance capable of
* broadcasting said change to the room's occupants - the default is an instance of {@link NicknameChangedBroadcast}.
*
* @param server {@link XMPPServer}
* @param service {@link MucService} being used
* @param room {@link MucRoom} may be null
* @param chatRoomJid JID of the chat room
* @param joiningMember The {@link MucRoomMember} of the user
* @param userJid The user's JID
* @param requestedNickName the nickname they requested
* @param nickName the nickname they got
* @param oldNick the original nickname
* @return XMPPLogic to invoke
* @throws MessageException on failure
*/
protected XMPPLogic nicknameChangedBroadcast( @Nonnull final XMPPServer> server,
@Nonnull final MucService service,
@Nullable final MucRoom room,
@Nonnull final JID chatRoomJid,
@Nonnull final MucRoomMember joiningMember,
@Nonnull final JID userJid,
@Nonnull final String requestedNickName,
@Nonnull final String nickName,
@Nonnull final String oldNick )
throws MessageException
{
return new NicknameChangedBroadcast( chatRoomJid,
joiningMember,
userJid,
requestedNickName,
nickName,
oldNick );
}
/**
* Called when a user enters a room. It should return an XMPPLogic instance capable of broadcasting the user
* entering the room. The default is an instance of {@link EnteredRoomBroadcast}.
*
* @param server {@link XMPPServer}
* @param service {@link MucService} being used
* @param room {@link MucRoom} may be null
* @param chatRoomJid JID of the chat room
* @param joiningMember The {@link MucRoomMember} of the user
* @param userJid The user's JID
* @param requestedNickName the nickname they requested
* @param nickName the nickname they got
* @return XMPPLogic to invoke
* @throws MessageException on failure
*/
protected XMPPLogic enteredRoomBroadcast( @Nonnull final XMPPServer> server,
@Nonnull final MucService service,
@Nullable final MucRoom room,
@Nonnull final JID chatRoomJid,
@Nonnull final MucRoomMember joiningMember,
@Nonnull final JID userJid,
@Nonnull final String requestedNickName,
@Nonnull final String nickName )
throws MessageException
{
return new EnteredRoomBroadcast( chatRoomJid, joiningMember, userJid, requestedNickName, nickName );
}
}