Merge branch '4.4'

This commit is contained in:
Florian Schmaus 2021-03-23 21:41:25 +01:00
commit ed807d5954
5 changed files with 91 additions and 6 deletions

View File

@ -31,6 +31,7 @@ import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.filter.ToTypeFilter; import org.jivesoftware.smack.filter.ToTypeFilter;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.muc.MultiUserChatManager;
import org.jivesoftware.smackx.sid.element.OriginIdElement; import org.jivesoftware.smackx.sid.element.OriginIdElement;
/** /**
@ -48,7 +49,7 @@ public final class StableUniqueStanzaIdManager extends Manager {
private static final Map<XMPPConnection, StableUniqueStanzaIdManager> INSTANCES = new WeakHashMap<>(); private static final Map<XMPPConnection, StableUniqueStanzaIdManager> INSTANCES = new WeakHashMap<>();
private static boolean enabledByDefault = true; private static boolean enabledByDefault = false;
// Filter for outgoing stanzas. // Filter for outgoing stanzas.
private static final StanzaFilter OUTGOING_FILTER = new AndFilter( private static final StanzaFilter OUTGOING_FILTER = new AndFilter(
@ -68,6 +69,14 @@ public final class StableUniqueStanzaIdManager extends Manager {
if (enabledByDefault) { if (enabledByDefault) {
getInstanceFor(connection).enable(); getInstanceFor(connection).enable();
} }
MultiUserChatManager.addDefaultMessageInterceptor((mb, muc) -> {
// No need to add an <origin-id/> if the MUC service supports stable IDs.
if (muc.serviceSupportsStableIds()) {
return;
}
OriginIdElement.addTo(mb);
});
} }
}); });
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2018 Paul Schaub * Copyright 2018 Paul Schaub, 2021 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -48,7 +48,12 @@ public class OriginIdElement extends StableAndUniqueIdElement {
@Deprecated @Deprecated
// TODO: Remove in Smack 4.5. // TODO: Remove in Smack 4.5.
public static OriginIdElement addOriginId(Message message) { public static OriginIdElement addOriginId(Message message) {
OriginIdElement originId = new OriginIdElement(); OriginIdElement originId = message.getExtension(OriginIdElement.class);
if (originId != null) {
return originId;
}
originId = new OriginIdElement();
message.addExtension(originId); message.addExtension(originId);
// TODO: Find solution to have both the originIds stanzaId and a nice to look at incremental stanzaID. // TODO: Find solution to have both the originIds stanzaId and a nice to look at incremental stanzaID.
// message.setStanzaId(originId.getId()); // message.setStanzaId(originId.getId());
@ -62,7 +67,12 @@ public class OriginIdElement extends StableAndUniqueIdElement {
* @return the added origin-id element. * @return the added origin-id element.
*/ */
public static OriginIdElement addTo(MessageBuilder messageBuilder) { public static OriginIdElement addTo(MessageBuilder messageBuilder) {
OriginIdElement originId = new OriginIdElement(); OriginIdElement originId = messageBuilder.getExtension(OriginIdElement.class);
if (originId != null) {
return originId;
}
originId = new OriginIdElement();
messageBuilder.addExtension(originId); messageBuilder.addExtension(originId);
// TODO: Find solution to have both the originIds stanzaId and a nice to look at incremental stanzaID. // TODO: Find solution to have both the originIds stanzaId and a nice to look at incremental stanzaID.
// message.setStanzaId(originId.getId()); // message.setStanzaId(originId.getId());

View File

@ -0,0 +1,25 @@
/**
*
* Copyright 2021 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.muc;
import org.jivesoftware.smack.packet.MessageBuilder;
public interface MucMessageInterceptor {
void intercept(MessageBuilder messageBuilder, MultiUserChat multiUserChat);
}

View File

@ -23,6 +23,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -156,10 +157,13 @@ public class MultiUserChat {
*/ */
private volatile boolean processedReflectedSelfPresence; private volatile boolean processedReflectedSelfPresence;
private CopyOnWriteArrayList<MucMessageInterceptor> messageInterceptors;
MultiUserChat(XMPPConnection connection, EntityBareJid room, MultiUserChatManager multiUserChatManager) { MultiUserChat(XMPPConnection connection, EntityBareJid room, MultiUserChatManager multiUserChatManager) {
this.connection = connection; this.connection = connection;
this.room = room; this.room = room;
this.multiUserChatManager = multiUserChatManager; this.multiUserChatManager = multiUserChatManager;
this.messageInterceptors = MultiUserChatManager.getMessageInterceptors();
fromRoomFilter = FromMatchesFilter.create(room); fromRoomFilter = FromMatchesFilter.create(room);
fromRoomGroupchatFilter = new AndFilter(fromRoomFilter, MessageTypeFilter.GROUPCHAT); fromRoomGroupchatFilter = new AndFilter(fromRoomFilter, MessageTypeFilter.GROUPCHAT);
@ -778,8 +782,7 @@ public class MultiUserChat {
MUCUserStatusCodeFilter.STATUS_110_PRESENCE_TO_SELF), MUCUserStatusCodeFilter.STATUS_110_PRESENCE_TO_SELF),
new AndFilter(fromRoomFilter, PresenceTypeFilter.ERROR))); new AndFilter(fromRoomFilter, PresenceTypeFilter.ERROR)));
boolean supportsStableId = mucServiceDiscoInfo.containsFeature(MultiUserChatConstants.STABLE_ID_FEATURE); if (serviceSupportsStableIds()) {
if (supportsStableId) {
reflectedLeavePresenceFilters.add(new StanzaIdFilter(leavePresence)); reflectedLeavePresenceFilters.add(new StanzaIdFilter(leavePresence));
} }
@ -2035,6 +2038,10 @@ public class MultiUserChat {
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
*/ */
public void sendMessage(MessageBuilder messageBuilder) throws NotConnectedException, InterruptedException { public void sendMessage(MessageBuilder messageBuilder) throws NotConnectedException, InterruptedException {
for (MucMessageInterceptor interceptor : messageInterceptors) {
interceptor.intercept(messageBuilder, this);
}
Message message = messageBuilder.to(room).ofType(Message.Type.groupchat).build(); Message message = messageBuilder.to(room).ofType(Message.Type.groupchat).build();
connection.sendStanza(message); connection.sendStanza(message);
} }
@ -2118,6 +2125,14 @@ public class MultiUserChat {
return messageListeners.remove(listener); return messageListeners.remove(listener);
} }
public boolean addMessageInterceptor(MucMessageInterceptor interceptor) {
return messageInterceptors.add(interceptor);
}
public boolean removeMessageInterceptor(MucMessageInterceptor interceptor) {
return messageInterceptors.remove(interceptor);
}
/** /**
* Changes the subject within the room. As a default, only users with a role of "moderator" * Changes the subject within the room. As a default, only users with a role of "moderator"
* are allowed to change the subject in a room. Although some rooms may be configured to * are allowed to change the subject in a room. Although some rooms may be configured to
@ -2539,6 +2554,10 @@ public class MultiUserChat {
return connection; return connection;
} }
public boolean serviceSupportsStableIds() {
return mucServiceDiscoInfo.containsFeature(MultiUserChatConstants.STABLE_ID_FEATURE);
}
@Override @Override
public String toString() { public String toString() {
return "MUC: " + room + "(" + connection.getUser() + ")"; return "MUC: " + room + "(" + connection.getUser() + ")";

View File

@ -20,10 +20,12 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -140,6 +142,8 @@ public final class MultiUserChatManager extends Manager {
private static final ExpirationCache<DomainBareJid, DiscoverInfo> KNOWN_MUC_SERVICES = new ExpirationCache<>( private static final ExpirationCache<DomainBareJid, DiscoverInfo> KNOWN_MUC_SERVICES = new ExpirationCache<>(
100, 1000 * 60 * 60 * 24); 100, 1000 * 60 * 60 * 24);
private static final Set<MucMessageInterceptor> DEFAULT_MESSAGE_INTERCEPTORS = new HashSet<>();
private final Set<InvitationListener> invitationsListeners = new CopyOnWriteArraySet<InvitationListener>(); private final Set<InvitationListener> invitationsListeners = new CopyOnWriteArraySet<InvitationListener>();
/** /**
@ -275,6 +279,18 @@ public final class MultiUserChatManager extends Manager {
return multiUserChat; return multiUserChat;
} }
public static boolean addDefaultMessageInterceptor(MucMessageInterceptor messageInterceptor) {
synchronized (DEFAULT_MESSAGE_INTERCEPTORS) {
return DEFAULT_MESSAGE_INTERCEPTORS.add(messageInterceptor);
}
}
public static boolean removeDefaultMessageInterceptor(MucMessageInterceptor messageInterceptor) {
synchronized (DEFAULT_MESSAGE_INTERCEPTORS) {
return DEFAULT_MESSAGE_INTERCEPTORS.remove(messageInterceptor);
}
}
private MultiUserChat createNewMucAndAddToMap(EntityBareJid jid) { private MultiUserChat createNewMucAndAddToMap(EntityBareJid jid) {
MultiUserChat multiUserChat = new MultiUserChat(connection(), jid, this); MultiUserChat multiUserChat = new MultiUserChat(connection(), jid, this);
multiUserChats.put(jid, new WeakReference<MultiUserChat>(multiUserChat)); multiUserChats.put(jid, new WeakReference<MultiUserChat>(multiUserChat));
@ -535,4 +551,10 @@ public final class MultiUserChatManager extends Manager {
void removeJoinedRoom(EntityBareJid room) { void removeJoinedRoom(EntityBareJid room) {
joinedRooms.remove(room); joinedRooms.remove(room);
} }
static CopyOnWriteArrayList<MucMessageInterceptor> getMessageInterceptors() {
synchronized (DEFAULT_MESSAGE_INTERCEPTORS) {
return new CopyOnWriteArrayList<>(DEFAULT_MESSAGE_INTERCEPTORS);
}
}
} }