/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.impl.gui.main.chat.conference;
import java.util.*;
import java.util.concurrent.*;
import javax.swing.*;
import javax.swing.SwingWorker;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.main.chat.*;
import net.java.sip.communicator.impl.gui.main.chat.history.*;
import net.java.sip.communicator.impl.gui.main.chatroomslist.*;
import net.java.sip.communicator.plugin.desktoputil.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.muc.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.service.protocol.globalstatus.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.Logger;
import org.jitsi.util.*;
import org.osgi.framework.*;
/**
* The <tt>ConferenceChatManager</tt> is the one that manages both chat room and
* ad-hoc chat rooms invitations.
*
* @author Yana Stamcheva
* @author Lubomir Marinov
* @author Valentin Martinet
* @author Hristo Terezov
*/
public class ConferenceChatManager
implements ChatRoomMessageListener,
ChatRoomInvitationListener,
ChatRoomInvitationRejectionListener,
AdHocChatRoomMessageListener,
AdHocChatRoomInvitationListener,
AdHocChatRoomInvitationRejectionListener,
LocalUserChatRoomPresenceListener,
LocalUserAdHocChatRoomPresenceListener,
ServiceListener, ChatRoomLocalUserRoleListener
{
/**
* The object used for logging.
*/
private static final Logger logger
= Logger.getLogger(ConferenceChatManager.class);
/**
* Maps each history window to a <tt>ChatRoomWrapper</tt>.
*/
private final Hashtable<ChatRoomWrapper, HistoryWindow> chatRoomHistory =
new Hashtable<ChatRoomWrapper, HistoryWindow>();
/**
* The list of ad-hoc chat rooms.
*/
private final AdHocChatRoomList adHocChatRoomList = new AdHocChatRoomList();
/**
* A list of all <tt>AdHocChatRoomListChangeListener</tt>-s.
*/
private final Vector<AdHocChatRoomListChangeListener>
adHoclistChangeListeners = new Vector<AdHocChatRoomListChangeListener>();
/**
* Creates an instance of <tt>ConferenceChatManager</tt>.
*/
public ConferenceChatManager()
{
// Loads the chat rooms list in a separate thread.
new Thread()
{
@Override
public void run()
{
adHocChatRoomList.loadList();
}
}.start();
GuiActivator.bundleContext.addServiceListener(this);
}
/**
* Returns all chat room providers currently contained in the ad-hoc chat
* room list.
*
* @return all chat room providers currently contained in the ad-hoc chat
* room list.
*/
public AdHocChatRoomList getAdHocChatRoomList()
{
return adHocChatRoomList;
}
/**
* Handles <tt>ChatRoomInvitationReceivedEvent</tt>-s.
*/
public void invitationReceived(ChatRoomInvitationReceivedEvent evt)
{
InvitationReceivedDialog dialog
= new InvitationReceivedDialog(
this,
evt.getSourceOperationSet(),
evt.getInvitation());
dialog.setVisible(true);
}
public void invitationRejected(ChatRoomInvitationRejectedEvent evt) {}
/**
* Implements the <tt>ChatRoomMessageListener.messageDelivered</tt> method.
* <br>
* Shows the message in the conversation area and clears the write message
* area.
* @param evt the <tt>ChatRoomMessageDeliveredEvent</tt> that notified us
* that the message was delivered to its destination
*/
public void messageDelivered(ChatRoomMessageDeliveredEvent evt)
{
ChatRoom sourceChatRoom = (ChatRoom) evt.getSource();
if (logger.isTraceEnabled())
logger.trace(
"MESSAGE DELIVERED to chat room: " + sourceChatRoom.getName());
ChatPanel chatPanel = GuiActivator.getUIService().getChatWindowManager()
.getMultiChat(sourceChatRoom, false);
if(chatPanel != null)
{
String messageType;
switch (evt.getEventType())
{
case ChatRoomMessageDeliveredEvent.CONVERSATION_MESSAGE_DELIVERED:
messageType = Chat.OUTGOING_MESSAGE;
break;
case ChatRoomMessageDeliveredEvent.ACTION_MESSAGE_DELIVERED:
messageType = Chat.ACTION_MESSAGE;
break;
default:
messageType = null;
break;
}
Message msg = evt.getMessage();
chatPanel.addMessage(
sourceChatRoom.getUserNickname(),
null,
evt.getTimestamp(),
messageType,
msg.getContent(),
msg.getContentType(),
msg.getMessageUID(),
null);
}
}
/**
* Implements the <tt>ChatRoomMessageListener.messageReceived</tt> method.
* <br>
* Obtains the corresponding <tt>ChatPanel</tt> and process the message
* there.
* @param evt the <tt>ChatRoomMessageReceivedEvent</tt> that notified us
* that a message has been received
*/
public void messageReceived(ChatRoomMessageReceivedEvent evt)
{
ChatRoom sourceChatRoom = evt.getSourceChatRoom();
ChatRoomMember sourceMember = evt.getSourceChatRoomMember();
String messageType = null;
switch (evt.getEventType())
{
case ChatRoomMessageReceivedEvent.CONVERSATION_MESSAGE_RECEIVED:
messageType = Chat.INCOMING_MESSAGE;
break;
case ChatRoomMessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED:
messageType = Chat.SYSTEM_MESSAGE;
break;
case ChatRoomMessageReceivedEvent.ACTION_MESSAGE_RECEIVED:
messageType = Chat.ACTION_MESSAGE;
break;
}
if (logger.isTraceEnabled())
logger.trace("MESSAGE RECEIVED from contact: "
+ sourceMember.getContactAddress());
Message message = evt.getMessage();
ChatPanel chatPanel = null;
ChatWindowManager chatWindowManager
= GuiActivator.getUIService().getChatWindowManager();
boolean createWindow = false;
String autoOpenConfig
= MUCService.getChatRoomAutoOpenOption(
sourceChatRoom.getParentProvider(),
sourceChatRoom.getIdentifier());
if(autoOpenConfig == null)
autoOpenConfig = MUCService.DEFAULT_AUTO_OPEN_BEHAVIOUR;
if(autoOpenConfig.equals(MUCService.OPEN_ON_ACTIVITY)
|| (autoOpenConfig.equals(MUCService.OPEN_ON_MESSAGE)
&& !evt.isHistoryMessage())
|| evt.isImportantMessage())
createWindow = true;
if(sourceChatRoom.isSystem())
{
ChatRoomProviderWrapper serverWrapper
= GuiActivator.getMUCService().findServerWrapperFromProvider(
sourceChatRoom.getParentProvider());
chatPanel = chatWindowManager.getMultiChat(
serverWrapper.getSystemRoomWrapper(), createWindow);
}
else
{
chatPanel = chatWindowManager.getMultiChat(
sourceChatRoom, createWindow, message.getMessageUID());
}
if(chatPanel == null)
return;
String messageContent = message.getContent();
if (evt.isHistoryMessage())
{
Date timeStamp = chatPanel.getChatConversationPanel()
.getLastIncomingMsgTimestamp();
Collection<Object> c =
chatPanel.getChatSession().getHistoryBeforeDate(
new Date(
timeStamp.equals(new Date(0))
? System.currentTimeMillis() - 10000
: timeStamp.getTime()
), 20);
if (c.size() > 0)
{
boolean isPresent = false;
for (Object o : c)
{
if (o instanceof ChatRoomMessageDeliveredEvent)
{
ChatRoomMessageDeliveredEvent ev =
(ChatRoomMessageDeliveredEvent) o;
if (evt.getTimestamp() != null
&& evt.getTimestamp().equals(ev.getTimestamp()))
{
isPresent = true;
break;
}
}
else if(o instanceof ChatRoomMessageReceivedEvent)
{
ChatRoomMessageReceivedEvent ev =
(ChatRoomMessageReceivedEvent) o;
if (evt.getTimestamp() != null
&& evt.getTimestamp().equals(ev.getTimestamp()))
{
isPresent = true;
break;
}
}
Message m2 = evt.getMessage();
if(m2 != null
&& m2.getContent().equals(messageContent))
{
isPresent = true;
break;
}
}
if (isPresent)
return;
}
}
chatPanel.addMessage(
sourceMember.getName(),
null,
evt.getTimestamp(),
messageType,
messageContent,
message.getContentType(),
message.getMessageUID(),
null);
if(createWindow)
chatWindowManager.openChat(chatPanel, false);
}
/**
* Implements the <tt>ChatRoomMessageListener.messageDeliveryFailed</tt>
* method.
* <br>
* In the conversation area shows an error message, explaining the problem.
* @param evt the <tt>ChatRoomMessageDeliveryFailedEvent</tt> that notified
* us of a delivery failure
*/
public void messageDeliveryFailed(ChatRoomMessageDeliveryFailedEvent evt)
{
ChatRoom sourceChatRoom = evt.getSourceChatRoom();
String errorMsg = null;
/*
* FIXME ChatRoomMessageDeliveryFailedEvent#getSource() is not a Message
* instance at the time of this writing and the attempt "(Message)
* evt.getSource()" seems to be to get the message which failed to be
* delivered. I'm not sure it's
* ChatRoomMessageDeliveryFailedEvent#getMessage() but since it's the
* only message I can get out of ChatRoomMessageDeliveryFailedEvent, I'm
* using it.
*/
Message sourceMessage = evt.getMessage();
ChatRoomMember destMember = evt.getDestinationChatRoomMember();
if (evt.getErrorCode()
== MessageDeliveryFailedEvent.OFFLINE_MESSAGES_NOT_SUPPORTED)
{
errorMsg = GuiActivator.getResources().getI18NString(
"service.gui.MSG_DELIVERY_NOT_SUPPORTED",
new String[]{destMember.getName()});
}
else if (evt.getErrorCode()
== MessageDeliveryFailedEvent.NETWORK_FAILURE)
{
errorMsg = GuiActivator.getResources()
.getI18NString("service.gui.MSG_NOT_DELIVERED");
}
else if (evt.getErrorCode()
== MessageDeliveryFailedEvent.PROVIDER_NOT_REGISTERED)
{
errorMsg = GuiActivator.getResources().getI18NString(
"service.gui.MSG_SEND_CONNECTION_PROBLEM");
}
else if (evt.getErrorCode()
== MessageDeliveryFailedEvent.INTERNAL_ERROR)
{
errorMsg = GuiActivator.getResources().getI18NString(
"service.gui.MSG_DELIVERY_INTERNAL_ERROR");
}
else if (evt.getErrorCode()
== ChatRoomMessageDeliveryFailedEvent.FORBIDDEN)
{
errorMsg = GuiActivator.getResources().getI18NString(
"service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN");
}
else if (evt.getErrorCode()
== ChatRoomMessageDeliveryFailedEvent.UNSUPPORTED_OPERATION)
{
errorMsg =
GuiActivator.getResources().getI18NString(
"service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION");
}
else
{
errorMsg = GuiActivator.getResources().getI18NString(
"service.gui.MSG_DELIVERY_UNKNOWN_ERROR");
}
String reason = evt.getReason();
if (reason != null)
errorMsg += " " + GuiActivator.getResources().getI18NString(
"service.gui.ERROR_WAS",
new String[]{reason});
ChatWindowManager chatWindowManager
= GuiActivator.getUIService().getChatWindowManager();
ChatPanel chatPanel
= chatWindowManager.getMultiChat(sourceChatRoom, true);
chatPanel.addMessage(
destMember != null ? destMember.getName()
: sourceChatRoom.getName(),
new Date(),
Chat.OUTGOING_MESSAGE,
sourceMessage.getContent(),
sourceMessage.getContentType());
chatPanel.addErrorMessage(
destMember != null ? destMember.getName()
: sourceChatRoom.getName(),
errorMsg);
chatWindowManager.openChat(chatPanel, false);
}
/**
* Implements the
* <tt>LocalUserAdHocChatRoomPresenceListener.localUserPresenceChanged</tt>
* method
*
* @param evt the <tt>LocalUserAdHocChatRoomPresenceChangeEvent</tt> that
* notified us of a presence change
*/
public void localUserAdHocPresenceChanged(
LocalUserAdHocChatRoomPresenceChangeEvent evt)
{
AdHocChatRoom sourceAdHocChatRoom = evt.getAdHocChatRoom();
AdHocChatRoomWrapper adHocChatRoomWrapper
= adHocChatRoomList
.findChatRoomWrapperFromAdHocChatRoom(sourceAdHocChatRoom);
String eventType = evt.getEventType();
if (LocalUserAdHocChatRoomPresenceChangeEvent
.LOCAL_USER_JOINED.equals(eventType))
{
if(adHocChatRoomWrapper != null)
{
this.fireAdHocChatRoomListChangedEvent(
adHocChatRoomWrapper,
AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_CHANGED);
ChatWindowManager chatWindowManager
= GuiActivator.getUIService().getChatWindowManager();
ChatPanel chatPanel
= chatWindowManager
.getMultiChat(adHocChatRoomWrapper, true);
// Check if we have already opened a chat window for this chat
// wrapper and load the real chat room corresponding to the
// wrapper.
if(chatPanel.isShown())
((AdHocConferenceChatSession) chatPanel.getChatSession())
.loadChatRoom(sourceAdHocChatRoom);
else
chatWindowManager.openChat(chatPanel, true);
}
sourceAdHocChatRoom.addMessageListener(this);
}
else if (evt.getEventType().equals(
LocalUserAdHocChatRoomPresenceChangeEvent.LOCAL_USER_JOIN_FAILED))
{
GuiActivator.getAlertUIService().showAlertPopup(
GuiActivator.getResources().getI18NString("service.gui.ERROR"),
GuiActivator.getResources().getI18NString(
"service.gui.FAILED_TO_JOIN_CHAT_ROOM",
new String[]{sourceAdHocChatRoom.getName()})
+ evt.getReason());
}
else if (LocalUserAdHocChatRoomPresenceChangeEvent
.LOCAL_USER_LEFT.equals(eventType)
|| LocalUserAdHocChatRoomPresenceChangeEvent
.LOCAL_USER_DROPPED.equals(eventType))
{
this.closeAdHocChatRoom(adHocChatRoomWrapper);
// Need to refresh the chat room's list in order to change
// the state of the chat room to offline.
fireAdHocChatRoomListChangedEvent(
adHocChatRoomWrapper,
AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_CHANGED);
sourceAdHocChatRoom.removeMessageListener(this);
}
}
/**
* Implements the
* <tt>LocalUserChatRoomPresenceListener.localUserPresenceChanged</tt>
* method.
* @param evt the <tt>LocalUserChatRoomPresenceChangeEvent</tt> that
* notified us
*/
public void localUserPresenceChanged(
final LocalUserChatRoomPresenceChangeEvent evt)
{
if(!SwingUtilities.isEventDispatchThread())
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
localUserPresenceChanged(evt);
}
});
return;
}
ChatRoom sourceChatRoom = evt.getChatRoom();
ChatRoomWrapper chatRoomWrapper
= GuiActivator.getMUCService().findChatRoomWrapperFromChatRoom(
sourceChatRoom);
String eventType = evt.getEventType();
if (LocalUserChatRoomPresenceChangeEvent
.LOCAL_USER_JOINED.equals(eventType))
{
if(chatRoomWrapper != null)
{
GuiActivator.getMUCService().fireChatRoomListChangedEvent(
chatRoomWrapper,
ChatRoomListChangeEvent.CHAT_ROOM_CHANGED);
boolean createWindow = false;
String autoOpenConfig
= MUCService.getChatRoomAutoOpenOption(
sourceChatRoom.getParentProvider(),
sourceChatRoom.getIdentifier());
if(autoOpenConfig != null
&& autoOpenConfig.equals(MUCService.OPEN_ON_ACTIVITY))
createWindow = true;
ChatWindowManager chatWindowManager
= GuiActivator.getUIService().getChatWindowManager();
ChatPanel chatPanel
= chatWindowManager.getMultiChat(
chatRoomWrapper, createWindow);
if(chatPanel != null)
{
chatPanel.setChatIcon(
chatPanel.getChatSession().getChatStatusIcon());
// Check if we have already opened a chat window for this chat
// wrapper and load the real chat room corresponding to the
// wrapper.
if(chatPanel.isShown())
{
((ConferenceChatSession) chatPanel.getChatSession())
.loadChatRoom(sourceChatRoom);
}
else
{
chatWindowManager.openChat(chatPanel, true);
}
}
}
if (sourceChatRoom.isSystem())
{
ChatRoomProviderWrapper serverWrapper
= GuiActivator.getMUCService()
.findServerWrapperFromProvider(
sourceChatRoom.getParentProvider());
serverWrapper.setSystemRoom(sourceChatRoom);
}
sourceChatRoom.addMessageListener(this);
sourceChatRoom.addLocalUserRoleListener(this);
}
else if (LocalUserChatRoomPresenceChangeEvent
.LOCAL_USER_JOIN_FAILED.equals(eventType))
{
GuiActivator.getAlertUIService().showAlertPopup(
GuiActivator.getResources().getI18NString("service.gui.ERROR"),
GuiActivator.getResources().getI18NString(
"service.gui.FAILED_TO_JOIN_CHAT_ROOM",
new String[]{sourceChatRoom.getName()})
+ evt.getReason());
}
else if (LocalUserChatRoomPresenceChangeEvent
.LOCAL_USER_LEFT.equals(eventType)
|| LocalUserChatRoomPresenceChangeEvent
.LOCAL_USER_KICKED.equals(eventType)
|| LocalUserChatRoomPresenceChangeEvent
.LOCAL_USER_DROPPED.equals(eventType))
{
if(chatRoomWrapper != null)
{
if(StringUtils.isNullOrEmpty(evt.getReason()))
{
GuiActivator.getUIService()
.closeChatRoomWindow(chatRoomWrapper);
}
else
{
// send some system messages informing for the
// reason of leaving
ChatWindowManager chatWindowManager
= GuiActivator.getUIService().getChatWindowManager();
ChatPanel chatPanel = chatWindowManager.getMultiChat(
sourceChatRoom, false);
if(chatPanel != null)
{
chatPanel.addMessage(
sourceChatRoom.getName(),
null,
new Date(),
Chat.SYSTEM_MESSAGE,
evt.getReason(),
OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE,
null,
null);
// print and the alternate address
if(!StringUtils.isNullOrEmpty(
evt.getAlternateAddress()))
{
chatPanel.addMessage(
sourceChatRoom.getName(),
null,
new Date(),
Chat.SYSTEM_MESSAGE,
GuiActivator.getResources().getI18NString(
"service.gui.CHAT_ROOM_ALTERNATE_ADDRESS",
new String[]{evt.getAlternateAddress()}),
OperationSetBasicInstantMessaging
.DEFAULT_MIME_TYPE,
null,
null);
}
}
}
// Need to refresh the chat room's list in order to change
// the state of the chat room to offline.
GuiActivator.getMUCService().fireChatRoomListChangedEvent(
chatRoomWrapper,
ChatRoomListChangeEvent.CHAT_ROOM_CHANGED);
}
sourceChatRoom.removeMessageListener(this);
sourceChatRoom.removelocalUserRoleListener(this);
}
}
/**
* Called to accept an incoming invitation. Adds the invitation chat room
* to the list of chat rooms and joins it.
*
* @param invitation the invitation to accept
* @param multiUserChatOpSet the operation set for chat conferencing
* @throws OperationFailedException if the accept fails
*/
public void acceptInvitation(
AdHocChatRoomInvitation invitation,
OperationSetAdHocMultiUserChat multiUserChatOpSet)
throws OperationFailedException
{
AdHocChatRoom chatRoom = invitation.getTargetAdHocChatRoom();
chatRoom.join();
}
/**
* Rejects the given invitation with the specified reason.
*
* @param multiUserChatAdHocOpSet the operation set to use for rejecting the
* invitation
* @param invitation the invitation to reject
* @param reason the reason for the rejection
*/
public void rejectInvitation(
OperationSetAdHocMultiUserChat multiUserChatAdHocOpSet,
AdHocChatRoomInvitation invitation,
String reason)
{
multiUserChatAdHocOpSet.rejectInvitation(invitation, reason);
}
/**
* Creates an ad-hoc chat room, by specifying the ad-hoc chat room name, the
* parent protocol provider and eventually, the contacts invited to
* participate in this ad-hoc chat room.
*
* @param protocolProvider the parent protocol provider.
* @param contacts the contacts invited when creating the chat room.
* @param reason the reason for this invitation
* @return the <tt>AdHocChatRoomWrapper</tt> corresponding to the created
* ad hoc chat room
*/
public AdHocChatRoomWrapper createAdHocChatRoom(
ProtocolProviderService protocolProvider,
Collection<String> contacts,
String reason)
{
AdHocChatRoomWrapper chatRoomWrapper = null;
OperationSetAdHocMultiUserChat groupChatOpSet
= protocolProvider
.getOperationSet(OperationSetAdHocMultiUserChat.class);
// If there's no group chat operation set we have nothing to do here.
if (groupChatOpSet == null)
return null;
AdHocChatRoom chatRoom = null;
try
{
java.util.List<String> members = new LinkedList<String>();
for(String address : contacts)
members.add(address);
chatRoom = groupChatOpSet.createAdHocChatRoom(
"chatroom-" + new Date().getTime(), members, reason);
}
catch (OperationFailedException ex)
{
new ErrorDialog(
GuiActivator.getUIService().getMainFrame(),
GuiActivator.getResources().getI18NString("service.gui.ERROR"),
GuiActivator.getResources().getI18NString(
"service.gui.CREATE_CHAT_ROOM_ERROR",
new String[]{protocolProvider.getProtocolDisplayName()}),
ex)
.showDialog();
}
catch (OperationNotSupportedException ex)
{
new ErrorDialog(
GuiActivator.getUIService().getMainFrame(),
GuiActivator.getResources().getI18NString("service.gui.ERROR"),
GuiActivator.getResources().getI18NString(
"service.gui.CREATE_CHAT_ROOM_ERROR",
new String[]{protocolProvider.getProtocolDisplayName()}),
ex)
.showDialog();
}
if(chatRoom != null)
{
AdHocChatRoomProviderWrapper parentProvider
= adHocChatRoomList.findServerWrapperFromProvider(
protocolProvider);
chatRoomWrapper = new AdHocChatRoomWrapper(
parentProvider, chatRoom);
parentProvider.addAdHocChatRoom(chatRoomWrapper);
adHocChatRoomList.addAdHocChatRoom(chatRoomWrapper);
fireAdHocChatRoomListChangedEvent(
chatRoomWrapper,
AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_ADDED);
}
return chatRoomWrapper;
}
/**
* Joins the given ad-hoc chat room
*
* @param chatRoomWrapper
*/
public void joinChatRoom(AdHocChatRoomWrapper chatRoomWrapper)
{
AdHocChatRoom chatRoom = chatRoomWrapper.getAdHocChatRoom();
if(chatRoom == null)
{
new ErrorDialog(
GuiActivator.getUIService().getMainFrame(),
GuiActivator.getResources().getI18NString("service.gui.WARNING"),
GuiActivator.getResources().getI18NString(
"service.gui.CHAT_ROOM_NOT_CONNECTED",
new String[]{chatRoomWrapper.getAdHocChatRoomName()}))
.showDialog();
return;
}
new JoinAdHocChatRoomTask(chatRoomWrapper).execute();
}
/**
* Removes the given chat room from the UI.
*
* @param chatRoomWrapper the chat room to remove.
*/
public void removeChatRoom(ChatRoomWrapper chatRoomWrapper)
{
ChatRoom chatRoom = chatRoomWrapper.getChatRoom();
if (chatRoom != null)
leaveChatRoom(chatRoomWrapper);
GuiActivator.getUIService().closeChatRoomWindow(chatRoomWrapper);
GuiActivator.getMUCService().removeChatRoom(chatRoomWrapper);
}
/**
* Joins the given chat room and manages all the exceptions that could
* occur during the join process.
*
* @param chatRoom the chat room to join
*/
public void joinChatRoom(AdHocChatRoom chatRoom)
{
AdHocChatRoomWrapper chatRoomWrapper
= adHocChatRoomList.findChatRoomWrapperFromAdHocChatRoom(chatRoom);
if(chatRoomWrapper == null)
{
AdHocChatRoomProviderWrapper parentProvider
= adHocChatRoomList.findServerWrapperFromProvider(
chatRoom.getParentProvider());
chatRoomWrapper =
new AdHocChatRoomWrapper(parentProvider, chatRoom);
adHocChatRoomList.addAdHocChatRoom(chatRoomWrapper);
fireAdHocChatRoomListChangedEvent(
chatRoomWrapper,
AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_ADDED);
}
this.joinChatRoom(chatRoomWrapper);
ChatWindowManager chatWindowManager
= GuiActivator.getUIService().getChatWindowManager();
chatWindowManager
.openChat(
chatWindowManager.getMultiChat(chatRoomWrapper, true),
true);
}
/**
* Leaves the given <tt>ChatRoom</tt>.
*
* @param chatRoomWrapper the <tt>ChatRoom</tt> to leave.
*/
public void leaveChatRoom(ChatRoomWrapper chatRoomWrapper)
{
ChatRoomWrapper leavedRoomWrapped
= GuiActivator.getMUCService().leaveChatRoom(chatRoomWrapper);
if(leavedRoomWrapped != null)
GuiActivator.getUIService().closeChatRoomWindow(leavedRoomWrapped);
}
/**
* Leaves the given <tt>ChatRoom</tt>.
*
* @param chatRoomWrapper the <tt>ChatRoom</tt> to leave.
*/
public void leaveChatRoom(AdHocChatRoomWrapper chatRoomWrapper)
{
AdHocChatRoom chatRoom = chatRoomWrapper.getAdHocChatRoom();
if (chatRoom != null)
{
chatRoom.leave();
}
else
{
new ErrorDialog(
GuiActivator.getUIService().getMainFrame(),
GuiActivator.getResources().getI18NString("service.gui.WARNING"),
GuiActivator.getResources().getI18NString(
"service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED"))
.showDialog();
}
}
/**
* Checks if there's an open history window for the given chat room.
*
* @param chatRoomWrapper the chat room wrapper to check for
* @return TRUE if there's an opened history window for the given chat room,
* FALSE otherwise.
*/
public boolean containsHistoryWindowForChatRoom(
ChatRoomWrapper chatRoomWrapper)
{
return chatRoomHistory.containsKey(chatRoomWrapper);
}
/**
* Returns the history window for the given chat room.
*
* @param chatRoomWrapper the chat room wrapper to search for
* @return the history window for the given chat room
*/
public HistoryWindow getHistoryWindowForChatRoom(
ChatRoomWrapper chatRoomWrapper)
{
return chatRoomHistory.get(chatRoomWrapper);
}
/**
* Adds a history window for a given chat room in the table of opened
* history windows.
*
* @param chatRoomWrapper the chat room wrapper to add
* @param historyWindow the history window to add
*/
public void addHistoryWindowForChatRoom(ChatRoomWrapper chatRoomWrapper,
HistoryWindow historyWindow)
{
chatRoomHistory.put(chatRoomWrapper, historyWindow);
}
/**
* Removes the history window for the given chat room.
*
* @param chatRoomWrapper the chat room wrapper to remove the history window
*/
public void removeHistoryWindowForChatRoom(ChatRoomWrapper chatRoomWrapper)
{
chatRoomHistory.remove(chatRoomWrapper);
}
/**
* Adds the given <tt>AdHocChatRoomListChangeListener</tt> that will listen
* for all changes of the chat room list data model.
*
* @param l the listener to add.
*/
public void addAdHocChatRoomListChangeListener(
AdHocChatRoomListChangeListener l)
{
synchronized (adHoclistChangeListeners)
{
adHoclistChangeListeners.add(l);
}
}
/**
* Removes the given <tt>AdHocChatRoomListChangeListener</tt>.
*
* @param l the listener to remove.
*/
public void removeAdHocChatRoomListChangeListener(
AdHocChatRoomListChangeListener l)
{
synchronized (adHoclistChangeListeners)
{
adHoclistChangeListeners.remove(l);
}
}
/**
* Notifies all interested listeners that a change in the chat room list
* model has occurred.
* @param adHocChatRoomWrapper the chat room wrapper that identifies the
* chat room
* @param eventID the identifier of the event
*/
private void fireAdHocChatRoomListChangedEvent(
AdHocChatRoomWrapper adHocChatRoomWrapper,
int eventID)
{
AdHocChatRoomListChangeEvent evt
= new AdHocChatRoomListChangeEvent(adHocChatRoomWrapper, eventID);
for (AdHocChatRoomListChangeListener l : adHoclistChangeListeners)
{
l.contentChanged(evt);
}
}
/**
* Closes the chat corresponding to the given ad-hoc chat room wrapper, if
* such exists.
*
* @param chatRoomWrapper the ad-hoc chat room wrapper for which we search a
* chat to close.
*/
private void closeAdHocChatRoom(AdHocChatRoomWrapper chatRoomWrapper)
{
ChatWindowManager chatWindowManager
= GuiActivator.getUIService().getChatWindowManager();
ChatPanel chatPanel
= chatWindowManager.getMultiChat(chatRoomWrapper, false);
if (chatPanel != null)
chatWindowManager.closeChat(chatPanel);
}
/**
* Handles <tt>ServiceEvent</tt>s triggered by adding or removing a
* ProtocolProviderService. Updates the list of available chat rooms and
* chat room servers.
*
* @param event The event to handle.
*/
public void serviceChanged(ServiceEvent event)
{
// if the event is caused by a bundle being stopped, we don't want to
// know
if (event.getServiceReference().getBundle().getState()
== Bundle.STOPPING)
return;
Object service = GuiActivator.bundleContext.getService(event
.getServiceReference());
// we don't care if the source service is not a protocol provider
if (!(service instanceof ProtocolProviderService))
return;
ProtocolProviderService protocolProvider
= (ProtocolProviderService) service;
Object multiUserChatAdHocOpSet
= protocolProvider
.getOperationSet(OperationSetAdHocMultiUserChat.class);
if (multiUserChatAdHocOpSet != null)
{
if (event.getType() == ServiceEvent.REGISTERED)
{
adHocChatRoomList.addChatProvider(protocolProvider);
}
else if (event.getType() == ServiceEvent.UNREGISTERING)
{
adHocChatRoomList.removeChatProvider(protocolProvider);
}
}
}
/**
* Joins an ad-hoc chat room in an asynchronous way.
*/
private static class JoinAdHocChatRoomTask
extends SwingWorker<String, Object>
{
private static final String SUCCESS = "Success";
private static final String AUTHENTICATION_FAILED
= "AuthenticationFailed";
private static final String REGISTRATION_REQUIRED
= "RegistrationRequired";
private static final String PROVIDER_NOT_REGISTERED
= "ProviderNotRegistered";
private static final String SUBSCRIPTION_ALREADY_EXISTS
= "SubscriptionAlreadyExists";
private static final String UNKNOWN_ERROR
= "UnknownError";
private final AdHocChatRoomWrapper adHocChatRoomWrapper;
JoinAdHocChatRoomTask(AdHocChatRoomWrapper chatRoomWrapper)
{
this.adHocChatRoomWrapper = chatRoomWrapper;
}
/**
* @override {@link SwingWorker}{@link #doInBackground()} to perform
* all asynchronous tasks.
* @return SUCCESS if success, otherwise the error code
*/
@Override
public String doInBackground()
{
AdHocChatRoom chatRoom = adHocChatRoomWrapper.getAdHocChatRoom();
try
{
chatRoom.join();
return SUCCESS;
}
catch (OperationFailedException e)
{
if (logger.isTraceEnabled())
logger.trace("Failed to join ad-hoc chat room: "
+ chatRoom.getName(), e);
switch (e.getErrorCode())
{
case OperationFailedException.AUTHENTICATION_FAILED:
return AUTHENTICATION_FAILED;
case OperationFailedException.REGISTRATION_REQUIRED:
return REGISTRATION_REQUIRED;
case OperationFailedException.PROVIDER_NOT_REGISTERED:
return PROVIDER_NOT_REGISTERED;
case OperationFailedException.SUBSCRIPTION_ALREADY_EXISTS:
return SUBSCRIPTION_ALREADY_EXISTS;
default:
return UNKNOWN_ERROR;
}
}
}
/**
* @override {@link SwingWorker}{@link #done()} to perform UI changes
* after the ad-hoc chat room join task has finished.
*/
@Override
protected void done()
{
String returnCode = null;
try
{
returnCode = get();
}
catch (InterruptedException ignore)
{}
catch (ExecutionException ignore)
{}
ConfigurationUtils.updateChatRoomStatus(
adHocChatRoomWrapper.getParentProvider().getProtocolProvider(),
adHocChatRoomWrapper.getAdHocChatRoomID(),
GlobalStatusEnum.ONLINE_STATUS);
String errorMessage = null;
if(PROVIDER_NOT_REGISTERED.equals(returnCode))
{
errorMessage
= GuiActivator.getResources()
.getI18NString("service.gui.CHAT_ROOM_NOT_CONNECTED",
new String[]{
adHocChatRoomWrapper.getAdHocChatRoomName()});
}
else if(SUBSCRIPTION_ALREADY_EXISTS.equals(returnCode))
{
errorMessage
= GuiActivator.getResources()
.getI18NString("service.gui.CHAT_ROOM_ALREADY_JOINED",
new String[]{
adHocChatRoomWrapper.getAdHocChatRoomName()});
}
else
{
errorMessage
= GuiActivator.getResources()
.getI18NString("service.gui.FAILED_TO_JOIN_CHAT_ROOM",
new String[]{
adHocChatRoomWrapper.getAdHocChatRoomName()});
}
if (!SUCCESS.equals(returnCode)
&& !AUTHENTICATION_FAILED.equals(returnCode))
{
GuiActivator.getAlertUIService().showAlertPopup(
GuiActivator.getResources().getI18NString(
"service.gui.ERROR"), errorMessage);
}
}
}
/**
* Indicates that an invitation has been received and opens the invitation
* dialog to notify the user.
* @param evt the <tt>AdHocChatRoomInvitationReceivedEvent</tt> that
* notified us
*/
public void invitationReceived(AdHocChatRoomInvitationReceivedEvent evt)
{
if (logger.isInfoEnabled())
logger.info("Invitation received: "+evt.toString());
OperationSetAdHocMultiUserChat multiUserChatOpSet
= evt.getSourceOperationSet();
InvitationReceivedDialog dialog = new InvitationReceivedDialog(
this, multiUserChatOpSet, evt.getInvitation());
dialog.setVisible(true);
}
/**
* Implements the <tt>AdHocChatRoomMessageListener.messageDelivered</tt>
* method.
* <br>
* Shows the message in the conversation area and clears the write message
* area.
* @param evt the <tt>AdHocChatRoomMessageDeliveredEvent</tt> that notified
* us
*/
public void messageDelivered(AdHocChatRoomMessageDeliveredEvent evt)
{
AdHocChatRoom sourceChatRoom = (AdHocChatRoom) evt.getSource();
if (logger.isInfoEnabled())
logger.info("MESSAGE DELIVERED to ad-hoc chat room: "
+ sourceChatRoom.getName());
ChatPanel chatPanel
= GuiActivator
.getUIService()
.getChatWindowManager()
.getMultiChat(sourceChatRoom, false);
if(chatPanel != null)
{
String messageType;
switch (evt.getEventType())
{
case AdHocChatRoomMessageDeliveredEvent
.CONVERSATION_MESSAGE_DELIVERED:
messageType = Chat.OUTGOING_MESSAGE;
break;
case AdHocChatRoomMessageDeliveredEvent.ACTION_MESSAGE_DELIVERED:
messageType = Chat.ACTION_MESSAGE;
break;
default:
messageType = null;
}
Message msg = evt.getMessage();
chatPanel
.addMessage(
sourceChatRoom
.getParentProvider().getAccountID().getUserID(),
null,
evt.getTimestamp(),
messageType,
msg.getContent(),
msg.getContentType(),
msg.getMessageUID(),
null);
}
else
{
logger.error("chat panel is null, message NOT DELIVERED !");
}
}
/**
* Implements <tt>AdHocChatRoomMessageListener.messageDeliveryFailed</tt>
* method.
* <br>
* In the conversation area shows an error message, explaining the problem.
* @param evt the <tt>AdHocChatRoomMessageDeliveryFailedEvent</tt> that
* notified us
*/
public void messageDeliveryFailed(
AdHocChatRoomMessageDeliveryFailedEvent evt)
{
AdHocChatRoom sourceChatRoom = evt.getSourceChatRoom();
Message sourceMessage = evt.getMessage();
Contact destParticipant = evt.getDestinationParticipant();
String errorMsg = null;
if (evt.getErrorCode()
== MessageDeliveryFailedEvent.OFFLINE_MESSAGES_NOT_SUPPORTED)
{
errorMsg = GuiActivator.getResources().getI18NString(
"service.gui.MSG_DELIVERY_NOT_SUPPORTED",
new String[]{destParticipant.getDisplayName()});
}
else if (evt.getErrorCode()
== MessageDeliveryFailedEvent.NETWORK_FAILURE)
{
errorMsg = GuiActivator.getResources()
.getI18NString("service.gui.MSG_NOT_DELIVERED");
}
else if (evt.getErrorCode()
== MessageDeliveryFailedEvent.PROVIDER_NOT_REGISTERED)
{
errorMsg = GuiActivator.getResources().getI18NString(
"service.gui.MSG_SEND_CONNECTION_PROBLEM");
}
else if (evt.getErrorCode()
== MessageDeliveryFailedEvent.INTERNAL_ERROR)
{
errorMsg = GuiActivator.getResources().getI18NString(
"service.gui.MSG_DELIVERY_INTERNAL_ERROR");
}
else if (evt.getErrorCode()
== MessageDeliveryFailedEvent.UNSUPPORTED_OPERATION)
{
errorMsg = GuiActivator.getResources().getI18NString(
"service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION");
}
else
{
errorMsg = GuiActivator.getResources().getI18NString(
"service.gui.MSG_DELIVERY_UNKNOWN_ERROR");
}
ChatWindowManager chatWindowManager
= GuiActivator.getUIService().getChatWindowManager();
ChatPanel chatPanel
= chatWindowManager.getMultiChat(sourceChatRoom, true);
chatPanel.addMessage(
destParticipant.getDisplayName(),
new Date(),
Chat.OUTGOING_MESSAGE,
sourceMessage.getContent(),
sourceMessage.getContentType());
chatPanel.addErrorMessage(
destParticipant.getDisplayName(),
errorMsg);
chatWindowManager.openChat(chatPanel, false);
}
/**
* Implements the <tt>AdHocChatRoomMessageListener.messageReceived</tt>
* method.
* <br>
* Obtains the corresponding <tt>ChatPanel</tt> and process the message
* there.
* @param evt the <tt>AdHocChatRoomMessageReceivedEvent</tt> that notified
* us
*/
public void messageReceived(AdHocChatRoomMessageReceivedEvent evt)
{
AdHocChatRoom sourceChatRoom = evt.getSourceChatRoom();
Contact sourceParticipant = evt.getSourceChatRoomParticipant();
String messageType = null;
switch (evt.getEventType())
{
case AdHocChatRoomMessageReceivedEvent.CONVERSATION_MESSAGE_RECEIVED:
messageType = Chat.INCOMING_MESSAGE;
break;
case AdHocChatRoomMessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED:
messageType = Chat.SYSTEM_MESSAGE;
break;
case AdHocChatRoomMessageReceivedEvent.ACTION_MESSAGE_RECEIVED:
messageType = Chat.ACTION_MESSAGE;
break;
}
if (logger.isInfoEnabled())
logger.info("MESSAGE RECEIVED from contact: "
+ sourceParticipant.getAddress());
Message message = evt.getMessage();
ChatWindowManager chatWindowManager
= GuiActivator.getUIService().getChatWindowManager();
ChatPanel chatPanel
= chatWindowManager
.getMultiChat(sourceChatRoom, true, message.getMessageUID());
String messageContent = message.getContent();
chatPanel.addMessage(
sourceParticipant.getDisplayName(),
null,
evt.getTimestamp(),
messageType,
messageContent,
message.getContentType(),
message.getMessageUID(),
null);
chatWindowManager.openChat(chatPanel, false);
}
public void invitationRejected(AdHocChatRoomInvitationRejectedEvent evt) {}
@Override
public void localUserRoleChanged(ChatRoomLocalUserRoleChangeEvent evt)
{
if(evt.isInitial())
return;
ChatRoom sourceChatRoom = evt.getSourceChatRoom();
ChatRoomWrapper chatRoomWrapper
= GuiActivator.getMUCService().findChatRoomWrapperFromChatRoom(
sourceChatRoom);
ChatWindowManager chatWindowManager
= GuiActivator.getUIService().getChatWindowManager();
ChatPanel chatPanel
= chatWindowManager.getMultiChat(chatRoomWrapper, true);
chatWindowManager.openChat(chatPanel, true);
}
}