mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2025-09-09 18:29:45 +02:00
Inroduce AsyncButOrdered
This commit is contained in:
parent
1acfd872a7
commit
476fdf99a1
11 changed files with 414 additions and 272 deletions
|
@ -22,6 +22,7 @@ import java.util.WeakHashMap;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.jivesoftware.smack.AsyncButOrdered;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.StanzaListener;
|
||||
|
@ -91,6 +92,8 @@ public final class ChatManager extends Manager {
|
|||
|
||||
private final Set<OutgoingChatMessageListener> outgoingListeners = new CopyOnWriteArraySet<>();
|
||||
|
||||
private final AsyncButOrdered<Chat> asyncButOrdered = new AsyncButOrdered<>();
|
||||
|
||||
private boolean xhtmlIm;
|
||||
|
||||
private ChatManager(final XMPPConnection connection) {
|
||||
|
@ -98,7 +101,7 @@ public final class ChatManager extends Manager {
|
|||
connection.addSyncStanzaListener(new StanzaListener() {
|
||||
@Override
|
||||
public void processStanza(Stanza stanza) {
|
||||
Message message = (Message) stanza;
|
||||
final Message message = (Message) stanza;
|
||||
if (!shouldAcceptMessage(message)) {
|
||||
return;
|
||||
}
|
||||
|
@ -109,9 +112,15 @@ public final class ChatManager extends Manager {
|
|||
final Chat chat = chatWith(bareFrom);
|
||||
chat.lockedResource = fullFrom;
|
||||
|
||||
for (IncomingChatMessageListener listener : incomingListeners) {
|
||||
listener.newIncomingMessage(bareFrom, message, chat);
|
||||
}
|
||||
asyncButOrdered.performAsyncButOrdered(chat, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (IncomingChatMessageListener listener : incomingListeners) {
|
||||
listener.newIncomingMessage(bareFrom, message, chat);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}, INCOMING_MESSAGE_FILTER);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.WeakHashMap;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.AsyncButOrdered;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.StanzaListener;
|
||||
|
@ -85,6 +86,8 @@ public final class ChatStateManager extends Manager {
|
|||
*/
|
||||
private final Map<Chat, ChatState> chatStates = new WeakHashMap<>();
|
||||
|
||||
private final AsyncButOrdered<Chat> asyncButOrdered = new AsyncButOrdered<>();
|
||||
|
||||
/**
|
||||
* Returns the ChatStateManager related to the XMPPConnection and it will create one if it does
|
||||
* not yet exist.
|
||||
|
@ -129,15 +132,15 @@ public final class ChatStateManager extends Manager {
|
|||
}
|
||||
});
|
||||
|
||||
connection.addAsyncStanzaListener(new StanzaListener() {
|
||||
connection.addSyncStanzaListener(new StanzaListener() {
|
||||
@Override
|
||||
public void processStanza(Stanza stanza) {
|
||||
Message message = (Message) stanza;
|
||||
final Message message = (Message) stanza;
|
||||
|
||||
EntityFullJid fullFrom = message.getFrom().asEntityFullJidIfPossible();
|
||||
EntityBareJid bareFrom = fullFrom.asEntityBareJid();
|
||||
|
||||
Chat chat = ChatManager.getInstanceFor(connection()).chatWith(bareFrom);
|
||||
final Chat chat = ChatManager.getInstanceFor(connection()).chatWith(bareFrom);
|
||||
ExtensionElement extension = message.getExtension(NAMESPACE);
|
||||
String chatStateElementName = extension.getElementName();
|
||||
|
||||
|
@ -149,6 +152,7 @@ public final class ChatStateManager extends Manager {
|
|||
LOGGER.log(Level.WARNING, "Invalid chat state element name: " + chatStateElementName, ex);
|
||||
return;
|
||||
}
|
||||
final ChatState finalState = state;
|
||||
|
||||
List<ChatStateListener> listeners;
|
||||
synchronized (chatStateListeners) {
|
||||
|
@ -156,9 +160,15 @@ public final class ChatStateManager extends Manager {
|
|||
listeners.addAll(chatStateListeners);
|
||||
}
|
||||
|
||||
for (ChatStateListener listener : listeners) {
|
||||
listener.stateChanged(chat, state, message);
|
||||
}
|
||||
final List<ChatStateListener> finalListeners = listeners;
|
||||
asyncButOrdered.performAsyncButOrdered(chat, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (ChatStateListener listener : finalListeners) {
|
||||
listener.stateChanged(chat, finalState, message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, INCOMING_CHAT_STATE_FILTER);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.AsyncButOrdered;
|
||||
import org.jivesoftware.smack.MessageListener;
|
||||
import org.jivesoftware.smack.PresenceListener;
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
|
@ -141,6 +142,8 @@ public class MultiUserChat {
|
|||
private final StanzaListener presenceListener;
|
||||
private final StanzaListener subjectListener;
|
||||
|
||||
private static final AsyncButOrdered<MultiUserChat> asyncButOrdered = new AsyncButOrdered<>();
|
||||
|
||||
private static final StanzaFilter DECLINE_FILTER = new AndFilter(MessageTypeFilter.NORMAL,
|
||||
new StanzaExtensionFilter(MUCUser.ELEMENT, MUCUser.NAMESPACE));
|
||||
private final StanzaListener declinesListener;
|
||||
|
@ -161,10 +164,16 @@ public class MultiUserChat {
|
|||
messageListener = new StanzaListener() {
|
||||
@Override
|
||||
public void processStanza(Stanza packet) throws NotConnectedException {
|
||||
Message message = (Message) packet;
|
||||
for (MessageListener listener : messageListeners) {
|
||||
listener.processMessage(message);
|
||||
}
|
||||
final Message message = (Message) packet;
|
||||
|
||||
asyncButOrdered.performAsyncButOrdered(MultiUserChat.this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (MessageListener listener : messageListeners) {
|
||||
listener.processMessage(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -172,84 +181,96 @@ public class MultiUserChat {
|
|||
subjectListener = new StanzaListener() {
|
||||
@Override
|
||||
public void processStanza(Stanza packet) {
|
||||
Message msg = (Message) packet;
|
||||
EntityFullJid from = msg.getFrom().asEntityFullJidIfPossible();
|
||||
final Message msg = (Message) packet;
|
||||
final EntityFullJid from = msg.getFrom().asEntityFullJidIfPossible();
|
||||
// Update the room subject
|
||||
subject = msg.getSubject();
|
||||
// Fire event for subject updated listeners
|
||||
for (SubjectUpdatedListener listener : subjectUpdatedListeners) {
|
||||
listener.subjectUpdated(subject, from);
|
||||
}
|
||||
|
||||
asyncButOrdered.performAsyncButOrdered(MultiUserChat.this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Fire event for subject updated listeners
|
||||
for (SubjectUpdatedListener listener : subjectUpdatedListeners) {
|
||||
listener.subjectUpdated(msg.getSubject(), from);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Create a listener for all presence updates.
|
||||
presenceListener = new StanzaListener() {
|
||||
@Override
|
||||
public void processStanza(Stanza packet) {
|
||||
Presence presence = (Presence) packet;
|
||||
public void processStanza(final Stanza packet) {
|
||||
final Presence presence = (Presence) packet;
|
||||
final EntityFullJid from = presence.getFrom().asEntityFullJidIfPossible();
|
||||
if (from == null) {
|
||||
LOGGER.warning("Presence not from a full JID: " + presence.getFrom());
|
||||
return;
|
||||
}
|
||||
String myRoomJID = MultiUserChat.this.room + "/" + nickname;
|
||||
boolean isUserStatusModification = presence.getFrom().equals(myRoomJID);
|
||||
switch (presence.getType()) {
|
||||
case available:
|
||||
Presence oldPresence = occupantsMap.put(from, presence);
|
||||
if (oldPresence != null) {
|
||||
// Get the previous occupant's affiliation & role
|
||||
MUCUser mucExtension = MUCUser.from(oldPresence);
|
||||
MUCAffiliation oldAffiliation = mucExtension.getItem().getAffiliation();
|
||||
MUCRole oldRole = mucExtension.getItem().getRole();
|
||||
// Get the new occupant's affiliation & role
|
||||
mucExtension = MUCUser.from(packet);
|
||||
MUCAffiliation newAffiliation = mucExtension.getItem().getAffiliation();
|
||||
MUCRole newRole = mucExtension.getItem().getRole();
|
||||
// Fire role modification events
|
||||
checkRoleModifications(oldRole, newRole, isUserStatusModification, from);
|
||||
// Fire affiliation modification events
|
||||
checkAffiliationModifications(
|
||||
oldAffiliation,
|
||||
newAffiliation,
|
||||
isUserStatusModification,
|
||||
from);
|
||||
}
|
||||
else {
|
||||
// A new occupant has joined the room
|
||||
if (!isUserStatusModification) {
|
||||
for (ParticipantStatusListener listener : participantStatusListeners) {
|
||||
listener.joined(from);
|
||||
final String myRoomJID = MultiUserChat.this.room + "/" + nickname;
|
||||
final boolean isUserStatusModification = presence.getFrom().equals(myRoomJID);
|
||||
|
||||
asyncButOrdered.performAsyncButOrdered(MultiUserChat.this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
switch (presence.getType()) {
|
||||
case available:
|
||||
Presence oldPresence = occupantsMap.put(from, presence);
|
||||
if (oldPresence != null) {
|
||||
// Get the previous occupant's affiliation & role
|
||||
MUCUser mucExtension = MUCUser.from(oldPresence);
|
||||
MUCAffiliation oldAffiliation = mucExtension.getItem().getAffiliation();
|
||||
MUCRole oldRole = mucExtension.getItem().getRole();
|
||||
// Get the new occupant's affiliation & role
|
||||
mucExtension = MUCUser.from(packet);
|
||||
MUCAffiliation newAffiliation = mucExtension.getItem().getAffiliation();
|
||||
MUCRole newRole = mucExtension.getItem().getRole();
|
||||
// Fire role modification events
|
||||
checkRoleModifications(oldRole, newRole, isUserStatusModification, from);
|
||||
// Fire affiliation modification events
|
||||
checkAffiliationModifications(
|
||||
oldAffiliation,
|
||||
newAffiliation,
|
||||
isUserStatusModification,
|
||||
from);
|
||||
}
|
||||
else {
|
||||
// A new occupant has joined the room
|
||||
if (!isUserStatusModification) {
|
||||
for (ParticipantStatusListener listener : participantStatusListeners) {
|
||||
listener.joined(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case unavailable:
|
||||
occupantsMap.remove(from);
|
||||
MUCUser mucUser = MUCUser.from(packet);
|
||||
if (mucUser != null && mucUser.hasStatus()) {
|
||||
// Fire events according to the received presence code
|
||||
checkPresenceCode(
|
||||
mucUser.getStatus(),
|
||||
presence.getFrom().equals(myRoomJID),
|
||||
mucUser,
|
||||
from);
|
||||
} else {
|
||||
// An occupant has left the room
|
||||
if (!isUserStatusModification) {
|
||||
for (ParticipantStatusListener listener : participantStatusListeners) {
|
||||
listener.left(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (PresenceListener listener : presenceListeners) {
|
||||
listener.processPresence(presence);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case unavailable:
|
||||
occupantsMap.remove(from);
|
||||
MUCUser mucUser = MUCUser.from(packet);
|
||||
if (mucUser != null && mucUser.hasStatus()) {
|
||||
// Fire events according to the received presence code
|
||||
checkPresenceCode(
|
||||
mucUser.getStatus(),
|
||||
presence.getFrom().equals(myRoomJID),
|
||||
mucUser,
|
||||
from);
|
||||
} else {
|
||||
// An occupant has left the room
|
||||
if (!isUserStatusModification) {
|
||||
for (ParticipantStatusListener listener : participantStatusListeners) {
|
||||
listener.left(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (PresenceListener listener : presenceListeners) {
|
||||
listener.processPresence(presence);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2007 Jive Software, 2015 Florian Schmaus
|
||||
* Copyright 2003-2007 Jive Software, 2015-2018 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -22,6 +22,7 @@ import java.util.Set;
|
|||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.jivesoftware.smack.AsyncButOrdered;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
|
@ -86,6 +87,8 @@ public final class PEPManager extends Manager {
|
|||
|
||||
private final Set<PEPListener> pepListeners = new CopyOnWriteArraySet<>();
|
||||
|
||||
private final AsyncButOrdered<EntityBareJid> asyncButOrdered = new AsyncButOrdered<>();
|
||||
|
||||
/**
|
||||
* Creates a new PEP exchange manager.
|
||||
*
|
||||
|
@ -96,14 +99,19 @@ public final class PEPManager extends Manager {
|
|||
StanzaListener packetListener = new StanzaListener() {
|
||||
@Override
|
||||
public void processStanza(Stanza stanza) {
|
||||
Message message = (Message) stanza;
|
||||
EventElement event = EventElement.from(stanza);
|
||||
final Message message = (Message) stanza;
|
||||
final EventElement event = EventElement.from(stanza);
|
||||
assert (event != null);
|
||||
EntityBareJid from = message.getFrom().asEntityBareJidIfPossible();
|
||||
final EntityBareJid from = message.getFrom().asEntityBareJidIfPossible();
|
||||
assert (from != null);
|
||||
for (PEPListener listener : pepListeners) {
|
||||
listener.eventReceived(from, event, message);
|
||||
}
|
||||
asyncButOrdered.performAsyncButOrdered(from, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (PEPListener listener : pepListeners) {
|
||||
listener.eventReceived(from, event, message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
// TODO Add filter to check if from supports PubSub as per xep163 2 2.4
|
||||
|
|
|
@ -521,6 +521,7 @@ public abstract class Node {
|
|||
EventContentFilter deleteItem = new EventContentFilter(EventElementType.items.toString(), "retract");
|
||||
EventContentFilter purge = new EventContentFilter(EventElementType.purge.toString());
|
||||
|
||||
// TODO: Use AsyncButOrdered (with Node as Key?)
|
||||
pubSubManager.getConnection().addSyncStanzaListener(delListener, new OrFilter(deleteItem, purge));
|
||||
}
|
||||
|
||||
|
@ -588,6 +589,7 @@ public abstract class Node {
|
|||
EventElement event = packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
|
||||
ItemsExtension itemsElem = (ItemsExtension) event.getEvent();
|
||||
ItemPublishEvent eventItems = new ItemPublishEvent(itemsElem.getNode(), itemsElem.getItems(), getSubscriptionIds(packet), DelayInformationManager.getDelayTimestamp(packet));
|
||||
// TODO: Use AsyncButOrdered (with Node as Key?)
|
||||
listener.handlePublishedItems(eventItems);
|
||||
}
|
||||
}
|
||||
|
@ -650,6 +652,7 @@ public abstract class Node {
|
|||
EventElement event = packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
|
||||
ConfigurationEvent config = (ConfigurationEvent) event.getEvent();
|
||||
|
||||
// TODO: Use AsyncButOrdered (with Node as Key?)
|
||||
listener.handleNodeConfiguration(config);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue