From e2d206e741a31f94b407fbc10923ee2fd14ab4e1 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Fri, 25 Oct 2019 13:57:18 +0200 Subject: [PATCH] Introduce XMPPConnection.add(Message|Presence)Interceptor add deprecate addStanzaInterceptor(). --- .../smack/AbstractXMPPConnection.java | 124 +++++++++++++++++- .../jivesoftware/smack/XMPPConnection.java | 57 +++++++- .../smack/filter/StanzaFilter.java | 8 +- .../jivesoftware/smack/packet/Message.java | 5 +- .../smack/packet/MessageBuilder.java | 3 +- .../smack/packet/MessageOrPresence.java | 36 +++++ .../packet/MessageOrPresenceBuilder.java | 42 ++++++ .../jivesoftware/smack/packet/Presence.java | 4 +- .../smack/packet/PresenceBuilder.java | 3 +- .../org/jivesoftware/smack/packet/Stanza.java | 8 +- .../jivesoftware/smack/packet/StanzaView.java | 20 +++ .../jivesoftware/smack/util/Predicate.java | 24 ++++ .../chat_markers/ChatMarkersManager.java | 16 +-- .../sid/StableUniqueStanzaIdManager.java | 24 ++-- .../smackx/sid/element/OriginIdElement.java | 18 +++ .../smackx/sid/StableUniqueStanzaIdTest.java | 8 +- .../jivesoftware/smack/chat2/ChatManager.java | 36 +++-- .../chat2/OutgoingChatMessageListener.java | 6 +- .../smackx/caps/EntityCapsManager.java | 37 +++--- .../smackx/chatstates/ChatStateManager.java | 7 +- .../smackx/muc/MultiUserChat.java | 4 +- .../receipts/DeliveryReceiptManager.java | 17 +-- .../smackx/xhtmlim/packet/XHTMLExtension.java | 10 +- ...utgoingMessageListenerIntegrationTest.java | 4 +- 24 files changed, 419 insertions(+), 102 deletions(-) create mode 100644 smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresence.java create mode 100644 smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresenceBuilder.java create mode 100644 smack-core/src/main/java/org/jivesoftware/smack/util/Predicate.java diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index fc957c5fb..42ba0903e 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -100,8 +100,12 @@ import org.jivesoftware.smack.packet.FullyQualifiedElement; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Mechanisms; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.MessageOrPresence; +import org.jivesoftware.smack.packet.MessageOrPresenceBuilder; import org.jivesoftware.smack.packet.Nonza; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.PresenceBuilder; import org.jivesoftware.smack.packet.Session; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.StanzaError; @@ -123,11 +127,13 @@ import org.jivesoftware.smack.sasl.core.SASLAnonymous; import org.jivesoftware.smack.sasl.packet.SaslNonza; import org.jivesoftware.smack.util.Async; import org.jivesoftware.smack.util.CollectionUtil; +import org.jivesoftware.smack.util.Consumer; import org.jivesoftware.smack.util.DNSUtil; import org.jivesoftware.smack.util.MultiMap; import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.ParserUtils; +import org.jivesoftware.smack.util.Predicate; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.dns.HostAddress; import org.jivesoftware.smack.util.dns.SmackDaneProvider; @@ -243,6 +249,10 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { private final Map interceptors = new HashMap<>(); + private final Map, GenericInterceptorWrapper> messageInterceptors = new HashMap<>(); + + private final Map, GenericInterceptorWrapper> presenceInterceptors = new HashMap<>(); + private XmlEnvironment incomingStreamXmlEnvironment; protected XmlEnvironment outgoingStreamXmlEnvironment; @@ -849,8 +859,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } // Invoke interceptors for the new stanza that is about to be sent. Interceptors may modify // the content of the stanza. - firePacketInterceptors(stanza); - sendStanzaInternal(stanza); + Stanza stanzaAfterInterceptors = firePacketInterceptors(stanza); + sendStanzaInternal(stanzaAfterInterceptors); } /** @@ -1204,6 +1214,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { }); } + @Deprecated @Override public void addStanzaInterceptor(StanzaListener packetInterceptor, StanzaFilter packetFilter) { @@ -1216,6 +1227,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } } + @Deprecated @Override public void removeStanzaInterceptor(StanzaListener packetInterceptor) { synchronized (interceptors) { @@ -1223,15 +1235,83 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } } + private static , MP extends MessageOrPresence> void addInterceptor( + Map, GenericInterceptorWrapper> interceptors, Consumer interceptor, + Predicate filter) { + Objects.requireNonNull(interceptor, "Interceptor must not be null"); + + GenericInterceptorWrapper interceptorWrapper = new GenericInterceptorWrapper<>(interceptor, filter); + + synchronized (interceptors) { + interceptors.put(interceptor, interceptorWrapper); + } + } + + private static , MP extends MessageOrPresence> void removeInterceptor( + Map, GenericInterceptorWrapper> interceptors, Consumer interceptor) { + synchronized (interceptors) { + interceptors.remove(interceptor); + } + } + + @Override + public void addMessageInterceptor(Consumer messageInterceptor, Predicate messageFilter) { + addInterceptor(messageInterceptors, messageInterceptor, messageFilter); + } + + @Override + public void removeMessageInterceptor(Consumer messageInterceptor) { + removeInterceptor(messageInterceptors, messageInterceptor); + } + + @Override + public void addPresenceInterceptor(Consumer presenceInterceptor, + Predicate presenceFilter) { + addInterceptor(presenceInterceptors, presenceInterceptor, presenceFilter); + } + + @Override + public void removePresenceInterceptor(Consumer presenceInterceptor) { + removeInterceptor(presenceInterceptors, presenceInterceptor); + } + + private static , MP extends MessageOrPresence> MP fireMessageOrPresenceInterceptors( + MP messageOrPresence, Map, GenericInterceptorWrapper> interceptors) { + List> interceptorsToInvoke = new LinkedList<>(); + synchronized (interceptors) { + for (GenericInterceptorWrapper interceptorWrapper : interceptors.values()) { + if (interceptorWrapper.filterMatches(messageOrPresence)) { + Consumer interceptor = interceptorWrapper.getInterceptor(); + interceptorsToInvoke.add(interceptor); + } + } + } + + // Avoid transforming the stanza to a builder if there is no interceptor. + if (interceptorsToInvoke.isEmpty()) { + return messageOrPresence; + } + + MPB builder = messageOrPresence.asBuilder(); + for (Consumer interceptor : interceptorsToInvoke) { + interceptor.accept(builder); + } + + // Now that the interceptors have (probably) modified the stanza in its builder form, we need to re-assemble it. + messageOrPresence = builder.build(); + return messageOrPresence; + } + /** * Process interceptors. Interceptors may modify the stanza that is about to be sent. * Since the thread that requested to send the stanza will invoke all interceptors, it * is important that interceptors perform their work as soon as possible so that the * thread does not remain blocked for a long period. * - * @param packet the stanza that is going to be sent to the server + * @param packet the stanza that is going to be sent to the server. + * @return the, potentially modified stanza, after the interceptors are run. */ - private void firePacketInterceptors(Stanza packet) { + private Stanza firePacketInterceptors(Stanza packet) { List interceptorsToInvoke = new LinkedList<>(); synchronized (interceptors) { for (InterceptorWrapper interceptorWrapper : interceptors.values()) { @@ -1247,6 +1327,22 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { LOGGER.log(Level.SEVERE, "Packet interceptor threw exception", e); } } + + final Stanza stanzaAfterInterceptors; + if (packet instanceof Message) { + Message message = (Message) packet; + stanzaAfterInterceptors = fireMessageOrPresenceInterceptors(message, messageInterceptors); + } + else if (packet instanceof Presence) { + Presence presence = (Presence) packet; + stanzaAfterInterceptors = fireMessageOrPresenceInterceptors(presence, presenceInterceptors); + } else { + // We do not (yet) support interceptors for IQ stanzas. + assert packet instanceof IQ; + stanzaAfterInterceptors = packet; + } + + return stanzaAfterInterceptors; } /** @@ -1674,6 +1770,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { /** * A wrapper class to associate a stanza filter with an interceptor. */ + @Deprecated + // TODO: Remove once addStanzaInterceptor is gone. protected static class InterceptorWrapper { private final StanzaListener packetInterceptor; @@ -1699,6 +1797,24 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } } + private static final class GenericInterceptorWrapper, MP extends MessageOrPresence> { + private final Consumer stanzaInterceptor; + private final Predicate stanzaFilter; + + private GenericInterceptorWrapper(Consumer stanzaInterceptor, Predicate stanzaFilter) { + this.stanzaInterceptor = stanzaInterceptor; + this.stanzaFilter = stanzaFilter; + } + + private boolean filterMatches(MP stanza) { + return stanzaFilter == null || stanzaFilter.test(stanza); + } + + public Consumer getInterceptor() { + return stanzaInterceptor; + } + } + @Override public int getConnectionCounter() { return connectionCounterValue; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java index d7df0a825..842007f1e 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java @@ -27,9 +27,15 @@ import org.jivesoftware.smack.iqrequest.IQRequestHandler; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.FullyQualifiedElement; import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Nonza; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.PresenceBuilder; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.StanzaFactory; +import org.jivesoftware.smack.util.Consumer; +import org.jivesoftware.smack.util.Predicate; import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.EntityFullJid; @@ -361,7 +367,7 @@ public interface XMPPConnection { boolean removeStanzaListener(StanzaListener stanzaListener); /** - * Registers a synchronous stanza listener with this connection. A stanza listener will be invoked only when + * Registers a synchronous stanza listener with this connection. A stanza listener will be invoked only when * an incoming stanza is received. A stanza filter determines which stanzas will be delivered to the listener. If * the same stanza listener is added again with a different filter, only the new filter will be used. *

@@ -446,16 +452,65 @@ public interface XMPPConnection { * * @param stanzaInterceptor the stanza interceptor to notify of stanzas about to be sent. * @param stanzaFilter the stanza filter to use. + * @deprecated use {@link #addMessageInterceptor(Consumer, Predicate)} or {@link #addPresenceInterceptor(Consumer, Predicate)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. void addStanzaInterceptor(StanzaListener stanzaInterceptor, StanzaFilter stanzaFilter); /** * Removes a stanza interceptor. * * @param stanzaInterceptor the stanza interceptor to remove. + * @deprecated use {@link #removeMessageInterceptor(Consumer)} or {@link #removePresenceInterceptor(Consumer)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. void removeStanzaInterceptor(StanzaListener stanzaInterceptor); + /** + * Registers a stanza interceptor with this connection. The interceptor will be + * invoked every time a stanza is about to be sent by this connection. Interceptors + * may modify the stanza to be sent. A stanza filter determines which stanzas + * will be delivered to the interceptor. + * + *

+ * NOTE: For a similar functionality on incoming stanzas, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}. + *

+ * + * @param messageInterceptor the stanza interceptor to notify of stanzas about to be sent. + * @param messageFilter the stanza filter to use. + */ + void addMessageInterceptor(Consumer messageInterceptor, Predicate messageFilter); + + /** + * Removes a message interceptor. + * + * @param messageInterceptor the message interceptor to remove. + */ + void removeMessageInterceptor(Consumer messageInterceptor); + + /** + * Registers a stanza interceptor with this connection. The interceptor will be + * invoked every time a stanza is about to be sent by this connection. Interceptors + * may modify the stanza to be sent. A stanza filter determines which stanzas + * will be delivered to the interceptor. + * + *

+ * NOTE: For a similar functionality on incoming stanzas, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}. + *

+ * + * @param presenceInterceptor the stanza interceptor to notify of stanzas about to be sent. + * @param presenceFilter the stanza filter to use. + */ + void addPresenceInterceptor(Consumer presenceInterceptor, Predicate presenceFilter); + + /** + * Removes a presence interceptor. + * + * @param presenceInterceptor the stanza interceptor to remove. + */ + void removePresenceInterceptor(Consumer presenceInterceptor); /** * Returns the current value of the reply timeout in milliseconds for request for this * XMPPConnection instance. diff --git a/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java b/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java index db0d1da72..f37d08b11 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java @@ -18,6 +18,7 @@ package org.jivesoftware.smack.filter; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.util.Predicate; /** * Defines a way to filter stanzas for particular attributes. Stanza filters are used when @@ -51,7 +52,7 @@ import org.jivesoftware.smack.packet.Stanza; * @see org.jivesoftware.smack.StanzaListener * @author Matt Tucker */ -public interface StanzaFilter { +public interface StanzaFilter extends Predicate { /** * Tests whether or not the specified stanza should pass the filter. @@ -60,4 +61,9 @@ public interface StanzaFilter { * @return true if and only if stanza passes the filter. */ boolean accept(Stanza stanza); + + @Override + default boolean test(Stanza stanza) { + return accept(stanza); + } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java index ef3dd9aec..58d69da59 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java @@ -60,7 +60,8 @@ import org.jxmpp.stringprep.XmppStringprepException; * * @author Matt Tucker */ -public final class Message extends Stanza implements MessageView, TypedCloneable { +public final class Message extends MessageOrPresence + implements MessageView, TypedCloneable { public static final String ELEMENT = "message"; public static final String BODY = "body"; @@ -534,6 +535,7 @@ public final class Message extends Stanza implements MessageView, TypedCloneable return ELEMENT; } + @Override public MessageBuilder asBuilder() { return StanzaBuilder.buildMessageFrom(this, getStanzaId()); } @@ -664,6 +666,7 @@ public final class Message extends Stanza implements MessageView, TypedCloneable public static final String ELEMENT = "body"; public static final String NAMESPACE = StreamOpen.CLIENT_NAMESPACE; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); enum BodyElementNamespace { client(StreamOpen.CLIENT_NAMESPACE), diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageBuilder.java index b73880d0c..027e2b0cc 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageBuilder.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageBuilder.java @@ -22,7 +22,7 @@ import org.jivesoftware.smack.packet.id.StanzaIdSource; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.ToStringUtil; -public final class MessageBuilder extends StanzaBuilder implements MessageView { +public final class MessageBuilder extends MessageOrPresenceBuilder implements MessageView { static final MessageBuilder EMPTY = new MessageBuilder(() -> { return null; }); @@ -153,6 +153,7 @@ public final class MessageBuilder extends StanzaBuilder implemen return this; } + @Override public Message build() { return new Message(this); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresence.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresence.java new file mode 100644 index 000000000..c885e941c --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresence.java @@ -0,0 +1,36 @@ +/** + * + * Copyright 2019 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.smack.packet; + +public abstract class MessageOrPresence> extends Stanza { + + @Deprecated + // TODO: Remove in Smack 4.5. + protected MessageOrPresence() { + } + + protected MessageOrPresence(StanzaBuilder stanzaBuilder) { + super(stanzaBuilder); + } + + protected MessageOrPresence(Stanza other) { + super(other); + } + + public abstract MPB asBuilder(); + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresenceBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresenceBuilder.java new file mode 100644 index 000000000..9a3ff66a0 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresenceBuilder.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2019 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.smack.packet; + +import org.jivesoftware.smack.packet.id.StanzaIdSource; + +public abstract class MessageOrPresenceBuilder>, SB extends StanzaBuilder> + extends StanzaBuilder { + + protected MessageOrPresenceBuilder(Stanza stanza, StanzaIdSource stanzaIdSource) { + super(stanza, stanzaIdSource); + } + + protected MessageOrPresenceBuilder(Stanza stanza, String stanzaId) { + super(stanza, stanzaId); + } + + protected MessageOrPresenceBuilder(StanzaIdSource stanzaIdSource) { + super(stanzaIdSource); + } + + protected MessageOrPresenceBuilder(String stanzaId) { + super(stanzaId); + } + + public abstract MP build(); + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java index 8a8db7030..9a1d1a43d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java @@ -61,7 +61,8 @@ import org.jxmpp.jid.Jid; * * @author Matt Tucker */ -public final class Presence extends Stanza implements PresenceView, TypedCloneable { +public final class Presence extends MessageOrPresence + implements PresenceView, TypedCloneable { public static final String ELEMENT = "presence"; @@ -277,6 +278,7 @@ public final class Presence extends Stanza implements PresenceView, TypedCloneab return ELEMENT; } + @Override public PresenceBuilder asBuilder() { return StanzaBuilder.buildPresenceFrom(this, getStanzaId()); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/PresenceBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/PresenceBuilder.java index 795c9a824..9c34fb89c 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/PresenceBuilder.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/PresenceBuilder.java @@ -21,7 +21,7 @@ import org.jivesoftware.smack.packet.id.StanzaIdSource; import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.ToStringUtil; -public final class PresenceBuilder extends StanzaBuilder implements PresenceView { +public final class PresenceBuilder extends MessageOrPresenceBuilder implements PresenceView { static final PresenceBuilder EMPTY = new PresenceBuilder(() -> { return null; }); @@ -102,6 +102,7 @@ public final class PresenceBuilder extends StanzaBuilder implem return this; } + @Override public Presence build() { return new Presence(this); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Stanza.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Stanza.java index b884468f7..4207efb6d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Stanza.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Stanza.java @@ -456,12 +456,8 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement { } } - /** - * Check if a stanza extension with the given namespace exists. - * - * @param namespace TODO javadoc me please - * @return true if a stanza extension exists, false otherwise. - */ + // Overridden in order to avoid an extra copy. + @Override public boolean hasExtension(String namespace) { synchronized (extensionElements) { for (ExtensionElement packetExtension : extensionElements.values()) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaView.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaView.java index 4de119fef..ff9874f13 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaView.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaView.java @@ -63,6 +63,26 @@ public interface StanzaView extends XmlLangElement { E getExtension(QName qname); + default boolean hasExtension(QName qname) { + return getExtension(qname) != null; + } + + /** + * Check if a extension element with the given namespace exists. + * + * @param namespace the namespace of the extension element to check for. + * @return true if a stanza extension exists, false otherwise. + */ + default boolean hasExtension(String namespace) { + for (ExtensionElement packetExtension : getExtensions()) { + if (packetExtension.getNamespace().equals(namespace)) { + return true; + } + } + + return false; + } + @SuppressWarnings("unchecked") default E getExtension(Class extensionElementClass) { QName qname = XmppElementUtil.getQNameFor(extensionElementClass); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/Predicate.java b/smack-core/src/main/java/org/jivesoftware/smack/util/Predicate.java new file mode 100644 index 000000000..ad4c11d0c --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/Predicate.java @@ -0,0 +1,24 @@ +/** + * + * Copyright 2019 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.smack.util; + +// TODO: Replace with java.util.function.Predicate once Smack's minimum Android SDK level is 24 or higher. +public interface Predicate { + + boolean test(T t); + +} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java index 7854204be..b2f99bd76 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java @@ -120,18 +120,10 @@ public final class ChatMarkersManager extends Manager { chatManager = ChatManager.getInstanceFor(connection); - connection.addStanzaInterceptor(new StanzaListener() { - @Override - public void processStanza(Stanza packet) - throws - NotConnectedException, - InterruptedException, - SmackException.NotLoggedInException { - Message message = (Message) packet; - // add a markable extension - message.addExtension(ChatMarkersElements.MarkableExtension.INSTANCE); - } - }, OUTGOING_MESSAGE_FILTER); + connection.addMessageInterceptor(mb -> mb.addExtension(ChatMarkersElements.MarkableExtension.INSTANCE), + m -> { + return OUTGOING_MESSAGE_FILTER.accept(m); + }); connection.addSyncStanzaListener(new StanzaListener() { @Override diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdManager.java index fbe507e4e..f0515a74b 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdManager.java @@ -21,7 +21,6 @@ import java.util.WeakHashMap; import org.jivesoftware.smack.ConnectionCreationListener; import org.jivesoftware.smack.Manager; -import org.jivesoftware.smack.StanzaListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnectionRegistry; import org.jivesoftware.smack.filter.AndFilter; @@ -31,8 +30,9 @@ import org.jivesoftware.smack.filter.StanzaExtensionFilter; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.filter.ToTypeFilter; import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Stanza; - +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.util.Consumer; +import org.jivesoftware.smack.util.Predicate; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.sid.element.OriginIdElement; @@ -62,12 +62,12 @@ public final class StableUniqueStanzaIdManager extends Manager { private static final StanzaFilter ORIGIN_ID_FILTER = new StanzaExtensionFilter(OriginIdElement.ELEMENT, NAMESPACE); // Listener for outgoing stanzas that adds origin-ids to outgoing stanzas. - private static final StanzaListener ADD_ORIGIN_ID_INTERCEPTOR = new StanzaListener() { - @Override - public void processStanza(Stanza stanza) { - Message message = (Message) stanza; - OriginIdElement.addOriginId(message); - } + private static final Consumer ADD_ORIGIN_ID_INTERCEPTOR = mb -> OriginIdElement.addOriginId(mb); + + // We need a filter for outgoing messages that do not carry an origin-id already. + private static final StanzaFilter ADD_ORIGIN_ID_FILTER = new AndFilter(OUTGOING_FILTER, new NotFilter(ORIGIN_ID_FILTER)); + private static final Predicate ADD_ORIGIN_ID_PREDICATE = m -> { + return ADD_ORIGIN_ID_FILTER.accept(m); }; static { @@ -112,10 +112,8 @@ public final class StableUniqueStanzaIdManager extends Manager { * Start appending origin-id elements to outgoing stanzas and add the feature to disco. */ public synchronized void enable() { + connection().addMessageInterceptor(ADD_ORIGIN_ID_INTERCEPTOR, ADD_ORIGIN_ID_PREDICATE); ServiceDiscoveryManager.getInstanceFor(connection()).addFeature(NAMESPACE); - // We need a filter for outgoing messages that do not carry an origin-id already - StanzaFilter filter = new AndFilter(OUTGOING_FILTER, new NotFilter(ORIGIN_ID_FILTER)); - connection().addStanzaInterceptor(ADD_ORIGIN_ID_INTERCEPTOR, filter); } /** @@ -123,7 +121,7 @@ public final class StableUniqueStanzaIdManager extends Manager { */ public synchronized void disable() { ServiceDiscoveryManager.getInstanceFor(connection()).removeFeature(NAMESPACE); - connection().removeStanzaInterceptor(ADD_ORIGIN_ID_INTERCEPTOR); + connection().removeMessageInterceptor(ADD_ORIGIN_ID_INTERCEPTOR); } /** diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java index 4291084bb..10531c4e3 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java @@ -17,6 +17,7 @@ package org.jivesoftware.smackx.sid.element; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager; @@ -38,7 +39,10 @@ public class OriginIdElement extends StableAndUniqueIdElement { * * @param message message. * @return the added origin-id element. + * @deprecated use {@link #addOriginId(MessageBuilder)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public static OriginIdElement addOriginId(Message message) { OriginIdElement originId = new OriginIdElement(); message.addExtension(originId); @@ -47,6 +51,20 @@ public class OriginIdElement extends StableAndUniqueIdElement { return originId; } + /** + * Add an origin-id element to a message and set the stanzas id to the same id as in the origin-id element. + * + * @param messageBuilder the message builder to add an origin ID to. + * @return the added origin-id element. + */ + public static OriginIdElement addOriginId(MessageBuilder messageBuilder) { + OriginIdElement originId = new OriginIdElement(); + messageBuilder.addExtension(originId); + // TODO: Find solution to have both the originIds stanzaId and a nice to look at incremental stanzaID. + // message.setStanzaId(originId.getId()); + return originId; + } + /** * Return true, if the message contains a origin-id element. * diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdTest.java index 3e6ac3027..c9c4367a8 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdTest.java @@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smack.test.util.TestUtils; @@ -71,12 +72,15 @@ public class StableUniqueStanzaIdTest extends SmackTestSuite { @Test public void fromMessageTest() { - Message message = StanzaBuilder.buildMessage().build(); + MessageBuilder messageBuilder = StanzaBuilder.buildMessage(); + + Message message = messageBuilder.build(); assertFalse(OriginIdElement.hasOriginId(message)); assertFalse(StanzaIdElement.hasStanzaId(message)); - OriginIdElement.addOriginId(message); + OriginIdElement.addOriginId(messageBuilder); + message = messageBuilder.build(); assertTrue(OriginIdElement.hasOriginId(message)); StanzaIdElement stanzaId = new StanzaIdElement("alice@wonderland.lit"); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/ChatManager.java b/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/ChatManager.java index 4066b1d4d..e8349b6c6 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/ChatManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/ChatManager.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017-2018 Florian Schmaus. + * Copyright 2017-2019 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ 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; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.filter.AndFilter; @@ -36,6 +35,7 @@ import org.jivesoftware.smack.filter.StanzaExtensionFilter; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.filter.ToTypeFilter; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageView; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.roster.AbstractRosterListener; @@ -124,22 +124,20 @@ public final class ChatManager extends Manager { } }, INCOMING_MESSAGE_FILTER); - connection.addStanzaInterceptor(new StanzaListener() { - @Override - public void processStanza(Stanza stanza) throws NotConnectedException, InterruptedException { - Message message = (Message) stanza; - if (!shouldAcceptMessage(message)) { - return; - } - - final EntityBareJid to = message.getTo().asEntityBareJidOrThrow(); - final Chat chat = chatWith(to); - - for (OutgoingChatMessageListener listener : outgoingListeners) { - listener.newOutgoingMessage(to, message, chat); - } + connection.addMessageInterceptor(messageBuilder -> { + if (!shouldAcceptMessage(messageBuilder)) { + return; } - }, OUTGOING_MESSAGE_FILTER); + + final EntityBareJid to = messageBuilder.getTo().asEntityBareJidOrThrow(); + final Chat chat = chatWith(to); + + for (OutgoingChatMessageListener listener : outgoingListeners) { + listener.newOutgoingMessage(to, messageBuilder, chat); + } + }, m -> { + return OUTGOING_MESSAGE_FILTER.accept(m); + }); Roster roster = Roster.getInstanceFor(connection); roster.addRosterListener(new AbstractRosterListener() { @@ -181,8 +179,8 @@ public final class ChatManager extends Manager { }); } - private boolean shouldAcceptMessage(Message message) { - if (!message.getBodies().isEmpty()) { + private boolean shouldAcceptMessage(MessageView message) { + if (message.hasExtension(Message.Body.QNAME)) { return true; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/OutgoingChatMessageListener.java b/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/OutgoingChatMessageListener.java index 4ceba2c6f..75a9918fd 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/OutgoingChatMessageListener.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/OutgoingChatMessageListener.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * Copyright 2017-2019 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,12 @@ */ package org.jivesoftware.smack.chat2; -import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jxmpp.jid.EntityBareJid; public interface OutgoingChatMessageListener { - void newOutgoingMessage(EntityBareJid to, Message message, Chat chat); + void newOutgoingMessage(EntityBareJid to, MessageBuilder messageBuilder, Chat chat); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java index 8d9b0df7f..c6b12c036 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java @@ -51,9 +51,11 @@ import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.PresenceBuilder; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.roster.AbstractPresenceEventListener; import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.util.Consumer; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.stringencoder.Base64; @@ -308,6 +310,15 @@ public final class EntityCapsManager extends Manager { */ private String entityNode = DEFAULT_ENTITY_NODE; + // Intercept presence packages and add caps data when intended. + // XEP-0115 specifies that a client SHOULD include entity capabilities + // with every presence notification it sends. + private final Consumer presenceInterceptor = presenceBuilder -> { + CapsVersionAndHash capsVersionAndHash = getCapsVersionAndHash(); + CapsExtension caps = new CapsExtension(entityNode, capsVersionAndHash.version, capsVersionAndHash.hash); + presenceBuilder.overrideExtension(caps); + }; + private EntityCapsManager(XMPPConnection connection) { super(connection); this.sdm = ServiceDiscoveryManager.getInstanceFor(connection); @@ -379,23 +390,9 @@ public final class EntityCapsManager extends Manager { } }, PresenceTypeFilter.OUTGOING_PRESENCE_BROADCAST); - // Intercept presence packages and add caps data when intended. - // XEP-0115 specifies that a client SHOULD include entity capabilities - // with every presence notification it sends. - StanzaListener packetInterceptor = new StanzaListener() { - @Override - public void processStanza(Stanza packet) { - if (!entityCapsEnabled) { - // Be sure to not send stanzas with the caps extension if it's not enabled - packet.removeExtension(CapsExtension.ELEMENT, CapsExtension.NAMESPACE); - return; - } - CapsVersionAndHash capsVersionAndHash = getCapsVersionAndHash(); - CapsExtension caps = new CapsExtension(entityNode, capsVersionAndHash.version, capsVersionAndHash.hash); - packet.overrideExtension(caps); - } - }; - connection.addStanzaInterceptor(packetInterceptor, PresenceTypeFilter.AVAILABLE); + + enableEntityCaps(); + // It's important to do this as last action. Since it changes the // behavior of the SDM in some ways sdm.addEntityCapabilitiesChangedListener(new EntityCapabilitiesChangedListener() { @@ -424,6 +421,10 @@ public final class EntityCapsManager extends Manager { } public synchronized void enableEntityCaps() { + connection().addPresenceInterceptor(presenceInterceptor, p -> { + return PresenceTypeFilter.AVAILABLE.accept(p); + }); + // Add Entity Capabilities (XEP-0115) feature node. sdm.addFeature(NAMESPACE); updateLocalEntityCaps(); @@ -433,6 +434,8 @@ public final class EntityCapsManager extends Manager { public synchronized void disableEntityCaps() { entityCapsEnabled = false; sdm.removeFeature(NAMESPACE); + + connection().removePresenceInterceptor(presenceInterceptor); } public boolean entityCapsEnabled() { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/chatstates/ChatStateManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/chatstates/ChatStateManager.java index 0c4c9f4ef..8e5060172 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/chatstates/ChatStateManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/chatstates/ChatStateManager.java @@ -37,11 +37,11 @@ import org.jivesoftware.smack.chat2.OutgoingChatMessageListener; import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.filter.FromTypeFilter; import org.jivesoftware.smack.filter.MessageTypeFilter; -import org.jivesoftware.smack.filter.NotFilter; import org.jivesoftware.smack.filter.StanzaExtensionFilter; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.StanzaBuilder; @@ -73,7 +73,6 @@ public final class ChatStateManager extends Manager { private static final Map INSTANCES = new WeakHashMap<>(); - private static final StanzaFilter filter = new NotFilter(new StanzaExtensionFilter(NAMESPACE)); private static final StanzaFilter INCOMING_MESSAGE_FILTER = new AndFilter(MessageTypeFilter.NORMAL_OR_CHAT, FromTypeFilter.ENTITY_FULL_JID); private static final StanzaFilter INCOMING_CHAT_STATE_FILTER = new AndFilter(INCOMING_MESSAGE_FILTER, new StanzaExtensionFilter(NAMESPACE)); @@ -117,13 +116,13 @@ public final class ChatStateManager extends Manager { ChatManager chatManager = ChatManager.getInstanceFor(connection); chatManager.addOutgoingListener(new OutgoingChatMessageListener() { @Override - public void newOutgoingMessage(EntityBareJid to, Message message, Chat chat) { + public void newOutgoingMessage(EntityBareJid to, MessageBuilder message, Chat chat) { if (chat == null) { return; } // if message already has a chatStateExtension, then do nothing, - if (!filter.accept(message)) { + if (message.hasExtension(ChatStateExtension.NAMESPACE)) { return; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java index b37f367ad..8aa301fa0 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java @@ -358,7 +358,7 @@ public class MultiUserChat { ); // @formatter:on connection.addSyncStanzaListener(declinesListener, new AndFilter(fromRoomFilter, DECLINE_FILTER)); - connection.addStanzaInterceptor(presenceInterceptor, new AndFilter(ToMatchesFilter.create(room), + connection.addStanzaSendingListener(presenceInterceptor, new AndFilter(ToMatchesFilter.create(room), StanzaTypeFilter.PRESENCE)); messageCollector = connection.createStanzaCollector(fromRoomGroupchatFilter); @@ -2122,7 +2122,7 @@ public class MultiUserChat { connection.removeSyncStanzaListener(presenceListener); connection.removeSyncStanzaListener(subjectListener); connection.removeSyncStanzaListener(declinesListener); - connection.removeStanzaInterceptor(presenceInterceptor); + connection.removeStanzaSendingListener(presenceInterceptor); if (messageCollector != null) { messageCollector.cancel(); messageCollector = null; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/receipts/DeliveryReceiptManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/receipts/DeliveryReceiptManager.java index bab23aa5e..b069709e1 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/receipts/DeliveryReceiptManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/receipts/DeliveryReceiptManager.java @@ -38,9 +38,11 @@ import org.jivesoftware.smack.filter.StanzaExtensionFilter; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.util.Consumer; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; @@ -271,13 +273,7 @@ public final class DeliveryReceiptManager extends Manager { ); // @formatter:on - private static final StanzaListener AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER = new StanzaListener() { - @Override - public void processStanza(Stanza packet) throws NotConnectedException { - Message message = (Message) packet; - DeliveryReceiptRequest.addTo(message); - } - }; + private static final Consumer AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER = mb -> DeliveryReceiptRequest.addTo(mb); /** * Enables automatic requests of delivery receipts for outgoing messages of @@ -288,8 +284,9 @@ public final class DeliveryReceiptManager extends Manager { * @see #dontAutoAddDeliveryReceiptRequests() */ public void autoAddDeliveryReceiptRequests() { - connection().addStanzaInterceptor(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER, - MESSAGES_TO_REQUEST_RECEIPTS_FOR); + connection().addMessageInterceptor(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER, m -> { + return MESSAGES_TO_REQUEST_RECEIPTS_FOR.accept(m); + }); } /** @@ -299,7 +296,7 @@ public final class DeliveryReceiptManager extends Manager { * @see #autoAddDeliveryReceiptRequests() */ public void dontAutoAddDeliveryReceiptRequests() { - connection().removeStanzaInterceptor(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER); + connection().removeMessageInterceptor(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER); } /** diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java index a87124fa5..39713f951 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java @@ -21,8 +21,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageView; import org.jivesoftware.smack.util.XmlStringBuilder; /** @@ -40,6 +42,8 @@ public class XHTMLExtension implements ExtensionElement { public static final String ELEMENT = "html"; public static final String NAMESPACE = "http://jabber.org/protocol/xhtml-im"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); + private final List bodies = new ArrayList<>(); /** @@ -125,7 +129,7 @@ public class XHTMLExtension implements ExtensionElement { } } - public static XHTMLExtension from(Message message) { - return message.getExtension(ELEMENT, NAMESPACE); + public static XHTMLExtension from(MessageView message) { + return message.getExtension(QNAME); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smack/chat2/OutgoingMessageListenerIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/chat2/OutgoingMessageListenerIntegrationTest.java index 6ea68d7f4..c284495fa 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/chat2/OutgoingMessageListenerIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/chat2/OutgoingMessageListenerIntegrationTest.java @@ -17,6 +17,7 @@ package org.jivesoftware.smack.chat2; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.util.StringUtils; import org.igniterealtime.smack.inttest.SmackIntegrationTest; @@ -36,7 +37,8 @@ public class OutgoingMessageListenerIntegrationTest extends AbstractChatIntegrat final SimpleResultSyncPoint syncPoint = new SimpleResultSyncPoint(); final OutgoingChatMessageListener listener = new OutgoingChatMessageListener() { @Override - public void newOutgoingMessage(EntityBareJid to, Message message, Chat chat) { + public void newOutgoingMessage(EntityBareJid to, MessageBuilder messageBuilder, Chat chat) { + Message message = messageBuilder.build(); if (message.getBody().equals(body)) { syncPoint.signal(); }