diff --git a/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomIrcImpl.java index ed72d5750..64ad1f227 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomIrcImpl.java @@ -136,6 +136,8 @@ public ChatRoomIrcImpl( String chatRoomName, { this(chatRoomName, parentProvider, false, false); } + + // TODO Need to implement equals() in order to correct compare 2 instances of ChatRoomIrcImpl as representing the same chatroom (room name + parent provider) /** * Creates an instance of ChatRoomIrcImpl, by specifying the room @@ -624,7 +626,7 @@ public void removeMessageListener(ChatRoomMessageListener listener) * @param memberID the identifier of the member * @return the ChatRoomMember corresponding to the given member id. */ - protected ChatRoomMember getChatRoomMember(String memberID) + public ChatRoomMember getChatRoomMember(String memberID) { return chatRoomMembers.get(memberID); } @@ -1278,4 +1280,14 @@ public void updateSubject(String subject) firePropertyChangeEvent(topicChangeEvent); } } + + public void updateChatRoomMemberName(String oldName, String newName) + { + synchronized(this.chatRoomMembers) + { + ChatRoomMember member = this.chatRoomMembers.remove(oldName); + if (member != null) + this.chatRoomMembers.put(newName, member); + } + } } diff --git a/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImpl.java index af4ab3f5d..538a9115c 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImpl.java @@ -25,7 +25,7 @@ public class ChatRoomMemberIrcImpl /** * The id of the contact. */ - private final String contactID; + private String contactID; /** * The provider that created us. @@ -108,6 +108,18 @@ public String getName() { return this.contactID; } + + /** + * Set a new name for this ChatRoomMember. + * + * @param newName + */ + public void setName(String newName) + { + if (newName == null) + throw new IllegalArgumentException("newName cannot be null"); + this.contactID = newName; + } /** * Returns the role of this chat room member in its containing room. diff --git a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java index 87f472233..4f1352476 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java @@ -5,43 +5,19 @@ */ package net.java.sip.communicator.impl.protocol.irc; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; import net.java.sip.communicator.impl.protocol.irc.ModeParser.ModeEntry; -import net.java.sip.communicator.impl.protocol.irc.listener.GenericListener; -import net.java.sip.communicator.service.protocol.ChatRoomMember; -import net.java.sip.communicator.service.protocol.ChatRoomMemberRole; -import net.java.sip.communicator.service.protocol.RegistrationState; -import net.java.sip.communicator.service.protocol.event.ChatRoomMemberPresenceChangeEvent; -import net.java.sip.communicator.service.protocol.event.ChatRoomMessageReceivedEvent; -import net.java.sip.communicator.service.protocol.event.LocalUserChatRoomPresenceChangeEvent; -import net.java.sip.communicator.service.protocol.event.MessageReceivedEvent; - -import com.ircclouds.irc.api.Callback; -import com.ircclouds.irc.api.IRCApi; -import com.ircclouds.irc.api.IRCApiImpl; -import com.ircclouds.irc.api.IServerParameters; -import com.ircclouds.irc.api.domain.IRCChannel; -import com.ircclouds.irc.api.domain.IRCServer; -import com.ircclouds.irc.api.domain.IRCTopic; -import com.ircclouds.irc.api.domain.IRCUser; -import com.ircclouds.irc.api.domain.IRCUserStatus; -import com.ircclouds.irc.api.domain.messages.ChanJoinMessage; -import com.ircclouds.irc.api.domain.messages.ChanPartMessage; -import com.ircclouds.irc.api.domain.messages.ChannelKick; -import com.ircclouds.irc.api.domain.messages.ChannelModeMessage; -import com.ircclouds.irc.api.domain.messages.ChannelPrivMsg; -import com.ircclouds.irc.api.domain.messages.QuitMessage; -import com.ircclouds.irc.api.domain.messages.TopicMessage; -import com.ircclouds.irc.api.listeners.VariousMessageListenerAdapter; -import com.ircclouds.irc.api.state.IIRCState; +import net.java.sip.communicator.impl.protocol.irc.listener.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; + +import com.ircclouds.irc.api.*; +import com.ircclouds.irc.api.domain.*; +import com.ircclouds.irc.api.domain.messages.*; +import com.ircclouds.irc.api.listeners.*; +import com.ircclouds.irc.api.state.*; /** * An implementation of the PircBot IRC stack. @@ -52,15 +28,15 @@ public class IrcStack private final ProtocolProviderServiceIrcImpl provider; - private final Map joined = Collections - .synchronizedMap(new HashMap()); + private final List joined = Collections + .synchronizedList(new ArrayList()); private final ServerParameters params; private IRCApi irc; private IIRCState connectionState; - + public IrcStack(final ProtocolProviderServiceIrcImpl parentProvider, final String nick, final String login, final String version, final String finger) @@ -91,6 +67,9 @@ public void connect(String host, int port, String password, && this.connectionState.isConnected()) return; + // Make sure we start with an empty joined-channel list. + this.joined.clear(); + // A container for storing the exception if connecting fails. final Exception[] exceptionContainer = new Exception[1]; @@ -98,7 +77,7 @@ public void connect(String host, int port, String password, this.params.setServer(new IRCServer(host, port, password, false)); synchronized (this.irc) { - this.irc.addListener(new GenericListener()); + this.irc.addListener(new GenericListener(this.joined)); // start connecting to the specified server ... this.irc.connect(this.params, new Callback() { @@ -166,11 +145,13 @@ public void disconnect() if (this.connectionState == null && this.irc == null) return; - for (String channel : this.joined.keySet()) + synchronized(this.joined) { - leave(channel); + for (ChatRoomIrcImpl channel : this.joined) + { + leave(channel); + } } - this.joined.clear(); this.irc.disconnect(); this.irc = null; this.connectionState = null; @@ -214,8 +195,7 @@ public void setSubject(ChatRoomIrcImpl chatroom, String subject) public boolean isJoined(ChatRoomIrcImpl chatroom) { - String chatRoomName = chatroom.getIdentifier(); - return this.joined.containsKey(chatRoomName); + return this.joined.contains(chatroom); } public List getServerChatRoomList() @@ -263,13 +243,10 @@ public void onSuccess(IRCChannel channel) { try { - String name = channel.getName(); - IrcStack.this.joined.put(name, channel); - + IrcStack.this.joined.add(chatroom); IrcStack.this.irc .addListener(new ChatRoomListener( chatroom)); - IRCTopic topic = channel.getTopic(); chatroom.updateSubject(topic.getValue()); @@ -468,17 +445,27 @@ public void onChannelPart(ChanPartMessage msg) IrcStack.this.provider.getMUC().fireLocalUserPresenceEvent( this.chatroom, LocalUserChatRoomPresenceChangeEvent.LOCAL_USER_LEFT, null); - IrcStack.this.joined.remove(this.chatroom.getIdentifier()); IrcStack.this.irc.deleteListener(this); + IrcStack.this.joined.remove(this.chatroom); } else { String user = msg.getSource().getNick(); ChatRoomMember member = this.chatroom.getChatRoomMember(user); - // Possibility that 'member' is null (should be fixed now that race condition in irc-api is fixed) - this.chatroom.fireMemberPresenceEvent(member, null, - ChatRoomMemberPresenceChangeEvent.MEMBER_LEFT, - msg.getPartMsg()); + try + { + // Possibility that 'member' is null (should be fixed now + // that race condition in irc-api is fixed) + this.chatroom.fireMemberPresenceEvent(member, null, + ChatRoomMemberPresenceChangeEvent.MEMBER_LEFT, + msg.getPartMsg()); + } + catch (NullPointerException e) + { + System.err + .println("This should not have happened. Please report this as it is a bug."); + e.printStackTrace(); + } } } @@ -495,8 +482,8 @@ public void onChannelKick(ChannelKick msg) this.chatroom, LocalUserChatRoomPresenceChangeEvent.LOCAL_USER_KICKED, msg.getText()); - IrcStack.this.joined.remove(this.chatroom.getIdentifier()); IrcStack.this.irc.deleteListener(this); + IrcStack.this.joined.remove(this.chatroom); } else { @@ -527,7 +514,7 @@ public void onUserQuit(QuitMessage msg) msg.getQuitMsg()); } } - + @Override public void onChannelMessage(ChannelPrivMsg msg) { diff --git a/src/net/java/sip/communicator/impl/protocol/irc/listener/GenericListener.java b/src/net/java/sip/communicator/impl/protocol/irc/listener/GenericListener.java index acd0b9d5c..6d3fd00e4 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/listener/GenericListener.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/listener/GenericListener.java @@ -1,29 +1,80 @@ package net.java.sip.communicator.impl.protocol.irc.listener; -import com.ircclouds.irc.api.domain.messages.ServerNotice; -import com.ircclouds.irc.api.domain.messages.ServerNumericMessage; -import com.ircclouds.irc.api.domain.messages.interfaces.IMessage; -import com.ircclouds.irc.api.listeners.IMessageListener; +import java.util.*; +import java.util.Map.Entry; + +import net.java.sip.communicator.impl.protocol.irc.*; +import net.java.sip.communicator.service.protocol.event.*; + +import com.ircclouds.irc.api.domain.messages.*; +import com.ircclouds.irc.api.listeners.*; public class GenericListener - implements IMessageListener + extends VariousMessageListenerAdapter { + private final List channels; + + public GenericListener(List joinedChannels) + { + this.channels = joinedChannels; + } + // TODO Maybe implement this as a IRC server listener and connect a system // chatroom to each listener in order to inform the user of server // (chatroom-independent) messages, notices, etc. - + @Override - public void onMessage(IMessage msg) + public void onServerNotice(ServerNotice msg) { - if (msg instanceof ServerNotice) + System.out.println("NOTICE: " + ((ServerNotice) msg).getText()); + } + + @Override + public void onServerNumericMessage(ServerNumericMessage msg) + { + System.out.println("NUM MSG: " + + ((ServerNumericMessage) msg).getNumericCode() + ": " + + ((ServerNumericMessage) msg).getText()); + } + + @Override + public void onNickChange(NickMessage msg) + { + if (msg == null) + return; + + // Find all affected channels. + HashMap affected = + new HashMap(); + String oldNick = msg.getSource().getNick(); + synchronized (this.channels) { - System.out.println("NOTICE: " + ((ServerNotice) msg).getText()); + for (ChatRoomIrcImpl channel : this.channels) + { + ChatRoomMemberIrcImpl member = + (ChatRoomMemberIrcImpl) channel.getChatRoomMember(oldNick); + if (member != null) + { + affected.put(channel, member); + } + } } - else if (msg instanceof ServerNumericMessage) + + // Process nick change for all of those channels and fire corresponding + // property change event. + String newNick = msg.getNewNick(); + for (Entry record : affected + .entrySet()) { - System.out.println("NUM MSG: " - + ((ServerNumericMessage) msg).getNumericCode() + ": " - + ((ServerNumericMessage) msg).getText()); + ChatRoomIrcImpl channel = record.getKey(); + ChatRoomMemberIrcImpl member = record.getValue(); + member.setName(newNick); + channel.updateChatRoomMemberName(oldNick, newNick); + ChatRoomMemberPropertyChangeEvent evt = + new ChatRoomMemberPropertyChangeEvent(member, channel, + ChatRoomMemberPropertyChangeEvent.MEMBER_NICKNAME, oldNick, + newNick); + channel.fireMemberPropertyChangeEvent(evt); } } }