Hi all,
I’m using Smack to interface with a hardware device that runs an XMPP server. It occasionally sends out elements that look like this:
The message has no from, to, or thread attributes. I suspect this is somewhat unusual (the XMPP server in this device could be weird), but reading through RFC-3921, I couldn’t find anything explicitly forbidding a message with no thread/from/to attributes.Unfortunately, it causes a NullPointerException in ChatManager.
When the processPacket(Packet) method from the anonymous PacketListener is invoked with this empty message element, it can’t find a thread-ID (because there isn’t one). It then calls getUserChat(message.getFrom()), but there’s no From attribute either. Last, it tries to call createChat:
public void processPacket(Packet packet) {
Message message = (Message) packet;
Chat chat;
if (message.getThread() == null) {
chat = getUserChat(message.getFrom());
}
else {
chat = getThreadChat(message.getThread());
}
if(chat == null) {
chat = createChat(message);
}
deliverMessage(chat, message);
}
As you can see, createChat(Message) checks for a null “thread”, but not a null “from”:
private Chat createChat(Message message) {
String threadID = message.getThread();
if(threadID == null) {
threadID = nextID();
}
String userJID = message.getFrom();
return createChat(userJID, threadID, false);
}
So a null userJID will be passed to createChat(String userJID, String threadID, boolean). It uses both String parameters as Map keys:
private Chat createChat(String userJID, String threadID, boolean createdLocally) {
Chat chat = new Chat(this, userJID, threadID);
threadChats.put(threadID, chat);
jidChats.put(userJID, chat);
baseJidChats.put(StringUtils.parseBareAddress(userJID), chat);
for(ChatManagerListener listener : chatManagerListeners) {
listener.chatCreated(chat, createdLocally);
}
return chat;
}
Unfortunately, the documentation on ReferenceMap (the implementation used for jidChats) warns:
“This java.util.Map implementation does *not *allow null elements. Attempting to add a null key or value to the map will raise a NullPointerException.”, so that’s just what it does - throws a NPE.
For my purposes, I just reorganized the logic in processPacket(Packet) and added a check to make sure that it doesn’t try to create a chat if there is no “from” attribute. Then, it just doesn’t deliver the packet if no existing chat was found. I don’t know if there’d ever be a reason you’d want to do more with it. I thought about substituting an empty string in as the userJID, but I didn’t need to process that packet, and it’s probably better that someone more familiar with XMPP decide how to handle it.
Note: I took a peek into the main branch and it looks like the same issue would occur there, too.
Russ