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);
}
}
}