mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-09-10 17:49:38 +02:00
Merge branch '4.4'
This commit is contained in:
commit
71f5cfe3da
28 changed files with 380 additions and 102 deletions
|
@ -26,8 +26,13 @@ import org.jivesoftware.smack.SmackException.NoResponseException;
|
|||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smack.packet.Stanza;
|
||||
import org.jivesoftware.smack.packet.StanzaBuilder;
|
||||
import org.jivesoftware.smack.packet.StanzaFactory;
|
||||
import org.jivesoftware.smack.packet.StanzaView;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import org.jivesoftware.smackx.address.packet.MultipleAddresses;
|
||||
|
@ -207,25 +212,44 @@ public class MultipleRecipientManager {
|
|||
return extension == null ? null : new MultipleRecipientInfo(extension);
|
||||
}
|
||||
|
||||
private static void sendToIndividualRecipients(XMPPConnection connection, Stanza packet,
|
||||
private static void sendToIndividualRecipients(XMPPConnection connection, StanzaView stanza,
|
||||
Collection<? extends Jid> to, Collection<? extends Jid> cc, Collection<? extends Jid> bcc) throws NotConnectedException, InterruptedException {
|
||||
final StanzaFactory stanzaFactory = connection.getStanzaFactory();
|
||||
final StanzaBuilder<?> stanzaBuilder;
|
||||
if (stanza instanceof Message) {
|
||||
Message message = (Message) stanza;
|
||||
stanzaBuilder = stanzaFactory.buildMessageStanzaFrom(message);
|
||||
} else if (stanza instanceof Presence) {
|
||||
Presence presence = (Presence) stanza;
|
||||
stanzaBuilder = stanzaFactory.buildPresenceStanzaFrom(presence);
|
||||
} else if (stanza instanceof IQ) {
|
||||
throw new IllegalArgumentException("IQ stanzas have no supported fallback in case no XEP-0033 service is available");
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
final int numRecipients = to.size() + cc.size() + bcc.size();
|
||||
final List<Jid> recipients = new ArrayList<>(numRecipients);
|
||||
|
||||
if (to != null) {
|
||||
for (Jid jid : to) {
|
||||
packet.setTo(jid);
|
||||
connection.sendStanza(new PacketCopy(packet));
|
||||
}
|
||||
recipients.addAll(to);
|
||||
}
|
||||
if (cc != null) {
|
||||
for (Jid jid : cc) {
|
||||
packet.setTo(jid);
|
||||
connection.sendStanza(new PacketCopy(packet));
|
||||
}
|
||||
recipients.addAll(cc);
|
||||
}
|
||||
if (bcc != null) {
|
||||
for (Jid jid : bcc) {
|
||||
packet.setTo(jid);
|
||||
connection.sendStanza(new PacketCopy(packet));
|
||||
}
|
||||
recipients.addAll(bcc);
|
||||
}
|
||||
|
||||
final List<Stanza> stanzasToSend = new ArrayList<>(numRecipients);
|
||||
for (Jid recipient : recipients) {
|
||||
Stanza stanzaToSend = stanzaBuilder.to(recipient).build();
|
||||
stanzasToSend.add(stanzaToSend);
|
||||
}
|
||||
|
||||
// TODO: Use XMPPConnection.sendStanzas(Collection<? extends Stanza>) once this method exists.
|
||||
for (Stanza stanzaToSend : stanzasToSend) {
|
||||
connection.sendStanza(stanzaToSend);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,43 +313,4 @@ public class MultipleRecipientManager {
|
|||
return sdm.findService(MultipleAddresses.NAMESPACE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stanza that holds the XML stanza to send. This class is useful when the same packet
|
||||
* is needed to be sent to different recipients. Since using the same stanza is not possible
|
||||
* (i.e. cannot change the TO address of a queues stanza to be sent) then this class was
|
||||
* created to keep the XML stanza to send.
|
||||
*/
|
||||
private static final class PacketCopy extends Stanza {
|
||||
|
||||
private final String elementName;
|
||||
private final CharSequence text;
|
||||
|
||||
/**
|
||||
* Create a copy of a stanza with the text to send. The passed text must be a valid text to
|
||||
* send to the server, no validation will be done on the passed text.
|
||||
*
|
||||
* @param text the whole text of the stanza to send
|
||||
*/
|
||||
private PacketCopy(Stanza stanza) {
|
||||
this.elementName = stanza.getElementName();
|
||||
this.text = stanza.toXML();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toXML().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return elementName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import java.util.WeakHashMap;
|
|||
|
||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.Smack;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
|
@ -152,7 +152,7 @@ public final class VersionManager extends Manager {
|
|||
|
||||
private static Version generateVersionFrom(String name, String version, String os) {
|
||||
if (autoAppendSmackVersion) {
|
||||
name += " (Smack " + SmackConfiguration.getVersion() + ')';
|
||||
name += " (Smack " + Smack.getVersion() + ')';
|
||||
}
|
||||
return new Version(name, version, os);
|
||||
}
|
||||
|
|
|
@ -149,6 +149,11 @@ public class MultiUserChat {
|
|||
private EntityFullJid myRoomJid;
|
||||
private StanzaCollector messageCollector;
|
||||
|
||||
/**
|
||||
* Used to signal that the reflected self-presence was received <b>and</b> processed by us.
|
||||
*/
|
||||
private volatile boolean processedReflectedSelfPresence;
|
||||
|
||||
MultiUserChat(XMPPConnection connection, EntityBareJid room, MultiUserChatManager multiUserChatManager) {
|
||||
this.connection = connection;
|
||||
this.room = room;
|
||||
|
@ -195,6 +200,7 @@ public class MultiUserChat {
|
|||
}
|
||||
final EntityFullJid myRoomJID = myRoomJid;
|
||||
final boolean isUserStatusModification = presence.getFrom().equals(myRoomJID);
|
||||
final MUCUser mucUser = MUCUser.from(packet);
|
||||
|
||||
switch (presence.getType()) {
|
||||
case available:
|
||||
|
@ -205,9 +211,8 @@ public class MultiUserChat {
|
|||
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();
|
||||
MUCAffiliation newAffiliation = mucUser.getItem().getAffiliation();
|
||||
MUCRole newRole = mucUser.getItem().getRole();
|
||||
// Fire role modification events
|
||||
checkRoleModifications(oldRole, newRole, isUserStatusModification, from);
|
||||
// Fire affiliation modification events
|
||||
|
@ -216,19 +221,20 @@ public class MultiUserChat {
|
|||
newAffiliation,
|
||||
isUserStatusModification,
|
||||
from);
|
||||
}
|
||||
else {
|
||||
} else if (mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110)) {
|
||||
processedReflectedSelfPresence = true;
|
||||
synchronized (this) {
|
||||
notify();
|
||||
}
|
||||
} else {
|
||||
// A new occupant has joined the room
|
||||
if (!isUserStatusModification) {
|
||||
for (ParticipantStatusListener listener : participantStatusListeners) {
|
||||
listener.joined(from);
|
||||
}
|
||||
for (ParticipantStatusListener listener : participantStatusListeners) {
|
||||
listener.joined(from);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case unavailable:
|
||||
occupantsMap.remove(from);
|
||||
MUCUser mucUser = MUCUser.from(packet);
|
||||
if (mucUser != null && mucUser.hasStatus()) {
|
||||
if (isUserStatusModification) {
|
||||
userHasLeft();
|
||||
|
@ -377,8 +383,9 @@ public class MultiUserChat {
|
|||
)
|
||||
);
|
||||
// @formatter:on
|
||||
processedReflectedSelfPresence = false;
|
||||
StanzaCollector presenceStanzaCollector = null;
|
||||
Presence presence;
|
||||
final Presence reflectedSelfPresence;
|
||||
try {
|
||||
// This stanza collector will collect the final self presence from the MUC, which also signals that we have successful entered the MUC.
|
||||
StanzaCollector selfPresenceCollector = connection.createStanzaCollectorAndSend(responseFilter, joinPresence);
|
||||
|
@ -386,7 +393,7 @@ public class MultiUserChat {
|
|||
selfPresenceCollector).setStanzaFilter(presenceFromRoomFilter);
|
||||
// This stanza collector is used to reset the timeout of the selfPresenceCollector.
|
||||
presenceStanzaCollector = connection.createStanzaCollector(presenceStanzaCollectorConfguration);
|
||||
presence = selfPresenceCollector.nextResultOrThrow(conf.getTimeout());
|
||||
reflectedSelfPresence = selfPresenceCollector.nextResultOrThrow(conf.getTimeout());
|
||||
}
|
||||
catch (NotConnectedException | InterruptedException | NoResponseException | XMPPErrorException e) {
|
||||
// Ensure that all callbacks are removed if there is an exception
|
||||
|
@ -399,14 +406,24 @@ public class MultiUserChat {
|
|||
}
|
||||
}
|
||||
|
||||
synchronized (presenceListener) {
|
||||
// Only continue after we have received *and* processed the reflected self-presence. Since presences are
|
||||
// handled in an extra listener, we may return from enter() without having processed all presences of the
|
||||
// participants, resulting in a e.g. to low participant counter after enter(). Hence we wait here until the
|
||||
// processing is done.
|
||||
while (!processedReflectedSelfPresence) {
|
||||
presenceListener.wait();
|
||||
}
|
||||
}
|
||||
|
||||
// This presence must be send from a full JID. We use the resourcepart of this JID as nick, since the room may
|
||||
// performed roomnick rewriting
|
||||
Resourcepart receivedNickname = presence.getFrom().getResourceOrThrow();
|
||||
Resourcepart receivedNickname = reflectedSelfPresence.getFrom().getResourceOrThrow();
|
||||
setNickname(receivedNickname);
|
||||
|
||||
// Update the list of joined rooms
|
||||
multiUserChatManager.addJoinedRoom(room);
|
||||
return presence;
|
||||
return reflectedSelfPresence;
|
||||
}
|
||||
|
||||
private void setNickname(Resourcepart nickname) {
|
||||
|
|
|
@ -51,14 +51,9 @@ public class OptionsExtension extends NodeExtension {
|
|||
|
||||
@Override
|
||||
protected void addXml(XmlStringBuilder xml) {
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.halfOpenElement(getElementName());
|
||||
xml.attribute("jid", jid);
|
||||
xml.optAttribute("node", getNode());
|
||||
xml.optAttribute("subid", id);
|
||||
|
||||
xml.closeEmptyElement();
|
||||
xml.closeElement(this);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue