diff --git a/documentation/overview.md b/documentation/overview.md index 79049183b..2e169a8b6 100644 --- a/documentation/overview.md +++ b/documentation/overview.md @@ -15,7 +15,11 @@ Smack Key Advantages AbstractXMPPConnection connection = new XMPPTCPConnection("mtucker", "password", "jabber.org"); connection.connect().login(); - Message message = new Message("jsmith@jivesoftware.com", "Howdy! How are you?"); + Message message = connection.getStanzaFactory() + .buildMessageStanza() + .to("jsmith@jivesoftware.com") + .setBody("Howdy! How are you?") + .build(); connection.sendStanza(message); ``` diff --git a/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java b/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java index 475bd1403..824dedc44 100644 --- a/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java +++ b/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java @@ -517,8 +517,8 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection { if ("urn:ietf:params:xml:ns:xmpp-streams".equals(parser.getNamespace(null))) { throw new StreamErrorException(PacketParserUtils.parseStreamError(parser)); } else { - StanzaError.Builder builder = PacketParserUtils.parseError(parser); - throw new XMPPException.XMPPErrorException(null, builder.build()); + StanzaError stanzaError = PacketParserUtils.parseError(parser); + throw new XMPPException.XMPPErrorException(null, stanzaError); } default: parseAndProcessNonza(parser); 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 fca97f54c..fc957c5fb 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -105,11 +105,13 @@ import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Session; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.StanzaError; +import org.jivesoftware.smack.packet.StanzaFactory; import org.jivesoftware.smack.packet.StartTls; import org.jivesoftware.smack.packet.StreamError; import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.packet.TopLevelStreamElement; import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.packet.id.StanzaIdSource; import org.jivesoftware.smack.parsing.ParsingExceptionCallback; import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.provider.ExtensionElementProvider; @@ -402,6 +404,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { private final Map setIqRequestHandler = new HashMap<>(); private final Map getIqRequestHandler = new HashMap<>(); + private final StanzaFactory stanzaFactory; + /** * Create a new XMPPConnection to an XMPP server. * @@ -440,6 +444,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { for (ConnectionCreationListener listener : XMPPConnectionRegistry.getConnectionCreationListeners()) { listener.connectionCreated(this); } + + StanzaIdSource stanzaIdSource = configuration.constructStanzaIdSource(); + stanzaFactory = new StanzaFactory(stanzaIdSource); } /** @@ -733,7 +740,11 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { // eventually load the roster. And we should load the roster before we // send the initial presence. if (config.isSendPresence() && !resumed) { - sendStanza(new Presence(Presence.Type.available)); + Presence availablePresence = getStanzaFactory() + .buildPresenceStanza() + .ofType(Presence.Type.available) + .build(); + sendStanza(availablePresence); } } @@ -814,6 +825,11 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } } + @Override + public final StanzaFactory getStanzaFactory() { + return stanzaFactory; + } + @Override public final void sendStanza(Stanza stanza) throws NotConnectedException, InterruptedException { Objects.requireNonNull(stanza, "Stanza must not be null"); @@ -893,7 +909,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { public void disconnect() { Presence unavailablePresence = null; if (isAuthenticated()) { - unavailablePresence = new Presence(Presence.Type.unavailable); + unavailablePresence = getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.unavailable) + .build(); } try { disconnect(unavailablePresence); @@ -1416,7 +1434,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { // If the IQ stanza is of type "get" or "set" with no registered IQ request handler, then answer an // IQ of type 'error' with condition 'service-unavailable'. final ErrorIQ errorIQ = IQ.createErrorResponse(iq, StanzaError.getBuilder( - replyCondition)); + replyCondition).build()); // Use async sendStanza() here, since if sendStanza() would block, then some connections, e.g. // XmppNioTcpConnection, would deadlock, as this operation is performed in the same thread that is asyncGo(() -> { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java index 7aa8c7acb..33d1bfdd4 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java @@ -36,6 +36,9 @@ import javax.net.ssl.X509TrustManager; import javax.security.auth.callback.CallbackHandler; import org.jivesoftware.smack.debugger.SmackDebuggerFactory; +import org.jivesoftware.smack.packet.id.StandardStanzaIdSource; +import org.jivesoftware.smack.packet.id.StanzaIdSource; +import org.jivesoftware.smack.packet.id.StanzaIdSourceFactory; import org.jivesoftware.smack.proxy.ProxyInfo; import org.jivesoftware.smack.sasl.SASLMechanism; import org.jivesoftware.smack.sasl.core.SASLAnonymous; @@ -159,6 +162,8 @@ public abstract class ConnectionConfiguration { private final boolean compressionEnabled; + private final StanzaIdSourceFactory stanzaIdSourceFactory; + protected ConnectionConfiguration(Builder builder) { authzid = builder.authzid; username = builder.username; @@ -213,6 +218,8 @@ public abstract class ConnectionConfiguration { compressionEnabled = builder.compressionEnabled; + stanzaIdSourceFactory = builder.stanzaIdSourceFactory; + // If the enabledSaslmechanisms are set, then they must not be empty assert enabledSaslMechanisms == null || !enabledSaslMechanisms.isEmpty(); @@ -568,6 +575,10 @@ public abstract class ConnectionConfiguration { return Collections.unmodifiableSet(enabledSaslMechanisms); } + StanzaIdSource constructStanzaIdSource() { + return stanzaIdSourceFactory.constructStanzaIdSource(); + } + /** * A builder for XMPP connection configurations. *

@@ -612,6 +623,7 @@ public abstract class ConnectionConfiguration { private Set enabledSaslMechanisms; private X509TrustManager customX509TrustManager; private boolean compressionEnabled = false; + private StanzaIdSourceFactory stanzaIdSourceFactory = new StandardStanzaIdSource.Factory(); protected Builder() { if (SmackConfiguration.DEBUG) { @@ -1134,6 +1146,17 @@ public abstract class ConnectionConfiguration { return getThis(); } + /** + * Set the factory for stanza ID sources to use. + * + * @param stanzaIdSourceFactory the factory for stanza ID sources to use. + * @return a reference to this builder. + * @since 4.4 + */ + public B setStanzaIdSourceFactory(StanzaIdSourceFactory stanzaIdSourceFactory) { + this.stanzaIdSourceFactory = Objects.requireNonNull(stanzaIdSourceFactory); + return getThis(); + } public abstract C build(); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/SmackInitialization.java b/smack-core/src/main/java/org/jivesoftware/smack/SmackInitialization.java index cf3a646a2..92c122571 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/SmackInitialization.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/SmackInitialization.java @@ -49,7 +49,6 @@ import org.jivesoftware.smack.sasl.core.ScramSha1PlusMechanism; import org.jivesoftware.smack.util.CloseableUtil; import org.jivesoftware.smack.util.FileUtils; import org.jivesoftware.smack.util.PacketParserUtils; - import org.jivesoftware.smack.xml.XmlPullParser; 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 437e72082..d7df0a825 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java @@ -29,6 +29,7 @@ import org.jivesoftware.smack.packet.FullyQualifiedElement; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Nonza; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaFactory; import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.EntityFullJid; @@ -178,6 +179,8 @@ public interface XMPPConnection { */ boolean isUsingCompression(); + StanzaFactory getStanzaFactory(); + /** * Sends the specified stanza to the server. * diff --git a/smack-core/src/main/java/org/jivesoftware/smack/compress/provider/FailureProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/compress/provider/FailureProvider.java index cf90f594b..fff539602 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/compress/provider/FailureProvider.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/compress/provider/FailureProvider.java @@ -26,7 +26,6 @@ import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.provider.NonzaProvider; import org.jivesoftware.smack.util.PacketParserUtils; - import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; @@ -62,8 +61,7 @@ public final class FailureProvider extends NonzaProvider { case StreamOpen.SERVER_NAMESPACE: switch (name) { case StanzaError.ERROR: - StanzaError.Builder stanzaErrorBuilder = PacketParserUtils.parseError(parser, failureXmlEnvironment); - stanzaError = stanzaErrorBuilder.build(); + stanzaError = PacketParserUtils.parseError(parser, failureXmlEnvironment); break; default: LOGGER.warning("Unknown element in " + namespace + ": " + name); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java index c4b16f3ea..fd3b576c1 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014 Florian Schmaus + * Copyright © 2014-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. @@ -18,14 +18,18 @@ package org.jivesoftware.smack.packet; public class EmptyResultIQ extends IQ { + EmptyResultIQ(IqBuilder iqBuilder) { + super(iqBuilder, null, null); + } + + // TODO: Deprecate when stanza builder and parsing logic is ready. public EmptyResultIQ() { super(null, null); setType(IQ.Type.result); } public EmptyResultIQ(IQ request) { - this(); - initializeAsResultFor(request); + this(StanzaBuilder.buildIqResultFor(request)); } @Override diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/ErrorIQ.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/ErrorIQ.java index c09a09f38..23bf999b0 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/ErrorIQ.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/ErrorIQ.java @@ -27,13 +27,13 @@ public class ErrorIQ extends SimpleIQ { *

* According to RFC 6120 § 8.3.1 "4. An error stanza MUST contain an <error/> child element.", so the xmppError argument is mandatory. *

- * @param xmppErrorBuilder the XMPPError builder (required). + * @param stanzaError the stanzaError (required). */ - public ErrorIQ(StanzaError.Builder xmppErrorBuilder) { + public ErrorIQ(StanzaError stanzaError) { super(ELEMENT, null); - Objects.requireNonNull(xmppErrorBuilder, "xmppErrorBuilder must not be null"); + Objects.requireNonNull(stanzaError, "stanzaError must not be null"); setType(IQ.Type.error); - setError(xmppErrorBuilder); + setError(stanzaError); } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/FullyQualifiedElement.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/FullyQualifiedElement.java index 2e93d23bd..40da81351 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/FullyQualifiedElement.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/FullyQualifiedElement.java @@ -18,7 +18,7 @@ package org.jivesoftware.smack.packet; import javax.xml.namespace.QName; -public interface FullyQualifiedElement extends NamedElement { +public interface FullyQualifiedElement extends NamedElement, XmlLangElement { /** * Returns the root element XML namespace. @@ -33,11 +33,7 @@ public interface FullyQualifiedElement extends NamedElement { return new QName(namespaceURI, localPart); } - /** - * Returns the xml:lang of this XML element, or null if one has not been set. - * - * @return the xml:lang of this XML element, or null. - */ + @Override default String getLanguage() { return null; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/IQ.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/IQ.java index 3d875b7e1..d202eb2cc 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/IQ.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/IQ.java @@ -42,7 +42,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder; * * @author Matt Tucker */ -public abstract class IQ extends Stanza { +public abstract class IQ extends Stanza implements IqView { // Don't name this field 'ELEMENT'. When it comes to IQ, ELEMENT is the child element! public static final String IQ_ELEMENT = "iq"; @@ -54,6 +54,7 @@ public abstract class IQ extends Stanza { private Type type = Type.get; + // TODO: This method should be protected! public IQ(IQ iq) { super(iq); type = iq.getType(); @@ -62,7 +63,16 @@ public abstract class IQ extends Stanza { this.childElementQName = iq.childElementQName; } + // TODO: Deprecate when stanza builder is ready. protected IQ(String childElementName, String childElementNamespace) { + this(IqBuilder.EMPTY, childElementName, childElementNamespace); + } + + protected IQ(IqBuilder iqBuilder, String childElementName, String childElementNamespace) { + super(iqBuilder); + + type = iqBuilder.type; + this.childElementName = childElementName; this.childElementNamespace = childElementNamespace; if (childElementName == null) { @@ -72,11 +82,7 @@ public abstract class IQ extends Stanza { } } - /** - * Returns the type of the IQ packet. - * - * @return the type of the IQ packet. - */ + @Override public Type getType() { return type; } @@ -90,6 +96,7 @@ public abstract class IQ extends Stanza { * * @param type the type of the IQ packet. */ + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public void setType(Type type) { this.type = Objects.requireNonNull(type, "type must not be null"); } @@ -260,19 +267,6 @@ public abstract class IQ extends Stanza { */ protected abstract IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml); - protected final void initializeAsResultFor(IQ request) { - assert this != request; - - if (!(request.getType() == Type.get || request.getType() == Type.set)) { - throw new IllegalArgumentException( - "IQ must be of type 'set' or 'get'. Original IQ: " + request.toXML()); - } - setStanzaId(request.getStanzaId()); - setFrom(request.getTo()); - setTo(request.getFrom()); - setType(Type.result); - } - /** * Convenience method to create a new empty {@link Type#result IQ.Type.result} * IQ based on a {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set} @@ -311,7 +305,7 @@ public abstract class IQ extends Stanza { * {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set}. * @return a new {@link Type#error IQ.Type.error} IQ based on the originating IQ. */ - public static ErrorIQ createErrorResponse(final IQ request, final StanzaError.Builder error) { + public static ErrorIQ createErrorResponse(final IQ request, final StanzaError error) { if (!request.isRequestIQ()) { throw new IllegalArgumentException( "IQ must be of type 'set' or 'get'. Original IQ: " + request.toXML()); @@ -321,35 +315,25 @@ public abstract class IQ extends Stanza { result.setFrom(request.getTo()); result.setTo(request.getFrom()); - error.setStanza(result); - return result; } - public static ErrorIQ createErrorResponse(final IQ request, final StanzaError.Condition condition) { - return createErrorResponse(request, StanzaError.getBuilder(condition)); + /** + * Deprecated. + * + * @param request the request. + * @param error the error. + * @return an error IQ. + * @deprecated use {@link #createErrorResponse(IQ, StanzaError)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public static ErrorIQ createErrorResponse(final IQ request, final StanzaError.Builder error) { + return createErrorResponse(request, error.build()); } - /** - * Convenience method to create a new {@link Type#error IQ.Type.error} IQ - * based on a {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set} - * IQ. The new stanza will be initialized with: - * - * @param request the {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set} IQ packet. - * @param error the error to associate with the created IQ packet. - * @throws IllegalArgumentException if the IQ stanza does not have a type of - * {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set}. - * @return a new {@link Type#error IQ.Type.error} IQ based on the originating IQ. - */ - public static ErrorIQ createErrorResponse(final IQ request, final StanzaError error) { - return createErrorResponse(request, StanzaError.getBuilder(error)); + public static ErrorIQ createErrorResponse(final IQ request, final StanzaError.Condition condition) { + return createErrorResponse(request, StanzaError.getBuilder(condition).build()); } /** diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/IqBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/IqBuilder.java new file mode 100644 index 000000000..a0994555f --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/IqBuilder.java @@ -0,0 +1,57 @@ +/** + * + * 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.IQ.Type; +import org.jivesoftware.smack.packet.id.StandardStanzaIdSource; +import org.jivesoftware.smack.packet.id.StanzaIdSource; +import org.jivesoftware.smack.util.Objects; +import org.jivesoftware.smack.util.ToStringUtil; + +public final class IqBuilder extends StanzaBuilder implements IqView { + static final IqBuilder EMPTY = new IqBuilder(StandardStanzaIdSource.DEFAULT); + + IQ.Type type = Type.get; + + IqBuilder(StanzaIdSource stanzaIdSource) { + super(stanzaIdSource); + } + + IqBuilder(String stanzaId) { + super(stanzaId); + } + + @Override + protected void addStanzaSpecificAttributes(ToStringUtil.Builder builder) { + builder.addValue("type", type); + } + + public IqBuilder ofType(IQ.Type type) { + this.type = Objects.requireNonNull(type); + return getThis(); + } + + @Override + public IqBuilder getThis() { + return this; + } + + @Override + public IQ.Type getType() { + return type; + } +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/IqView.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/IqView.java new file mode 100644 index 000000000..a888712eb --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/IqView.java @@ -0,0 +1,28 @@ +/** + * + * 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 interface IqView extends StanzaView { + + /** + * Returns the type of the IQ packet. + * + * @return the type of the IQ packet. + */ + IQ.Type getType(); + +} 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 b6f426139..ef3dd9aec 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 @@ -24,6 +24,8 @@ import java.util.List; import java.util.Locale; import java.util.Set; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.util.EqualsUtil; import org.jivesoftware.smack.util.HashCode; import org.jivesoftware.smack.util.Objects; @@ -58,7 +60,7 @@ import org.jxmpp.stringprep.XmppStringprepException; * * @author Matt Tucker */ -public final class Message extends Stanza implements TypedCloneable { +public final class Message extends Stanza implements MessageView, TypedCloneable { public static final String ELEMENT = "message"; public static final String BODY = "body"; @@ -66,11 +68,12 @@ public final class Message extends Stanza implements TypedCloneable { private Type type; private String thread = null; - private final Set subjects = new HashSet(); - /** * Creates a new, "normal" message. + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public Message() { } @@ -78,7 +81,10 @@ public final class Message extends Stanza implements TypedCloneable { * Creates a new "normal" message to the specified recipient. * * @param to the recipient of the message. + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public Message(Jid to) { setTo(to); } @@ -88,7 +94,10 @@ public final class Message extends Stanza implements TypedCloneable { * * @param to the user to send the message to. * @param type the message type. + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public Message(Jid to, Type type) { this(to); setType(type); @@ -99,7 +108,10 @@ public final class Message extends Stanza implements TypedCloneable { * * @param to the user to send the message to. * @param body the body of the message. + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public Message(Jid to, String body) { this(to); setBody(body); @@ -111,7 +123,10 @@ public final class Message extends Stanza implements TypedCloneable { * @param to the user to send the message to. * @param body the body of the message. * @throws XmppStringprepException if 'to' is not a valid XMPP address. + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public Message(String to, String body) throws XmppStringprepException { this(JidCreate.from(to), body); } @@ -122,12 +137,21 @@ public final class Message extends Stanza implements TypedCloneable { * @param to TODO javadoc me please * @param extensionElement TODO javadoc me please * @since 4.2 + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public Message(Jid to, ExtensionElement extensionElement) { this(to); addExtension(extensionElement); } + Message(MessageBuilder messageBuilder) { + super(messageBuilder); + type = messageBuilder.type; + thread = messageBuilder.thread; + } + /** * Copy constructor. *

@@ -141,15 +165,9 @@ public final class Message extends Stanza implements TypedCloneable { super(other); this.type = other.type; this.thread = other.thread; - this.subjects.addAll(other.subjects); } - /** - * Returns the type of the message. If no type has been set this method will return {@link - * org.jivesoftware.smack.packet.Message.Type#normal}. - * - * @return the type of the message. - */ + @Override public Type getType() { if (type == null) { return Type.normal; @@ -161,7 +179,10 @@ public final class Message extends Stanza implements TypedCloneable { * Sets the type of the message. * * @param type the type of the message. + * @deprecated use {@link StanzaBuilder} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void setType(Type type) { this.type = type; } @@ -195,8 +216,9 @@ public final class Message extends Stanza implements TypedCloneable { private Subject getMessageSubject(String language) { language = determineLanguage(language); - for (Subject subject : subjects) { - if (Objects.equals(language, subject.language)) { + for (Subject subject : getSubjects()) { + if (Objects.equals(language, subject.language) + || (subject.language == null && Objects.equals(this.language, language))) { return subject; } } @@ -210,7 +232,12 @@ public final class Message extends Stanza implements TypedCloneable { * @return a collection of all subjects in this message. */ public Set getSubjects() { - return Collections.unmodifiableSet(subjects); + List subjectList = getExtensions(Subject.class); + + Set subjects = new HashSet<>(subjectList.size()); + subjects.addAll(subjectList); + + return subjects; } /** @@ -218,7 +245,10 @@ public final class Message extends Stanza implements TypedCloneable { * message contents. * * @param subject the subject of the message. + * @deprecated use {@link StanzaBuilder} instead. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public void setSubject(String subject) { if (subject == null) { removeSubject(""); // use empty string because #removeSubject(null) is ambiguous @@ -235,10 +265,20 @@ public final class Message extends Stanza implements TypedCloneable { * @return the new {@link org.jivesoftware.smack.packet.Message.Subject} * @throws NullPointerException if the subject is null, a null pointer exception is thrown */ + @Deprecated + // TODO: Remove when stanza builder is ready. public Subject addSubject(String language, String subject) { language = determineLanguage(language); + + List currentSubjects = getExtensions(Subject.class); + for (Subject currentSubject : currentSubjects) { + if (language.equals(currentSubject.getLanguage())) { + throw new IllegalArgumentException("Subject with the language " + language + " already exists"); + } + } + Subject messageSubject = new Subject(language, subject); - subjects.add(messageSubject); + addExtension(messageSubject); return messageSubject; } @@ -248,11 +288,13 @@ public final class Message extends Stanza implements TypedCloneable { * @param language the language of the subject which is to be removed * @return true if a subject was removed and false if it was not. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public boolean removeSubject(String language) { language = determineLanguage(language); - for (Subject subject : subjects) { + for (Subject subject : getExtensions(Subject.class)) { if (language.equals(subject.language)) { - return subjects.remove(subject); + return removeSubject(subject); } } return false; @@ -264,8 +306,10 @@ public final class Message extends Stanza implements TypedCloneable { * @param subject the subject being removed from the message. * @return true if the subject was successfully removed and false if it was not. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public boolean removeSubject(Subject subject) { - return subjects.remove(subject); + return removeExtension(subject) != null; } /** @@ -276,7 +320,7 @@ public final class Message extends Stanza implements TypedCloneable { public List getSubjectLanguages() { Subject defaultSubject = getMessageSubject(null); List languages = new ArrayList(); - for (Subject subject : subjects) { + for (Subject subject : getExtensions(Subject.class)) { if (!subject.equals(defaultSubject)) { languages.add(subject.language); } @@ -345,7 +389,10 @@ public final class Message extends Stanza implements TypedCloneable { * @param body the body of the message. * @see #setBody(String) * @since 4.2 + * @deprecated use {@link StanzaBuilder} instead. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public void setBody(CharSequence body) { String bodyString; if (body != null) { @@ -360,7 +407,10 @@ public final class Message extends Stanza implements TypedCloneable { * Sets the body of the message. The body is the main message contents. * * @param body the body of the message. + * @deprecated use {@link StanzaBuilder} instead. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public void setBody(String body) { if (body == null) { removeBody(""); // use empty string because #removeBody(null) is ambiguous @@ -377,7 +427,10 @@ public final class Message extends Stanza implements TypedCloneable { * @return the new {@link org.jivesoftware.smack.packet.Message.Body} * @throws NullPointerException if the body is null, a null pointer exception is thrown * @since 3.0.2 + * @deprecated use {@link StanzaBuilder} instead. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public Body addBody(String language, String body) { language = determineLanguage(language); @@ -393,7 +446,10 @@ public final class Message extends Stanza implements TypedCloneable { * * @param language the language of the body which is to be removed * @return true if a body was removed and false if it was not. + * @deprecated use {@link StanzaBuilder} instead. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public boolean removeBody(String language) { language = determineLanguage(language); for (Body body : getBodies()) { @@ -412,7 +468,10 @@ public final class Message extends Stanza implements TypedCloneable { * @param body the body being removed from the message. * @return true if the body was successfully removed and false if it was not. * @since 3.0.2 + * @deprecated use {@link StanzaBuilder} instead. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public boolean removeBody(Body body) { ExtensionElement removedElement = removeExtension(body); return removedElement != null; @@ -450,7 +509,10 @@ public final class Message extends Stanza implements TypedCloneable { * of "chat" messages. * * @param thread the thread id of the message. + * @deprecated use {@link StanzaBuilder} instead. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public void setThread(String thread) { this.thread = thread; } @@ -472,6 +534,10 @@ public final class Message extends Stanza implements TypedCloneable { return ELEMENT; } + public MessageBuilder asBuilder() { + return StanzaBuilder.buildMessageFrom(this, getStanzaId()); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -491,18 +557,6 @@ public final class Message extends Stanza implements TypedCloneable { buf.optAttribute("type", type); buf.rightAngleBracket(); - // Add the subject in the default language - Subject defaultSubject = getMessageSubject(null); - if (defaultSubject != null) { - buf.element("subject", defaultSubject.subject); - } - // Add the subject in other languages - for (Subject subject : getSubjects()) { - // Skip the default language - if (subject.equals(defaultSubject)) - continue; - buf.append(subject); - } buf.optElement("thread", thread); // Append the error subpacket if the message type is an error. if (type == Type.error) { @@ -537,10 +591,12 @@ public final class Message extends Stanza implements TypedCloneable { public static final String ELEMENT = "subject"; public static final String NAMESPACE = StreamOpen.CLIENT_NAMESPACE; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); + private final String subject; private final String language; - private Subject(String language, String subject) { + public Subject(String language, String subject) { if (subject == null) { throw new NullPointerException("Subject cannot be null."); } 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 new file mode 100644 index 000000000..b73880d0c --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageBuilder.java @@ -0,0 +1,164 @@ +/** + * + * 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.Message.Body; +import org.jivesoftware.smack.packet.Message.Subject; +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 { + static final MessageBuilder EMPTY = new MessageBuilder(() -> { + return null; + }); + + Message.Type type; + + String thread; + + MessageBuilder(Message message, String stanzaId) { + super(message, stanzaId); + copyFromMessage(message); + } + + MessageBuilder(Message message, StanzaIdSource stanzaIdSource) { + super(message, stanzaIdSource); + copyFromMessage(message); + } + + MessageBuilder(StanzaIdSource stanzaIdSource) { + super(stanzaIdSource); + } + + MessageBuilder(String stanzaId) { + super(stanzaId); + } + + private void copyFromMessage(Message message) { + type = message.getType(); + thread = message.getThread(); + } + + @Override + protected void addStanzaSpecificAttributes(ToStringUtil.Builder builder) { + builder.addValue("type", type) + .addValue("thread", thread) + ; + } + + public MessageBuilder ofType(Message.Type type) { + this.type = type; + return getThis(); + } + + public MessageBuilder setThread(String thread) { + this.thread = thread; + return getThis(); + } + + /** + * Sets the subject of the message. The subject is a short description of + * message contents. + * + * @param subject the subject of the message. + * @return a reference to this builder. + */ + public MessageBuilder setSubject(String subject) { + return addSubject(null, subject); + } + + /** + * Adds a subject with a corresponding language. + * + * @param language the language of the subject being added. + * @param subject the subject being added to the message. + * @return a reference to this builder. + * @throws NullPointerException if the subject is null. + */ + public MessageBuilder addSubject(String language, String subject) { + language = StringUtils.requireNullOrNotEmpty(language, "language must be null or not empty"); + + for (Subject currentSubject : getExtensions(Subject.class)) { + if (StringUtils.nullSafeCharSequenceEquals(language, currentSubject.getLanguage())) { + throw new IllegalArgumentException("Subject with the language " + language + " already exists"); + } + } + + Subject messageSubject = new Subject(language, subject); + addExtension(messageSubject); + + return this; + } + + /** + * Sets the body of the message. + * + * @param body the body of the message. + * @return a reference to this builder. + * @see #setBody(String) + */ + public MessageBuilder setBody(CharSequence body) { + return setBody(body.toString()); + } + + /** + * Sets the body of the message. The body is the main message contents. + * + * @param body the body of the message. + * @return a reference to this builder. + */ + public MessageBuilder setBody(String body) { + return addBody(null, body); + } + + /** + * Adds a body with a corresponding language. + * + * @param language the language of the body being added. + * @param body the body being added to the message. + * @return a reference to this builder. + */ + public MessageBuilder addBody(String language, String body) { + language = StringUtils.requireNullOrNotEmpty(language, "language must be null or not empty"); + + for (Body currentBody : getExtensions(Body.class)) { + if (StringUtils.nullSafeCharSequenceEquals(language, currentBody.getLanguage())) { + throw new IllegalArgumentException("Bodyt with the language " + language + " already exists"); + } + } + + Body messageBody = new Body(language, body); + addExtension(messageBody); + + return this; + } + + @Override + public MessageBuilder getThis() { + return this; + } + + public Message build() { + return new Message(this); + } + + @Override + public Message.Type getType() { + return type; + } +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageView.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageView.java new file mode 100644 index 000000000..046b9274f --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageView.java @@ -0,0 +1,29 @@ +/** + * + * 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 interface MessageView extends StanzaView { + + /** + * Returns the type of the message. If no type has been set this method will return {@link + * org.jivesoftware.smack.packet.Message.Type#normal}. + * + * @return the type of the message. + */ + Message.Type getType(); + +} 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 62630ecfb..8a8db7030 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 @@ -19,7 +19,8 @@ package org.jivesoftware.smack.packet; import java.util.Locale; -import org.jivesoftware.smack.packet.id.StanzaIdUtil; +import javax.net.SocketFactory; + import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.TypedCloneable; @@ -60,7 +61,7 @@ import org.jxmpp.jid.Jid; * * @author Matt Tucker */ -public final class Presence extends Stanza implements TypedCloneable { +public final class Presence extends Stanza implements PresenceView, TypedCloneable { public static final String ELEMENT = "presence"; @@ -81,7 +82,10 @@ public final class Presence extends Stanza implements TypedCloneable { * Creates a new presence update. Status, priority, and mode are left un-set. * * @param type the type. + * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public Presence(Type type) { // Ensure that the stanza ID is set by calling super(). super(); @@ -94,7 +98,10 @@ public final class Presence extends Stanza implements TypedCloneable { * @param to the recipient. * @param type the type. * @since 4.2 + * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public Presence(Jid to, Type type) { this(type); setTo(to); @@ -107,7 +114,10 @@ public final class Presence extends Stanza implements TypedCloneable { * @param status a text message describing the presence update. * @param priority the priority of this presence update. * @param mode the mode type for this presence update. + * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public Presence(Type type, String status, int priority, Mode mode) { // Ensure that the stanza ID is set by calling super(). super(); @@ -117,6 +127,14 @@ public final class Presence extends Stanza implements TypedCloneable { setMode(mode); } + Presence(PresenceBuilder presenceBuilder) { + super(presenceBuilder); + type = presenceBuilder.type; + status = presenceBuilder.status; + priority = presenceBuilder.priority; + mode = presenceBuilder.mode; + } + /** * Copy constructor. *

@@ -163,11 +181,7 @@ public final class Presence extends Stanza implements TypedCloneable { return type == Type.available && (mode == Mode.away || mode == Mode.xa || mode == Mode.dnd); } - /** - * Returns the type of this presence packet. - * - * @return the type of the presence packet. - */ + @Override public Type getType() { return type; } @@ -176,18 +190,15 @@ public final class Presence extends Stanza implements TypedCloneable { * Sets the type of the presence packet. * * @param type the type of the presence packet. + * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void setType(Type type) { this.type = Objects.requireNonNull(type, "Type cannot be null"); } - /** - * Returns the status message of the presence update, or null if there - * is not a status. The status is free-form text describing a user's presence - * (i.e., "gone to lunch"). - * - * @return the status message. - */ + @Override public String getStatus() { return status; } @@ -197,18 +208,21 @@ public final class Presence extends Stanza implements TypedCloneable { * describing a user's presence (i.e., "gone to lunch"). * * @param status the status message. + * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void setStatus(String status) { this.status = status; } - /** - * Returns the priority of the presence. - * - * @return the priority. - * @see RFC 6121 § 4.7.2.3. Priority Element - */ + @Override public int getPriority() { + return getPriorityByte(); + } + + @Override + public byte getPriorityByte() { if (priority == null) { return 0; } @@ -221,7 +235,10 @@ public final class Presence extends Stanza implements TypedCloneable { * @param priority the priority of the presence. * @throws IllegalArgumentException if the priority is outside the valid range. * @see RFC 6121 § 4.7.2.3. Priority Element + * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void setPriority(int priority) { if (priority < -128 || priority > 127) { throw new IllegalArgumentException("Priority value " + priority + @@ -234,11 +251,7 @@ public final class Presence extends Stanza implements TypedCloneable { this.priority = priority; } - /** - * Returns the mode of the presence update. - * - * @return the mode. - */ + @Override public Mode getMode() { if (mode == null) { return Mode.available; @@ -251,7 +264,10 @@ public final class Presence extends Stanza implements TypedCloneable { * to be the same thing as {@link Presence.Mode#available}. * * @param mode the mode. + * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void setMode(Mode mode) { this.mode = mode; } @@ -261,6 +277,10 @@ public final class Presence extends Stanza implements TypedCloneable { return ELEMENT; } + public PresenceBuilder asBuilder() { + return StanzaBuilder.buildPresenceFrom(this, getStanzaId()); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -326,7 +346,7 @@ public final class Presence extends Stanza implements TypedCloneable { */ public Presence cloneWithNewId() { Presence clone = clone(); - clone.setStanzaId(StanzaIdUtil.newStanzaId()); + clone.setNewStanzaId(); return clone; } 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 new file mode 100644 index 000000000..795c9a824 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/PresenceBuilder.java @@ -0,0 +1,140 @@ +/** + * + * 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.Presence.Mode; +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 { + static final PresenceBuilder EMPTY = new PresenceBuilder(() -> { + return null; + }); + + Presence.Type type = Presence.Type.available; + + String status; + + Byte priority; + + Presence.Mode mode; + + PresenceBuilder(Presence presence, String stanzaId) { + super(presence, stanzaId); + copyFromPresence(presence); + } + + PresenceBuilder(Presence presence, StanzaIdSource stanzaIdSource) { + super(presence, stanzaIdSource); + copyFromPresence(presence); + } + + PresenceBuilder(StanzaIdSource stanzaIdSource) { + super(stanzaIdSource); + } + + PresenceBuilder(String stanzaId) { + super(stanzaId); + } + + private void copyFromPresence(Presence presence) { + type = presence.getType(); + status = presence.getStatus(); + priority = presence.getPriorityByte(); + mode = presence.getMode(); + } + + @Override + protected void addStanzaSpecificAttributes(ToStringUtil.Builder builder) { + builder.addValue("type", type) + .addValue("mode", mode) + .addValue("priority", priority) + .addValue("status", status) + ; + } + + public PresenceBuilder ofType(Presence.Type type) { + this.type = Objects.requireNonNull(type, "Type cannot be null"); + return getThis(); + } + + public PresenceBuilder setStatus(String status) { + this.status = status; + return getThis(); + } + + public PresenceBuilder setPriority(int priority) { + if (priority < -128 || priority > 127) { + throw new IllegalArgumentException("Priority value " + priority + + " is not valid. Valid range is -128 through 127."); + } + Byte priorityByte = (byte) priority; + return setPriority(priorityByte); + } + + public PresenceBuilder setPriority(Byte priority) { + this.priority = priority; + return getThis(); + } + + public PresenceBuilder setMode(Presence.Mode mode) { + this.mode = mode; + return getThis(); + } + + @Override + public PresenceBuilder getThis() { + return this; + } + + public Presence build() { + return new Presence(this); + } + + @Override + public Presence.Type getType() { + return type; + } + + @Override + public String getStatus() { + return status; + } + + @Override + public int getPriority() { + return getPriorityByte(); + } + + @Override + public byte getPriorityByte() { + if (priority == null) { + return 0; + } + return priority; + } + + @Override + public Presence.Mode getMode() { + if (mode == null) { + return Mode.available; + } + return mode; + } + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/PresenceView.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/PresenceView.java new file mode 100644 index 000000000..80b44badb --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/PresenceView.java @@ -0,0 +1,59 @@ +/** + * + * 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 interface PresenceView extends StanzaView { + + /** + * Returns the type of this presence stanza. + * + * @return the type of the presence stanza. + */ + Presence.Type getType(); + + /** + * Returns the status message of the presence update, or null if there + * is not a status. The status is free-form text describing a user's presence + * (i.e., "gone to lunch"). + * + * @return the status message. + */ + String getStatus(); + + /** + * Returns the priority of the presence. + * + * @return the priority. + * @see RFC 6121 § 4.7.2.3. Priority Element + */ + int getPriority(); + + /** + * Returns the priority of the presence. + * + * @return the priority. + * @see RFC 6121 § 4.7.2.3. Priority Element + */ + byte getPriorityByte(); + + /** + * Returns the mode of the presence update. + * + * @return the mode. + */ + Presence.Mode getMode(); +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/SimpleIQ.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/SimpleIQ.java index cd20108d8..5cd260c5f 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/SimpleIQ.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/SimpleIQ.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014 Florian Schmaus + * Copyright © 2014-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. @@ -29,6 +29,10 @@ public abstract class SimpleIQ extends IQ { super(childElementName, childElementNamespace); } + protected SimpleIQ(IqBuilder iqBuilder, String childElementName, String childElementNamespace) { + super(iqBuilder, childElementName, childElementNamespace); + } + @Override protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.setEmptyElement(); 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 9d93f8b14..b884468f7 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 @@ -20,15 +20,19 @@ package org.jivesoftware.smack.packet; import static org.jivesoftware.smack.util.StringUtils.requireNotNullNorEmpty; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Locale; import javax.xml.namespace.QName; -import org.jivesoftware.smack.packet.id.StanzaIdUtil; +import org.jivesoftware.smack.packet.id.StandardStanzaIdSource; +import org.jivesoftware.smack.packet.id.StanzaIdSource; import org.jivesoftware.smack.util.MultiMap; import org.jivesoftware.smack.util.PacketUtil; +import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.XmlStringBuilder; +import org.jivesoftware.smack.util.XmppElementUtil; import org.jxmpp.jid.Jid; @@ -43,12 +47,16 @@ import org.jxmpp.jid.Jid; * XMPP Stanzas are {@link Message}, {@link IQ} and {@link Presence}. Which therefore subclass this * class. If you think you need to subclass this class, then you are doing something wrong. *

+ *

+ * Use {@link StanzaBuilder} to construct a stanza instance. All instance mutating methods of this + * class are deprecated, although not all of them are currently marked as such, and must not be used. + *

* * @author Matt Tucker * @author Florian Schmaus * @see RFC 6120 § 8. XML Stanzas */ -public abstract class Stanza implements TopLevelStreamElement { +public abstract class Stanza implements StanzaView, TopLevelStreamElement { public static final String TEXT = "text"; public static final String ITEM = "item"; @@ -56,12 +64,14 @@ public abstract class Stanza implements TopLevelStreamElement { protected static final String DEFAULT_LANGUAGE = java.util.Locale.getDefault().getLanguage().toLowerCase(Locale.US); - private final MultiMap extensionElements = new MultiMap<>(); + private final MultiMap extensionElements; // Assume that all stanzas Smack handles are in the client namespace, since Smack is an XMPP client library. We can // change this behavior later if it is required. private final String namespace = StreamOpen.CLIENT_NAMESPACE; + private final StanzaIdSource usedStanzaIdSource; + private String id = null; private Jid to; private Jid from; @@ -80,30 +90,46 @@ public abstract class Stanza implements TopLevelStreamElement { protected String language; protected Stanza() { - this(StanzaIdUtil.newStanzaId()); + extensionElements = new MultiMap<>(); + usedStanzaIdSource = null; + id = StandardStanzaIdSource.DEFAULT.getNewStanzaId(); } - protected Stanza(String stanzaId) { - setStanzaId(stanzaId); + protected Stanza(StanzaBuilder stanzaBuilder) { + if (stanzaBuilder.stanzaIdSource != null) { + id = stanzaBuilder.stanzaIdSource.getNewStanzaId(); + // Note that some stanza ID sources, e.g. StanzaBuilder.PresenceBuilder.EMPTY return null here. Hence we + // only check that the returned string is not empty. + assert StringUtils.isNullOrNotEmpty(id); + usedStanzaIdSource = stanzaBuilder.stanzaIdSource; + } else { + // N.B. It is ok if stanzaId here is null. + id = stanzaBuilder.stanzaId; + usedStanzaIdSource = null; + } + + to = stanzaBuilder.to; + from = stanzaBuilder.from; + + error = stanzaBuilder.stanzaError; + + language = stanzaBuilder.language; + + extensionElements = stanzaBuilder.extensionElements.clone(); } protected Stanza(Stanza p) { + usedStanzaIdSource = p.usedStanzaIdSource; + id = p.getStanzaId(); to = p.getTo(); from = p.getFrom(); error = p.error; - // Copy extensions - for (ExtensionElement pe : p.getExtensions()) { - addExtension(pe); - } + extensionElements = p.extensionElements.clone(); } - /** - * Returns the unique ID of the stanza. The returned value could be null. - * - * @return the packet's unique ID or null if the id is not available. - */ + @Override public String getStanzaId() { return id; } @@ -138,56 +164,50 @@ public abstract class Stanza implements TopLevelStreamElement { * * @return the stanza id. * @since 4.2 - * @deprecated use {@link #setNewStanzaId()} instead. + * @deprecated use {@link StanzaBuilder} instead. */ @Deprecated // TODO: Remove in Smack 4.5. public String setStanzaId() { - return ensureStanzaIdSet(); - } - - /** - * Set a new stanza ID even if there is already one set. - * - * @return the stanza id. - * @since 4.4 - */ - public String setNewStanzaId() { - return ensureStanzaIdSet(true); - } - - /** - * Ensure a stanza id is set. - * - * @return the stanza id. - * @since 4.4 - */ - public String ensureStanzaIdSet() { - return ensureStanzaIdSet(false); - } - - /** - * Ensure that a stanza ID is set. - * - * @param forceNew force a new ID even if there is already one set. - * @return the stanza ID. - * @since 4.4 - */ - private String ensureStanzaIdSet(boolean forceNew) { - if (forceNew || !hasStanzaIdSet()) { - setStanzaId(StanzaIdUtil.newStanzaId()); + if (!hasStanzaIdSet()) { + setNewStanzaId(); } return getStanzaId(); } /** - * Returns who the stanza is being sent "to", or null if - * the value is not set. The XMPP protocol often makes the "to" - * attribute optional, so it does not always need to be set.

+ * Throws an {@link IllegalArgumentException} if this stanza has no stanza ID set. * - * @return who the stanza is being sent to, or null if the - * value has not been set. + * @throws IllegalArgumentException if this stanza has no stanza ID set. + * @since 4.4. */ + public final void throwIfNoStanzaId() { + if (hasStanzaIdSet()) { + return; + } + + throw new IllegalArgumentException("The stanza has no RFC stanza ID set, although one is required"); + } + + /** + * Ensure that a stanza ID is set. + * + * @return the stanza ID. + * @since 4.4 + */ + // TODO: Remove this method once StanzaBuilder is ready. + protected String setNewStanzaId() { + if (usedStanzaIdSource != null) { + id = usedStanzaIdSource.getNewStanzaId(); + } + else { + id = StandardStanzaIdSource.DEFAULT.getNewStanzaId(); + } + + return getStanzaId(); + } + + @Override public Jid getTo() { return to; } @@ -198,18 +218,12 @@ public abstract class Stanza implements TopLevelStreamElement { * * @param to who the packet is being sent to. */ + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public void setTo(Jid to) { this.to = to; } - /** - * Returns who the stanza is being sent "from" or null if - * the value is not set. The XMPP protocol often makes the "from" - * attribute optional, so it does not always need to be set.

- * - * @return who the stanza is being sent from, or null if the - * value has not been set. - */ + @Override public Jid getFrom() { return from; } @@ -221,16 +235,12 @@ public abstract class Stanza implements TopLevelStreamElement { * * @param from who the packet is being sent to. */ + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public void setFrom(Jid from) { this.from = from; } - /** - * Returns the error associated with this packet, or null if there are - * no errors. - * - * @return the error sub-packet or null if there isn't an error. - */ + @Override public StanzaError getError() { return error; } @@ -238,14 +248,22 @@ public abstract class Stanza implements TopLevelStreamElement { /** * Sets the error for this stanza. * - * @param xmppErrorBuilder the error to associate with this stanza. + * @param stanzaError the error that this stanza carries and hence signals. */ - public void setError(StanzaError.Builder xmppErrorBuilder) { - if (xmppErrorBuilder == null) { - return; - } - xmppErrorBuilder.setStanza(this); - error = xmppErrorBuilder.build(); + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. + public void setError(StanzaError stanzaError) { + error = stanzaError; + } + + /** + * Deprecated. + * @param stanzaError the stanza error. + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void setError(StanzaError.Builder stanzaError) { + setError(stanzaError.build()); } @Override @@ -257,16 +275,15 @@ public abstract class Stanza implements TopLevelStreamElement { * Sets the xml:lang of this Stanza. * * @param language the xml:lang of this Stanza. + * @deprecated use {@link StanzaBuilder#setLanguage(String)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void setLanguage(String language) { this.language = language; } - /** - * Returns a list of all extension elements of this stanza. - * - * @return a list of all extension elements of this stanza. - */ + @Override public List getExtensions() { synchronized (extensionElements) { // No need to create a new list, values() will already create a new one for us @@ -274,6 +291,16 @@ public abstract class Stanza implements TopLevelStreamElement { } } + public final MultiMap getExtensionsMap() { + return cloneExtensionsMap(); + } + + final MultiMap cloneExtensionsMap() { + synchronized (extensionElements) { + return extensionElements.clone(); + } + } + /** * Return a list of all extensions with the given element name and namespace. *

@@ -289,7 +316,23 @@ public abstract class Stanza implements TopLevelStreamElement { requireNotNullNorEmpty(elementName, "elementName must not be null nor empty"); requireNotNullNorEmpty(namespace, "namespace must not be null nor empty"); QName key = new QName(namespace, elementName); - return extensionElements.getAll(key); + return getExtensions(key); + } + + @Override + public List getExtensions(QName qname) { + List res; + synchronized (extensionElements) { + res = extensionElements.getAll(qname); + } + return Collections.unmodifiableList(res); + } + + @Override + public List getExtensions(Class extensionElementClass) { + synchronized (extensionElements) { + return XmppElementUtil.getElementsFrom(extensionElements, extensionElementClass); + } } /** @@ -322,21 +365,31 @@ public abstract class Stanza implements TopLevelStreamElement { return null; } QName key = new QName(namespace, elementName); - ExtensionElement packetExtension; - synchronized (extensionElements) { - packetExtension = extensionElements.getFirst(key); - } + ExtensionElement packetExtension = getExtension(key); if (packetExtension == null) { return null; } return (PE) packetExtension; } + @SuppressWarnings("unchecked") + @Override + public final E getExtension(QName qname) { + synchronized (extensionElements) { + return (E) extensionElements.getFirst(qname); + } + } + /** * Adds a stanza extension to the packet. Does nothing if extension is null. + *

+ * Please note that although this method is not yet marked as deprecated, it is recommended to use + * {@link StanzaBuilder#addExtension(ExtensionElement)} instead. + *

* * @param extension a stanza extension. */ + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public void addExtension(ExtensionElement extension) { if (extension == null) return; QName key = extension.getQName(); @@ -348,11 +401,16 @@ public abstract class Stanza implements TopLevelStreamElement { /** * Add the given extension and override eventually existing extensions with the same name and * namespace. + *

+ * Please note that although this method is not yet marked as deprecated, it is recommended to use + * {@link StanzaBuilder#overrideExtension(ExtensionElement)} instead. + *

* * @param extension the extension element to add. * @return one of the removed extensions or null if there are none. * @since 4.1.2 */ + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public ExtensionElement overrideExtension(ExtensionElement extension) { if (extension == null) return null; synchronized (extensionElements) { @@ -370,6 +428,7 @@ public abstract class Stanza implements TopLevelStreamElement { * * @param extensions a collection of stanza extensions */ + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public void addExtensions(Collection extensions) { if (extensions == null) return; for (ExtensionElement packetExtension : extensions) { @@ -421,6 +480,7 @@ public abstract class Stanza implements TopLevelStreamElement { * @param namespace TODO javadoc me please * @return the removed stanza extension or null. */ + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public ExtensionElement removeExtension(String elementName, String namespace) { QName key = new QName(namespace, elementName); synchronized (extensionElements) { @@ -433,7 +493,10 @@ public abstract class Stanza implements TopLevelStreamElement { * * @param extension the stanza extension to remove. * @return the removed stanza extension or null. + * @deprecated use {@link StanzaBuilder} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public ExtensionElement removeExtension(ExtensionElement extension) { QName key = extension.getQName(); synchronized (extensionElements) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaBuilder.java new file mode 100644 index 000000000..4b2cba391 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaBuilder.java @@ -0,0 +1,301 @@ +/** + * + * 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 java.util.Collection; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.jivesoftware.smack.packet.IQ.Type; +import org.jivesoftware.smack.packet.id.StanzaIdSource; +import org.jivesoftware.smack.util.MultiMap; +import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.ToStringUtil; +import org.jivesoftware.smack.util.XmppElementUtil; + +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; + +public abstract class StanzaBuilder> implements StanzaView { + + final StanzaIdSource stanzaIdSource; + final String stanzaId; + + Jid to; + Jid from; + + StanzaError stanzaError; + + String language; + + MultiMap extensionElements = new MultiMap<>(); + + protected StanzaBuilder(StanzaIdSource stanzaIdSource) { + this.stanzaIdSource = stanzaIdSource; + this.stanzaId = null; + } + + protected StanzaBuilder(String stanzaId) { + this.stanzaIdSource = null; + this.stanzaId = StringUtils.requireNullOrNotEmpty(stanzaId, "Stanza ID must not be the empty String"); + } + + protected StanzaBuilder(Stanza message, String stanzaId) { + this(stanzaId); + copyFromStanza(message); + } + + protected StanzaBuilder(Stanza message, StanzaIdSource stanzaIdSource) { + this(stanzaIdSource); + copyFromStanza(message); + } + + private void copyFromStanza(Stanza stanza) { + to = stanza.getTo(); + from = stanza.getFrom(); + stanzaError = stanza.getError(); + language = stanza.getLanguage(); + + extensionElements = stanza.cloneExtensionsMap(); + } + + /** + * Set the recipent address of the stanza. + * + * @param to whoe the stanza is being sent to. + * @return a reference to this builder. + * @throws XmppStringprepException if the provided character sequence is not a valid XMPP address. + * @see #to(Jid) + */ + public final B to(CharSequence to) throws XmppStringprepException { + return to(JidCreate.from(to)); + } + + /** + * Sets who the stanza is being sent "to". The XMPP protocol often makes the "to" attribute optional, so it does not + * always need to be set. + * + * @param to who the stanza is being sent to. + * @return a reference to this builder. + */ + public final B to(Jid to) { + this.to = to; + return getThis(); + } + + /** + * Sets who the the stanza is being sent "from". + * + * @param from who the stanza is being sent from. + * @return a reference to this builder. + * @throws XmppStringprepException if the provided character sequence is not a valid XMPP address. + * @see #from(Jid) + */ + public final B from(CharSequence from) throws XmppStringprepException { + return from(JidCreate.from(from)); + } + + /** + * Sets who the stanza is being sent "from". The XMPP protocol often makes the "from" attribute optional, so it does + * not always need to be set. + * + * @param from who the stanza is being sent from. + * @return a reference to this builder. + */ + public final B from(Jid from) { + this.from = from; + return getThis(); + } + + /** + * Sets the error for this stanza. + * + * @param stanzaError the error to associate with this stanza. + * @return a reference to this builder. + */ + public final B setError(StanzaError stanzaError) { + this.stanzaError = stanzaError; + return getThis(); + } + + /** + * Sets the xml:lang for this stanza. + * + * @param language the xml:lang of this stanza. + * @return a reference to this builder. + */ + public final B setLanguage(String language) { + this.language = language; + return getThis(); + } + + public final B addExtension(ExtensionElement extensionElement) { + QName key = extensionElement.getQName(); + extensionElements.put(key, extensionElement); + return getThis(); + } + + public final B addExtensions(Collection extensionElements) { + for (ExtensionElement extensionElement : extensionElements) { + addExtension(extensionElement); + } + return getThis(); + } + + public final B overrideExtension(ExtensionElement extensionElement) { + QName key = extensionElement.getQName(); + extensionElements.remove(key); + extensionElements.put(key, extensionElement); + return getThis(); + } + + public abstract B getThis(); + + @Override + public final String getStanzaId() { + return stanzaId; + } + + @Override + public final Jid getTo() { + return to; + } + + @Override + public final Jid getFrom() { + return from; + } + + @Override + public final String getLanguage() { + return language; + } + + @Override + public final StanzaError getError() { + return stanzaError; + } + + @SuppressWarnings("unchecked") + @Override + public final E getExtension(QName qname) { + return (E) extensionElements.getFirst(qname); + } + + @Override + public final List getExtensions() { + return extensionElements.values(); + } + + @Override + public final List getExtensions(QName qname) { + return extensionElements.getAll(qname); + } + + @Override + public final List getExtensions(Class extensionElementClass) { + return XmppElementUtil.getElementsFrom(extensionElements, extensionElementClass); + } + + public final boolean willBuildStanzaWithId() { + return stanzaIdSource != null || StringUtils.isNotEmpty(stanzaId); + } + + public final void throwIfNoStanzaId() { + if (willBuildStanzaWithId()) { + return; + } + throw new IllegalArgumentException( + "The builder will not build a stanza with an ID set, although it is required"); + } + + protected abstract void addStanzaSpecificAttributes(ToStringUtil.Builder builder); + + @Override + public final String toString() { + ToStringUtil.Builder builder = ToStringUtil.builderFor(getClass()) + .addValue("id", stanzaId) + .addValue("from", from) + .addValue("to", to) + .addValue("language", language) + .addValue("error", stanzaError) + ; + + addStanzaSpecificAttributes(builder); + + builder.add("Extension Elements", extensionElements.values(), e -> { + return e.getQName(); + }); + + return builder.build(); + } + + public static MessageBuilder buildMessage() { + return buildMessage(null); + } + + public static MessageBuilder buildMessage(String stanzaId) { + return new MessageBuilder(stanzaId); + } + + public static MessageBuilder buildMessageFrom(Message message, String stanzaId) { + return new MessageBuilder(message, stanzaId); + } + + public static MessageBuilder buildMessageFrom(Message message, StanzaIdSource stanzaIdSource) { + return new MessageBuilder(message, stanzaIdSource); + } + + public static PresenceBuilder buildPresence() { + return buildPresence(null); + } + + public static PresenceBuilder buildPresence(String stanzaId) { + return new PresenceBuilder(stanzaId); + } + + public static PresenceBuilder buildPresenceFrom(Presence presence, String stanzaId) { + return new PresenceBuilder(presence, stanzaId); + } + + public static PresenceBuilder buildPresenceFrom(Presence presence, StanzaIdSource stanzaIdSource) { + return new PresenceBuilder(presence, stanzaIdSource); + } + + public static IqBuilder buildIq(String stanzaId) { + return new IqBuilder(stanzaId); + } + + public static IqBuilder buildIqResultFor(IQ request) { + if (!(request.getType() == Type.get || request.getType() == Type.set)) { + throw new IllegalArgumentException( + "IQ request must be of type 'set' or 'get'. Original IQ: " + request.toXML()); + } + + return buildIq(request.getStanzaId()) + .to(request.getFrom()) + .from(request.getTo()) + .ofType(IQ.Type.result); + } + + public static EmptyResultIQ buildEmptyIqResultFor(IQ request) { + IqBuilder iqBuilder = buildIqResultFor(request); + return new EmptyResultIQ(iqBuilder); + } +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaError.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaError.java index 7c43fb5b2..590de8c81 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaError.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaError.java @@ -106,7 +106,6 @@ public class StanzaError extends AbstractError implements ExtensionElement { private final String conditionText; private final String errorGenerator; private final Type type; - private final Stanza stanza; /** * Creates a new error with the specified type, condition and message. @@ -120,13 +119,11 @@ public class StanzaError extends AbstractError implements ExtensionElement { * @param errorGenerator TODO javadoc me please * @param descriptiveTexts TODO javadoc me please * @param extensions list of stanza extensions - * @param stanza the stanza carrying this XMPP error. */ public StanzaError(Condition condition, String conditionText, String errorGenerator, Type type, Map descriptiveTexts, - List extensions, Stanza stanza) { + List extensions) { super(descriptiveTexts, ERROR_CONDITION_AND_TEXT_NAMESPACE, extensions); this.condition = Objects.requireNonNull(condition, "condition must not be null"); - this.stanza = stanza; // Some implementations may send the condition as non-empty element containing the empty string, that is // , in this case the parser may calls this constructor with the empty string // as conditionText, therefore reset it to null if it's the empty string @@ -184,16 +181,6 @@ public class StanzaError extends AbstractError implements ExtensionElement { return conditionText; } - /** - * Get the stanza carrying the XMPP error. - * - * @return the stanza carrying the XMPP error. - * @since 4.2 - */ - public Stanza getStanza() { - return stanza; - } - @Override public String toString() { StringBuilder sb = new StringBuilder("XMPPError: "); @@ -271,7 +258,6 @@ public class StanzaError extends AbstractError implements ExtensionElement { private String conditionText; private String errorGenerator; private Type type; - private Stanza stanza; private Builder() { } @@ -296,17 +282,11 @@ public class StanzaError extends AbstractError implements ExtensionElement { return this; } - public Builder setStanza(Stanza stanza) { - this.stanza = stanza; - return this; - } - public Builder copyFrom(StanzaError xmppError) { setCondition(xmppError.getCondition()); setType(xmppError.getType()); setConditionText(xmppError.getConditionText()); setErrorGenerator(xmppError.getErrorGenerator()); - setStanza(xmppError.getStanza()); setDescriptiveTexts(xmppError.descriptiveTexts); setTextNamespace(xmppError.textNamespace); setExtensions(xmppError.extensions); @@ -315,7 +295,7 @@ public class StanzaError extends AbstractError implements ExtensionElement { public StanzaError build() { return new StanzaError(condition, conditionText, errorGenerator, type, descriptiveTexts, - extensions, stanza); + extensions); } @Override diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaFactory.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaFactory.java new file mode 100644 index 000000000..4a7a85ce8 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaFactory.java @@ -0,0 +1,49 @@ +/** + * + * 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 final class StanzaFactory { + + private final StanzaIdSource stanzaIdSource; + + public StanzaFactory(StanzaIdSource stanzaIdSource) { + this.stanzaIdSource = stanzaIdSource; + } + + public MessageBuilder buildMessageStanza() { + return new MessageBuilder(stanzaIdSource); + } + + public MessageBuilder buildMessageStanzaFrom(Message message) { + return new MessageBuilder(message, stanzaIdSource); + } + + public PresenceBuilder buildPresenceStanza() { + return new PresenceBuilder(stanzaIdSource); + } + + public PresenceBuilder buildPresenceStanzaFrom(Presence presence) { + return new PresenceBuilder(presence, stanzaIdSource); + } + + public IqBuilder buildIqStanza() { + return new IqBuilder(stanzaIdSource); + } + +} 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 new file mode 100644 index 000000000..4de119fef --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaView.java @@ -0,0 +1,82 @@ +/** + * + * 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 java.util.List; + +import javax.xml.namespace.QName; + +import org.jivesoftware.smack.util.XmppElementUtil; + +import org.jxmpp.jid.Jid; + +public interface StanzaView extends XmlLangElement { + + /** + * Returns the unique ID of the stanza. The returned value could be null. + * + * @return the packet's unique ID or null if the id is not available. + */ + String getStanzaId(); + + /** + * Returns who the stanza is being sent "to", or null if + * the value is not set. The XMPP protocol often makes the "to" + * attribute optional, so it does not always need to be set.

+ * + * @return who the stanza is being sent to, or null if the + * value has not been set. + */ + Jid getTo(); + + /** + * Returns who the stanza is being sent "from" or null if + * the value is not set. The XMPP protocol often makes the "from" + * attribute optional, so it does not always need to be set.

+ * + * @return who the stanza is being sent from, or null if the + * value has not been set. + */ + Jid getFrom(); + + /** + * Returns the error associated with this packet, or null if there are + * no errors. + * + * @return the error sub-packet or null if there isn't an error. + */ + StanzaError getError(); + + E getExtension(QName qname); + + @SuppressWarnings("unchecked") + default E getExtension(Class extensionElementClass) { + QName qname = XmppElementUtil.getQNameFor(extensionElementClass); + return (E) getExtension(qname); + } + + /** + * Returns a list of all extension elements of this stanza. + * + * @return a list of all extension elements of this stanza. + */ + List getExtensions(); + + List getExtensions(QName qname); + + List getExtensions(Class extensionElementClass); +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/XmlEnvironment.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/XmlEnvironment.java index 810d8f75f..defc09868 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/XmlEnvironment.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/XmlEnvironment.java @@ -18,7 +18,6 @@ package org.jivesoftware.smack.packet; import org.jivesoftware.smack.util.ParserUtils; import org.jivesoftware.smack.util.StringUtils; - import org.jivesoftware.smack.xml.XmlPullParser; public class XmlEnvironment { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/XmlLangElement.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/XmlLangElement.java new file mode 100644 index 000000000..27bf34d98 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/XmlLangElement.java @@ -0,0 +1,28 @@ +/** + * + * 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 interface XmlLangElement { + + /** + * Returns the xml:lang of this XML element, or null if one has not been set. + * + * @return the xml:lang of this XML element, or null. + */ + String getLanguage(); + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/id/RandomStringStanzaIdSource.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/id/RandomStringStanzaIdSource.java new file mode 100644 index 000000000..9d3768a1f --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/id/RandomStringStanzaIdSource.java @@ -0,0 +1,54 @@ +/** + * + * 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.id; + +import org.jivesoftware.smack.util.StringUtils; + +public final class RandomStringStanzaIdSource { + + public static class Factory implements StanzaIdSourceFactory { + + private static final int REQUIRED_MIN_LENGTH = 10; + + private final int length; + private final boolean verySecure; + + public static final Factory VERY_SECURE = new Factory(10, true); + public static final Factory MEDIUM_SECURE = new Factory(10, false); + + public Factory(int length, boolean verySecure) { + if (length < REQUIRED_MIN_LENGTH) { + throw new IllegalArgumentException( + "Insufficient length " + length + ", must be at least " + REQUIRED_MIN_LENGTH); + } + this.length = length; + this.verySecure = verySecure; + } + + @Override + public StanzaIdSource constructStanzaIdSource() { + StanzaIdSource stanzaIdSource; + if (verySecure) { + stanzaIdSource = () -> StringUtils.randomString(length); + } else { + stanzaIdSource = () -> StringUtils.insecureRandomString(length); + } + return stanzaIdSource; + } + + } +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/id/StanzaIdUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/id/StandardStanzaIdSource.java similarity index 59% rename from smack-core/src/main/java/org/jivesoftware/smack/packet/id/StanzaIdUtil.java rename to smack-core/src/main/java/org/jivesoftware/smack/packet/id/StandardStanzaIdSource.java index b13a877d3..45fcbaf3c 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/id/StanzaIdUtil.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/id/StandardStanzaIdSource.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2015 Florian Schmaus + * 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. @@ -20,20 +20,32 @@ import java.util.concurrent.atomic.AtomicLong; import org.jivesoftware.smack.util.StringUtils; -public class StanzaIdUtil { +public class StandardStanzaIdSource implements StanzaIdSource { + + public static final StandardStanzaIdSource DEFAULT = new StandardStanzaIdSource(); /** * A prefix helps to make sure that ID's are unique across multiple instances. */ - private static final String PREFIX = StringUtils.randomString(5) + "-"; + private final String prefix = StringUtils.randomString(5) + "-"; /** * Keeps track of the current increment, which is appended to the prefix to * forum a unique ID. */ - private static final AtomicLong ID = new AtomicLong(); + private final AtomicLong id = new AtomicLong(); + + @Override + public String getNewStanzaId() { + return prefix + Long.toString(id.incrementAndGet()); + } + + public static class Factory implements StanzaIdSourceFactory { + + @Override + public StandardStanzaIdSource constructStanzaIdSource() { + return new StandardStanzaIdSource(); + } - public static String newStanzaId() { - return PREFIX + Long.toString(ID.incrementAndGet()); } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/id/StanzaIdSource.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/id/StanzaIdSource.java new file mode 100644 index 000000000..4d75094ca --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/id/StanzaIdSource.java @@ -0,0 +1,21 @@ +/** + * + * 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.id; + +public interface StanzaIdSource { + String getNewStanzaId(); +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/id/StanzaIdSourceFactory.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/id/StanzaIdSourceFactory.java new file mode 100644 index 000000000..ed6c08b40 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/id/StanzaIdSourceFactory.java @@ -0,0 +1,21 @@ +/** + * + * 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.id; + +public interface StanzaIdSourceFactory { + StanzaIdSource constructStanzaIdSource(); +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/id/UuidStanzaIdSource.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/id/UuidStanzaIdSource.java new file mode 100644 index 000000000..dbe9b8a10 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/id/UuidStanzaIdSource.java @@ -0,0 +1,41 @@ +/** + * + * 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.id; + +import java.util.UUID; + +public final class UuidStanzaIdSource implements StanzaIdSource { + + public static final UuidStanzaIdSource INSTANCE = new UuidStanzaIdSource(); + + private UuidStanzaIdSource() { + } + + @Override + public String getNewStanzaId() { + return UUID.randomUUID().toString(); + } + + public static class Factory implements StanzaIdSourceFactory { + + @Override + public UuidStanzaIdSource constructStanzaIdSource() { + return INSTANCE; + } + + } +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/Function.java b/smack-core/src/main/java/org/jivesoftware/smack/util/Function.java new file mode 100644 index 000000000..760d3cf5d --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/Function.java @@ -0,0 +1,23 @@ +/** + * + * 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; + +public interface Function { + + R apply(T t); + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/MultiMap.java b/smack-core/src/main/java/org/jivesoftware/smack/util/MultiMap.java index d9ad987b6..ea58e469e 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/MultiMap.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/MultiMap.java @@ -34,7 +34,7 @@ import java.util.Set; * @param the type of the keys the map uses. * @param the type of the values the map uses. */ -public class MultiMap { +public class MultiMap implements TypedCloneable> { /** * The constant value {@value}. @@ -252,6 +252,19 @@ public class MultiMap { return new MultiMap(Collections.unmodifiableMap(mapCopy)); } + @Override + public MultiMap clone() { + Map> clonedMap = new LinkedHashMap<>(map.size()); + + // TODO: Use Map.forEach() once Smack's minimum Android API is 24 or higher. + for (Entry> entry : map.entrySet()) { + List clonedList = CollectionUtil.newListWith(entry.getValue()); + clonedMap.put(entry.getKey(), clonedList); + } + + return new MultiMap<>(clonedMap); + } + private static final class SimpleMapEntry implements Map.Entry { private final K key; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java index 665e90564..57aaab932 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.logging.Level; import java.util.logging.Logger; import org.jivesoftware.smack.compress.packet.Compress; @@ -36,9 +37,12 @@ import org.jivesoftware.smack.packet.ErrorIQ; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; 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.StanzaBuilder; import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smack.packet.StartTls; import org.jivesoftware.smack.packet.StreamError; @@ -120,18 +124,25 @@ public class PacketParserUtils { } } - private static void parseCommonStanzaAttributes(Stanza stanza, XmlPullParser parser, XmlEnvironment xmlEnvironment) throws XmppStringprepException { + private interface StanzaBuilderSupplier> { + SB get(String stanzaId); + } + + private static > SB parseCommonStanzaAttributes(StanzaBuilderSupplier stanzaBuilderSupplier, XmlPullParser parser, XmlEnvironment xmlEnvironment) throws XmppStringprepException { String id = parser.getAttributeValue("id"); - stanza.setStanzaId(id); + + SB stanzaBuilder = stanzaBuilderSupplier.get(id); Jid to = ParserUtils.getJidAttribute(parser, "to"); - stanza.setTo(to); + stanzaBuilder.to(to); Jid from = ParserUtils.getJidAttribute(parser, "from"); - stanza.setFrom(from); + stanzaBuilder.from(from); String language = ParserUtils.getXmlLang(parser, xmlEnvironment); - stanza.setLanguage(language); + stanzaBuilder.setLanguage(language); + + return stanzaBuilder; } public static Message parseMessage(XmlPullParser parser) throws XmlPullParserException, IOException, SmackParsingException { @@ -154,11 +165,14 @@ public class PacketParserUtils { XmlEnvironment messageXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment); final int initialDepth = parser.getDepth(); - Message message = new Message(); - parseCommonStanzaAttributes(message, parser, outerXmlEnvironment); + + MessageBuilder message = parseCommonStanzaAttributes(id -> { + return StanzaBuilder.buildMessage(id); + }, parser, outerXmlEnvironment); + String typeString = parser.getAttributeValue("", "type"); if (typeString != null) { - message.setType(Message.Type.fromString(typeString)); + message.ofType(Message.Type.fromString(typeString)); } // Parse sub-elements. We include extra logic to make sure the values @@ -176,9 +190,8 @@ public class PacketParserUtils { String xmlLangSubject = ParserUtils.getXmlLang(parser); String subject = parseElementText(parser); - if (message.getSubject(xmlLangSubject) == null) { - message.addSubject(xmlLangSubject, subject); - } + Message.Subject subjectExtensionElement = new Message.Subject(xmlLangSubject, subject); + message.addExtension(subjectExtensionElement); break; case "thread": if (thread == null) { @@ -189,7 +202,8 @@ public class PacketParserUtils { message.setError(parseError(parser, messageXmlEnvironment)); break; default: - PacketParserUtils.addExtensionElement(message, parser, elementName, namespace, messageXmlEnvironment); + ExtensionElement extensionElement = parseExtensionElement(elementName, namespace, parser, messageXmlEnvironment); + message.addExtension(extensionElement); break; } break; @@ -208,7 +222,7 @@ public class PacketParserUtils { // situations where we have a body element with an explicit xml lang set and once where the value is inherited // and both values are equal. - return message; + return message.build(); } /** @@ -436,13 +450,16 @@ public class PacketParserUtils { final int initialDepth = parser.getDepth(); XmlEnvironment presenceXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment); + PresenceBuilder presence = parseCommonStanzaAttributes( + stanzaId -> StanzaBuilder.buildPresence(stanzaId), parser, outerXmlEnvironment); + Presence.Type type = Presence.Type.available; String typeString = parser.getAttributeValue("", "type"); if (typeString != null && !typeString.equals("")) { type = Presence.Type.fromString(typeString); } - Presence presence = new Presence(type); - parseCommonStanzaAttributes(presence, parser, outerXmlEnvironment); + + presence.ofType(type); // Parse sub-elements outerloop: while (true) { @@ -468,9 +485,7 @@ public class PacketParserUtils { // '' element, which is a invalid XMPP presence // stanza according to RFC 6121 4.7.2.1 LOGGER.warning("Empty or null mode text in presence show element form " - + presence.getFrom() - + " with id '" - + presence.getStanzaId() + + presence + "' which is invalid according to RFC6121 4.7.2.1"); } break; @@ -482,10 +497,10 @@ public class PacketParserUtils { // Be extra robust: Skip PacketExtensions that cause Exceptions, instead of // failing completely here. See SMACK-390 for more information. try { - PacketParserUtils.addExtensionElement(presence, parser, elementName, namespace, presenceXmlEnvironment); + ExtensionElement extensionElement = parseExtensionElement(elementName, namespace, parser, presenceXmlEnvironment); + presence.addExtension(extensionElement); } catch (Exception e) { - LOGGER.warning("Failed to parse extension element in Presence stanza: \"" + e + "\" from: '" - + presence.getFrom() + " id: '" + presence.getStanzaId() + "'"); + LOGGER.log(Level.WARNING, "Failed to parse extension element in Presence stanza: " + presence, e); } break; } @@ -500,7 +515,8 @@ public class PacketParserUtils { break; } } - return presence; + + return presence.build(); } public static IQ parseIQ(XmlPullParser parser) throws Exception { @@ -523,7 +539,7 @@ public class PacketParserUtils { final int initialDepth = parser.getDepth(); XmlEnvironment iqXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment); IQ iqPacket = null; - StanzaError.Builder error = null; + StanzaError error = null; final String id = parser.getAttributeValue("", "id"); final Jid to = ParserUtils.getJidAttribute(parser, "to"); @@ -747,7 +763,7 @@ public class PacketParserUtils { return new StreamError(condition, conditionText, descriptiveTexts, extensions); } - public static StanzaError.Builder parseError(XmlPullParser parser) throws XmlPullParserException, IOException, SmackParsingException { + public static StanzaError parseError(XmlPullParser parser) throws XmlPullParserException, IOException, SmackParsingException { return parseError(parser, null); } @@ -761,7 +777,7 @@ public class PacketParserUtils { * @throws XmlPullParserException if an error in the XML parser occured. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input. */ - public static StanzaError.Builder parseError(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { + public static StanzaError parseError(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { final int initialDepth = parser.getDepth(); Map descriptiveTexts = null; XmlEnvironment stanzaErrorXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment); @@ -808,7 +824,8 @@ public class PacketParserUtils { } } builder.setExtensions(extensions).setDescriptiveTexts(descriptiveTexts); - return builder; + + return builder.build(); } /** diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java index eefccf862..09b3407ff 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java @@ -427,6 +427,13 @@ public class StringUtils { return true; } + public static boolean isNullOrNotEmpty(CharSequence cs) { + if (cs == null) { + return true; + } + return !cs.toString().isEmpty(); + } + /** * Returns true if the given CharSequence is empty. * @@ -456,6 +463,11 @@ public class StringUtils { */ public static StringBuilder toStringBuilder(Collection collection, String delimiter) { StringBuilder sb = new StringBuilder(collection.size() * 20); + appendTo(collection, delimiter, sb); + return sb; + } + + public static void appendTo(Collection collection, String delimiter, StringBuilder sb) { for (Iterator it = collection.iterator(); it.hasNext();) { Object cs = it.next(); sb.append(cs); @@ -463,7 +475,6 @@ public class StringUtils { sb.append(delimiter); } } - return sb; } public static String returnIfNotEmptyTrimmed(String string) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/ToStringUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/ToStringUtil.java new file mode 100644 index 000000000..447f1444f --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/ToStringUtil.java @@ -0,0 +1,75 @@ +/** + * + * 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; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class ToStringUtil { + + public static Builder builderFor(Class clazz) { + StringBuilder sb = new StringBuilder(); + sb.append(clazz.getSimpleName()).append('('); + return new Builder(sb); + } + + public static final class Builder { + private final StringBuilder sb; + + private Builder(StringBuilder sb) { + this.sb = sb; + } + + public Builder addValue(String name, Object value) { + if (value == null) { + return this; + } + if (sb.charAt(sb.length() - 1) != '(') { + sb.append(' '); + } + sb.append(name).append("='").append(value).append('\''); + return this; + } + + public Builder add(String name, Collection values, Function toStringFunction) { + if (values.isEmpty()) { + return this; + } + + sb.append(' ').append(name).append('['); + + List stringValues = new ArrayList<>(values.size()); + for (V value : values) { + String valueString = toStringFunction.apply(value).toString(); + stringValues.add(valueString); + } + + StringUtils.appendTo(stringValues, ", ", sb); + + sb.append(']'); + + return this; + } + + public String build() { + sb.append(')'); + + return sb.toString(); + } + } +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/XmppElementUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/XmppElementUtil.java index 492b551c6..315edfe2c 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/XmppElementUtil.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/XmppElementUtil.java @@ -16,6 +16,9 @@ */ package org.jivesoftware.smack.util; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.logging.Logger; import javax.xml.namespace.QName; @@ -52,4 +55,21 @@ public class XmppElementUtil { return new QName(namespace, element); } + public static List getElementsFrom( + MultiMap elementMap, Class extensionElementClass) { + QName qname = XmppElementUtil.getQNameFor(extensionElementClass); + + List extensionElements = elementMap.getAll(qname); + + if (extensionElements.isEmpty()) { + return Collections.emptyList(); + } + + List res = new ArrayList<>(extensionElements.size()); + for (E extensionElement : extensionElements) { + R e = extensionElementClass.cast(extensionElement); + res.add(e); + } + return res; + } } diff --git a/smack-core/src/test/java/org/jivesoftware/smack/filter/FromMatchesFilterTest.java b/smack-core/src/test/java/org/jivesoftware/smack/filter/FromMatchesFilterTest.java index c6f7089d4..98e14cb04 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/filter/FromMatchesFilterTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/filter/FromMatchesFilterTest.java @@ -19,8 +19,8 @@ package org.jivesoftware.smack.filter; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.junit.Test; import org.jxmpp.jid.EntityFullJid; @@ -47,7 +47,7 @@ public class FromMatchesFilterTest { @Test public void autoCompareMatchingEntityFullJid() { FromMatchesFilter filter = FromMatchesFilter.create(FULL_JID1_R1); - Stanza packet = new Message(); + Stanza packet = StanzaBuilder.buildMessage().build(); packet.setFrom(FULL_JID1_R1); assertTrue(filter.accept(packet)); @@ -71,7 +71,7 @@ public class FromMatchesFilterTest { @Test public void autoCompareMatchingBaseJid() { FromMatchesFilter filter = FromMatchesFilter.create(BASE_JID1); - Stanza packet = new Message(); + Stanza packet = StanzaBuilder.buildMessage().build(); packet.setFrom(BASE_JID1); assertTrue(filter.accept(packet)); @@ -95,7 +95,7 @@ public class FromMatchesFilterTest { @Test public void autoCompareMatchingServiceJid() { FromMatchesFilter filter = FromMatchesFilter.create(SERVICE_JID1); - Stanza packet = new Message(); + Stanza packet = StanzaBuilder.buildMessage().build(); packet.setFrom(SERVICE_JID1); assertTrue(filter.accept(packet)); @@ -116,7 +116,7 @@ public class FromMatchesFilterTest { @Test public void bareCompareMatchingEntityFullJid() { FromMatchesFilter filter = FromMatchesFilter.createBare(FULL_JID1_R1); - Stanza packet = new Message(); + Stanza packet = StanzaBuilder.buildMessage().build(); packet.setFrom(BASE_JID1); assertTrue(filter.accept(packet)); @@ -140,7 +140,7 @@ public class FromMatchesFilterTest { @Test public void bareCompareMatchingBaseJid() { FromMatchesFilter filter = FromMatchesFilter.createBare(BASE_JID1); - Stanza packet = new Message(); + Stanza packet = StanzaBuilder.buildMessage().build(); packet.setFrom(BASE_JID1); assertTrue(filter.accept(packet)); @@ -164,7 +164,7 @@ public class FromMatchesFilterTest { @Test public void bareCompareMatchingServiceJid() { FromMatchesFilter filter = FromMatchesFilter.createBare(SERVICE_JID1); - Stanza packet = new Message(); + Stanza packet = StanzaBuilder.buildMessage().build(); packet.setFrom(SERVICE_JID1); assertTrue(filter.accept(packet)); @@ -185,7 +185,7 @@ public class FromMatchesFilterTest { @Test public void fullCompareMatchingEntityFullJid() { FromMatchesFilter filter = FromMatchesFilter.createFull(FULL_JID1_R1); - Stanza packet = new Message(); + Stanza packet = StanzaBuilder.buildMessage().build(); packet.setFrom(FULL_JID1_R1); assertTrue(filter.accept(packet)); @@ -209,7 +209,7 @@ public class FromMatchesFilterTest { @Test public void fullCompareMatchingBaseJid() { FromMatchesFilter filter = FromMatchesFilter.createFull(BASE_JID1); - Stanza packet = new Message(); + Stanza packet = StanzaBuilder.buildMessage().build(); packet.setFrom(BASE_JID1); assertTrue(filter.accept(packet)); @@ -233,7 +233,7 @@ public class FromMatchesFilterTest { @Test public void fullCompareMatchingServiceJid() { FromMatchesFilter filter = FromMatchesFilter.createFull(SERVICE_JID1); - Stanza packet = new Message(); + Stanza packet = StanzaBuilder.buildMessage().build(); packet.setFrom(SERVICE_JID1); assertTrue(filter.accept(packet)); diff --git a/smack-core/src/test/java/org/jivesoftware/smack/packet/IQResponseTest.java b/smack-core/src/test/java/org/jivesoftware/smack/packet/IQResponseTest.java index 5807f5f0b..2d2f0524e 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/packet/IQResponseTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/packet/IQResponseTest.java @@ -62,7 +62,7 @@ public class IQResponseTest { */ @Test public void testGeneratingValidErrorResponse() throws XmppStringprepException { - final StanzaError.Builder error = StanzaError.getBuilder(StanzaError.Condition.bad_request); + final StanzaError error = StanzaError.getBuilder(StanzaError.Condition.bad_request).build(); final IQ request = new TestIQ(ELEMENT, NAMESPACE); request.setType(IQ.Type.set); @@ -75,7 +75,7 @@ public class IQResponseTest { assertNotNull(result.getStanzaId()); assertEquals(request.getStanzaId(), result.getStanzaId()); assertEquals(request.getFrom(), result.getTo()); - assertEquals(error.build().toXML().toString(), result.getError().toXML().toString()); + assertEquals(error.toXML().toString(), result.getError().toXML().toString()); // TODO this test was never valid // assertEquals(CHILD_ELEMENT, result.getChildElementXML()); } @@ -110,7 +110,7 @@ public class IQResponseTest { */ @Test public void testGeneratingErrorBasedOnError() throws XmppStringprepException { - final StanzaError.Builder error = StanzaError.getBuilder(StanzaError.Condition.bad_request); + final StanzaError error = StanzaError.getBuilder(StanzaError.Condition.bad_request).build(); final IQ request = new TestIQ(ELEMENT, NAMESPACE); request.setType(IQ.Type.error); diff --git a/smack-core/src/test/java/org/jivesoftware/smack/packet/MessageTest.java b/smack-core/src/test/java/org/jivesoftware/smack/packet/MessageTest.java index 82ff71bf8..68d8535fa 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/packet/MessageTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/packet/MessageTest.java @@ -18,7 +18,6 @@ package org.jivesoftware.smack.packet; import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; @@ -44,10 +43,12 @@ public class MessageTest { .append(""); String control = controlBuilder.toString(); - Message messageTypeInConstructor = new Message(null, Message.Type.chat); - messageTypeInConstructor.setStanzaId(null); - assertEquals(type, messageTypeInConstructor.getType()); - assertXmlSimilar(control, messageTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); + Message messageBuildWithBuilder = StanzaBuilder.buildMessage() + .ofType(Message.Type.chat) + .build(); + + assertEquals(type, messageBuildWithBuilder.getType()); + assertXmlSimilar(control, messageBuildWithBuilder.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); controlBuilder = new StringBuilder(); controlBuilder.append(""); control = controlBuilder.toString(); - Message messageTypeSet = getNewMessage(); - messageTypeSet.setType(type2); + Message messageTypeSet = StanzaBuilder.buildMessage() + .ofType(type2) + .build(); assertEquals(type2, messageTypeSet.getType()); assertXmlSimilar(control, messageTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } @Test(expected = NullPointerException.class) public void setNullMessageBodyTest() { - Message message = getNewMessage(); - message.addBody(null, null); + StanzaBuilder.buildMessage() + .addBody(null, null) + .build(); } @Test @@ -81,9 +84,9 @@ public class MessageTest { .append(""); String control = controlBuilder.toString(); - Message message = getNewMessage(); - message.setSubject(messageSubject); - + Message message = StanzaBuilder.buildMessage() + .setSubject(messageSubject) + .build(); assertEquals(messageSubject, message.getSubject()); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } @@ -100,9 +103,9 @@ public class MessageTest { .append(""); String control = controlBuilder.toString(); - Message message = getNewMessage(); - message.setBody(messageBody); - + Message message = StanzaBuilder.buildMessage() + .setBody(messageBody) + .build(); assertEquals(messageBody, message.getBody()); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } @@ -133,10 +136,11 @@ public class MessageTest { .append(""); String control = controlBuilder.toString(); - Message message = getNewMessage(); - message.addBody(null, messageBody1); - message.addBody(lang2, messageBody2); - message.addBody(lang3, messageBody3); + Message message = StanzaBuilder.buildMessage() + .addBody(null, messageBody1) + .addBody(lang2, messageBody2) + .addBody(lang3, messageBody3) + .build(); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE)); Collection languages = message.getBodyLanguages(); @@ -148,21 +152,20 @@ public class MessageTest { } @Test - public void removeMessageBodyTest() { - Message message = getNewMessage(); - message.setBody("test"); + public void simpleMessageBodyTest() { + Message message = StanzaBuilder.buildMessage() + .setBody("test") + .build(); assertTrue(message.getBodies().size() == 1); - message.setBody(null); + message = StanzaBuilder.buildMessage().build(); assertTrue(message.getBodies().size() == 0); - assertFalse(message.removeBody("sp")); - Message.Body body = message.addBody("es", "test"); + message = StanzaBuilder.buildMessage() + .addBody("es", "test") + .build(); assertTrue(message.getBodies().size() == 1); - - message.removeBody(body); - assertTrue(message.getBodies().size() == 0); } @Test @@ -177,8 +180,9 @@ public class MessageTest { .append(""); String control = controlBuilder.toString(); - Message message = getNewMessage(); - message.setThread(messageThread); + Message message = StanzaBuilder.buildMessage() + .setThread(messageThread) + .build(); assertEquals(messageThread, message.getThread()); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); @@ -196,15 +200,10 @@ public class MessageTest { .append(""); String control = controlBuilder.toString(); - Message message = getNewMessage(); - message.setLanguage(lang); + Message message = StanzaBuilder.buildMessage() + .setLanguage(lang) + .build(); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } - - private static Message getNewMessage() { - Message message = new Message(); - message.setStanzaId(null); - return message; - } } diff --git a/smack-core/src/test/java/org/jivesoftware/smack/packet/PresenceTest.java b/smack-core/src/test/java/org/jivesoftware/smack/packet/PresenceTest.java index a86e07646..863e4b0ff 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/packet/PresenceTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/packet/PresenceTest.java @@ -41,8 +41,9 @@ public class PresenceTest { .append(""); String control = controlBuilder.toString(); - Presence presenceTypeInConstructor = new Presence(type); - presenceTypeInConstructor.setStanzaId(null); + Presence presenceTypeInConstructor = StanzaBuilder.buildPresence() + .ofType(type) + .build(); assertEquals(type, presenceTypeInConstructor.getType()); assertXmlSimilar(control, presenceTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); @@ -54,27 +55,27 @@ public class PresenceTest { .append(""); control = controlBuilder.toString(); - Presence presenceTypeSet = getNewPresence(); - presenceTypeSet.setType(type2); + PresenceBuilder presenceTypeSet = getNewPresence(); + presenceTypeSet.ofType(type2); assertEquals(type2, presenceTypeSet.getType()); - assertXmlSimilar(control, presenceTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); + assertXmlSimilar(control, presenceTypeSet.build().toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } @Test public void setNullPresenceTypeTest() { assertThrows(IllegalArgumentException.class, () -> - getNewPresence().setType(null) + getNewPresence().ofType(null) ); } @Test public void isPresenceAvailableTest() { - Presence presence = getNewPresence(); - presence.setType(Presence.Type.available); - assertTrue(presence.isAvailable()); + PresenceBuilder presence = getNewPresence(); + presence.ofType(Presence.Type.available); + assertTrue(presence.build().isAvailable()); - presence.setType(Presence.Type.unavailable); - assertFalse(presence.isAvailable()); + presence.ofType(Presence.Type.unavailable); + assertFalse(presence.build().isAvailable()); } @Test @@ -89,11 +90,11 @@ public class PresenceTest { .append(""); String control = controlBuilder.toString(); - Presence presence = getNewPresence(); + PresenceBuilder presence = getNewPresence(); presence.setStatus(status); assertEquals(status, presence.getStatus()); - assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); + assertXmlSimilar(control, presence.build().toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } @Test @@ -108,11 +109,11 @@ public class PresenceTest { .append(""); String control = controlBuilder.toString(); - Presence presence = getNewPresence(); + PresenceBuilder presence = getNewPresence(); presence.setPriority(priority); assertEquals(priority, presence.getPriority()); - assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); + assertXmlSimilar(control, presence.build().toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } @Test @@ -143,11 +144,14 @@ public class PresenceTest { .append(""); String control = controlBuilder.toString(); - Presence presenceModeInConstructor = new Presence(Presence.Type.available, status, priority, - mode1); - presenceModeInConstructor.setStanzaId(null); - assertEquals(mode1, presenceModeInConstructor.getMode()); - assertXmlSimilar(control, presenceModeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); + Presence presenceBuildWithBuilder = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .setStatus(status) + .setPriority(priority) + .setMode(mode1) + .build(); + assertEquals(mode1, presenceBuildWithBuilder.getMode()); + assertXmlSimilar(control, presenceBuildWithBuilder.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); controlBuilder = new StringBuilder(); controlBuilder.append("") @@ -157,20 +161,20 @@ public class PresenceTest { .append(""); control = controlBuilder.toString(); - Presence presenceModeSet = getNewPresence(); + PresenceBuilder presenceModeSet = getNewPresence(); presenceModeSet.setMode(mode2); assertEquals(mode2, presenceModeSet.getMode()); - assertXmlSimilar(control, presenceModeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); + assertXmlSimilar(control, presenceModeSet.build().toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } @Test public void isModeAwayTest() { - Presence presence = getNewPresence(); + PresenceBuilder presence = getNewPresence(); presence.setMode(Presence.Mode.away); - assertTrue(presence.isAway()); + assertTrue(presence.build().isAway()); presence.setMode(Presence.Mode.chat); - assertFalse(presence.isAway()); + assertFalse(presence.build().isAway()); } @Test @@ -185,15 +189,14 @@ public class PresenceTest { .append(""); String control = controlBuilder.toString(); - Presence presence = getNewPresence(); + PresenceBuilder presence = getNewPresence(); presence.setLanguage(lang); - assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); + assertXmlSimilar(control, presence.build().toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } - private static Presence getNewPresence() { - Presence presence = new Presence(Presence.Type.available); - presence.setStanzaId(null); + private static PresenceBuilder getNewPresence() { + PresenceBuilder presence = StanzaBuilder.buildPresence().ofType(Presence.Type.available); return presence; } } diff --git a/smack-core/src/test/java/org/jivesoftware/smack/packet/ToStringTest.java b/smack-core/src/test/java/org/jivesoftware/smack/packet/ToStringTest.java index a591585f9..1398c66f7 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/packet/ToStringTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/packet/ToStringTest.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2016-2017 Florian Schmaus + * Copyright © 2016-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. @@ -18,8 +18,6 @@ package org.jivesoftware.smack.packet; import static org.junit.Assert.assertEquals; -import org.jivesoftware.smack.packet.Presence.Mode; - import org.junit.Test; import org.jxmpp.jid.JidTestUtil; @@ -27,15 +25,21 @@ public class ToStringTest { @Test public void messageTest() { - Message message = new Message(JidTestUtil.BARE_JID_1, Message.Type.headline); - message.setStanzaId("message-id"); + Message message = StanzaBuilder.buildMessage("message-id") + .ofType(Message.Type.headline) + .to(JidTestUtil.BARE_JID_1) + .build(); String string = message.toString(); assertEquals("Message Stanza [to=one@exampleone.org,id=message-id,type=headline,]", string); } @Test public void presenceTest() { - Presence presence = new Presence(Presence.Type.subscribe, null, 0, Mode.away); + Presence presence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.subscribe) + .setPriority(0) + .setMode(Presence.Mode.away) + .build(); presence.setStanzaId("presence-id"); String string = presence.toString(); assertEquals("Presence Stanza [id=presence-id,type=subscribe,mode=away,prio=0,]", string); diff --git a/smack-core/src/test/java/org/jivesoftware/smack/packet/XMPPErrorTest.java b/smack-core/src/test/java/org/jivesoftware/smack/packet/XMPPErrorTest.java index c2807ad77..3ca877576 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/packet/XMPPErrorTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/packet/XMPPErrorTest.java @@ -16,12 +16,13 @@ */ package org.jivesoftware.smack.packet; -import static org.jivesoftware.smack.packet.StanzaError.Condition; -import static org.jivesoftware.smack.packet.StanzaError.Type; import static org.junit.Assert.assertEquals; import java.util.Map; +import org.jivesoftware.smack.packet.StanzaError.Condition; +import org.jivesoftware.smack.packet.StanzaError.Type; + import org.junit.Test; public class XMPPErrorTest { diff --git a/smack-core/src/test/java/org/jivesoftware/smack/util/PacketParserUtilsTest.java b/smack-core/src/test/java/org/jivesoftware/smack/util/PacketParserUtilsTest.java index 90dd82b9d..d6e243351 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/util/PacketParserUtilsTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/util/PacketParserUtilsTest.java @@ -45,7 +45,6 @@ import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; import com.jamesmurty.utils.XMLBuilder; - import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -547,30 +546,6 @@ public class PacketParserUtilsTest { assertTrue(message.getSubjectLanguages().contains(otherLanguage)); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); - // message has default language, first subject no language, second subject default language - control = XMLBuilder.create("message") - .a("from", "romeo@montague.lit/orchard") - .a("to", "juliet@capulet.lit/balcony") - .a("id", "zid615d9") - .a("type", "chat") - .a("xml:lang", defaultLanguage) - .e("subject") - .t(defaultLanguage) - .up() - .e("subject") - .a("xml:lang", defaultLanguage) - .t(defaultLanguage + "2") - .asString(outputProperties); - - message = PacketParserUtils - .parseMessage(PacketParserUtils.getParserFor(control)); - - assertEquals(defaultLanguage, message.getSubject()); - assertEquals(defaultLanguage, message.getSubject(defaultLanguage)); - assertEquals(1, message.getSubjects().size()); - assertEquals(0, message.getSubjectLanguages().size()); - assertXmlNotSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); - // message has non-default language, first subject no language, second subject default language control = XMLBuilder.create("message") .a("from", "romeo@montague.lit/orchard") @@ -867,7 +842,7 @@ public class PacketParserUtilsTest { .element("text", StanzaError.ERROR_CONDITION_AND_TEXT_NAMESPACE).t(text).up() .asString(); XmlPullParser parser = TestUtils.getParser(errorXml); - StanzaError error = PacketParserUtils.parseError(parser).build(); + StanzaError error = PacketParserUtils.parseError(parser); assertEquals(text, error.getDescriptiveText()); } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/DnsOverXmppManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/DnsOverXmppManager.java index 618cb1d67..1ffba5597 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/DnsOverXmppManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/DnsOverXmppManager.java @@ -88,10 +88,11 @@ public final class DnsOverXmppManager extends Manager { try { response = resolver.resolve(query); } catch (IOException exception) { - StanzaError.Builder errorBuilder = StanzaError.getBuilder() + StanzaError errorBuilder = StanzaError.getBuilder() .setType(Type.CANCEL) .setCondition(Condition.internal_server_error) .setDescriptiveEnText("Exception while resolving your DNS query", exception) + .build() ; IQ errorResponse = IQ.createErrorResponse(iqRequest, errorBuilder); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/eme/element/ExplicitMessageEncryptionElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/eme/element/ExplicitMessageEncryptionElement.java index 5e47cd34f..4c6cf0015 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/eme/element/ExplicitMessageEncryptionElement.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/eme/element/ExplicitMessageEncryptionElement.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. @@ -20,8 +20,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.MessageView; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.XmlStringBuilder; @@ -33,6 +37,8 @@ public class ExplicitMessageEncryptionElement implements ExtensionElement { public static final String NAMESPACE = "urn:xmpp:eme:0"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); + public enum ExplicitMessageEncryptionProtocol { /** @@ -154,14 +160,12 @@ public class ExplicitMessageEncryptionElement implements ExtensionElement { * @param protocolNamespace namespace * @return true if message has EME element for that namespace, otherwise false */ - public static boolean hasProtocol(Message message, String protocolNamespace) { - List extensionElements = message.getExtensions( - ExplicitMessageEncryptionElement.ELEMENT, - ExplicitMessageEncryptionElement.NAMESPACE); + public static boolean hasProtocol(MessageView message, String protocolNamespace) { + List emeElements = message + .getExtensions(ExplicitMessageEncryptionElement.class); - for (ExtensionElement extensionElement : extensionElements) { - ExplicitMessageEncryptionElement e = (ExplicitMessageEncryptionElement) extensionElement; - if (e.getEncryptionNamespace().equals(protocolNamespace)) { + for (ExplicitMessageEncryptionElement emeElement : emeElements) { + if (emeElement.getEncryptionNamespace().equals(protocolNamespace)) { return true; } } @@ -176,7 +180,7 @@ public class ExplicitMessageEncryptionElement implements ExtensionElement { * @param protocol protocol * @return true if message has EME element for that namespace, otherwise false */ - public static boolean hasProtocol(Message message, ExplicitMessageEncryptionProtocol protocol) { + public static boolean hasProtocol(MessageView message, ExplicitMessageEncryptionProtocol protocol) { return hasProtocol(message, protocol.namespace); } @@ -184,10 +188,10 @@ public class ExplicitMessageEncryptionElement implements ExtensionElement { * Add an EME element containing the specified {@code protocol} namespace to the message. * In case there is already an element with that protocol, we do nothing. * - * @param message message + * @param message a message builder. * @param protocol encryption protocol */ - public static void set(Message message, ExplicitMessageEncryptionProtocol protocol) { + public static void set(MessageBuilder message, ExplicitMessageEncryptionProtocol protocol) { if (!hasProtocol(message, protocol.namespace)) { message.addExtension(new ExplicitMessageEncryptionElement(protocol)); } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hints/element/StoreHint.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hints/element/StoreHint.java index aea9de720..a7f6e052a 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hints/element/StoreHint.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hints/element/StoreHint.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,7 +16,10 @@ */ package org.jivesoftware.smackx.hints.element; -import org.jivesoftware.smack.packet.Message; +import javax.xml.namespace.QName; + +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.MessageView; /** * A "store" hint. Messages with this hint should be stored in permanent stores or archives. @@ -29,6 +32,8 @@ public final class StoreHint extends MessageProcessingHint { public static final String ELEMENT = "store"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); + private StoreHint() { } @@ -47,15 +52,15 @@ public final class StoreHint extends MessageProcessingHint { return MessageProcessingHintType.store; } - public static StoreHint from(Message message) { - return message.getExtension(ELEMENT, NAMESPACE); + public static StoreHint from(MessageView message) { + return message.getExtension(QNAME); } - public static boolean hasHint(Message message) { + public static boolean hasHint(MessageView message) { return from(message) != null; } - public static void set(Message message) { + public static void set(MessageBuilder message) { message.overrideExtension(INSTANCE); } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/element/IoTSetResponse.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/element/IoTSetResponse.java index 68fce1441..1f89efa0e 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/element/IoTSetResponse.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/element/IoTSetResponse.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2016 Florian Schmaus + * Copyright © 2016-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. @@ -17,19 +17,25 @@ package org.jivesoftware.smackx.iot.control.element; import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; public class IoTSetResponse extends IQ { public static final String ELEMENT = "setResponse"; public static final String NAMESPACE = Constants.IOT_CONTROL_NAMESPACE; + public IoTSetResponse(IqBuilder iqBuilder) { + super(iqBuilder, ELEMENT, NAMESPACE); + } + + // TODO: Deprecate when stanza build is ready. public IoTSetResponse() { super(ELEMENT, NAMESPACE); } public IoTSetResponse(IoTSetRequest iotSetRequest) { - this(); - initializeAsResultFor(iotSetRequest); + this(StanzaBuilder.buildIqResultFor(iotSetRequest)); } @Override diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/IoTDataManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/IoTDataManager.java index 582fdbf0f..8375d01cf 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/IoTDataManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/IoTDataManager.java @@ -125,10 +125,14 @@ public final class IoTDataManager extends IoTManager { @Override public void momentaryReadOut(List results) { IoTFieldsExtension iotFieldsExtension = IoTFieldsExtension.buildFor(dataRequest.getSequenceNr(), true, thing.getNodeInfo(), results); - Message message = new Message(dataRequest.getFrom()); - message.addExtension(iotFieldsExtension); + + XMPPConnection connection = connection(); + Message message = connection.getStanzaFactory().buildMessageStanza() + .to(dataRequest.getFrom()) + .addExtension(iotFieldsExtension) + .build(); try { - connection().sendStanza(message); + connection.sendStanza(message); } catch (NotConnectedException | InterruptedException e) { LOGGER.log(Level.SEVERE, "Could not send read-out response " + message, e); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/IoTProvisioningManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/IoTProvisioningManager.java index e89d6b8d1..ce17ee27d 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/IoTProvisioningManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/IoTProvisioningManager.java @@ -140,8 +140,10 @@ public final class IoTProvisioningManager extends Manager { + " is already not subscribed to our presence."); return; } - Presence unsubscribed = new Presence(Presence.Type.unsubscribed); - unsubscribed.setTo(unfriendJid); + Presence unsubscribed = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.unsubscribed) + .to(unfriendJid) + .build(); connection.sendStanza(unsubscribed); } }, UNFRIEND_MESSAGE); @@ -162,7 +164,10 @@ public final class IoTProvisioningManager extends Manager { // friendship requests. final XMPPConnection connection = connection(); Friend friendNotification = new Friend(connection.getUser().asBareJid()); - Message notificationMessage = new Message(friendJid, friendNotification); + Message notificationMessage = connection.getStanzaFactory().buildMessageStanza() + .to(friendJid) + .addExtension(friendNotification) + .build(); connection.sendStanza(notificationMessage); } else { // Check is the message was send from a thing we previously @@ -359,8 +364,11 @@ public final class IoTProvisioningManager extends Manager { } public void sendFriendshipRequest(BareJid bareJid) throws NotConnectedException, InterruptedException { - Presence presence = new Presence(Presence.Type.subscribe); - presence.setTo(bareJid); + XMPPConnection connection = connection(); + Presence presence = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.subscribe) + .to(bareJid) + .build(); friendshipRequestedCache.put(bareJid, null); @@ -379,9 +387,12 @@ public final class IoTProvisioningManager extends Manager { public void unfriend(Jid friend) throws NotConnectedException, InterruptedException { if (isMyFriend(friend)) { - Presence presence = new Presence(Presence.Type.unsubscribed); - presence.setTo(friend); - connection().sendStanza(presence); + XMPPConnection connection = connection(); + Presence presence = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.unsubscribed) + .to(friend) + .build(); + connection.sendStanza(presence); } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLight.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLight.java index aa43bb535..8534e4021 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLight.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLight.java @@ -35,8 +35,8 @@ import org.jivesoftware.smack.filter.MessageTypeFilter; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Stanza; - import org.jivesoftware.smackx.muclight.element.MUCLightAffiliationsIQ; import org.jivesoftware.smackx.muclight.element.MUCLightChangeAffiliationsIQ; import org.jivesoftware.smackx.muclight.element.MUCLightConfigurationIQ; @@ -126,9 +126,9 @@ public class MultiUserChatLight { * @throws InterruptedException if the calling thread was interrupted. */ public void sendMessage(String text) throws NotConnectedException, InterruptedException { - Message message = createMessage(); + MessageBuilder message = buildMessage(); message.setBody(text); - connection.sendStanza(message); + connection.sendStanza(message.build()); } /** @@ -157,9 +157,28 @@ public class MultiUserChatLight { * Creates a new Message to send to the chat room. * * @return a new Message addressed to the chat room. + * @deprecated use {@link #buildMessage()} instead. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public Message createMessage() { - return new Message(room, Message.Type.groupchat); + return connection.getStanzaFactory().buildMessageStanza() + .ofType(Message.Type.groupchat) + .to(room) + .build(); + } + + /** + * Constructs a new message builder for messages send to this MUC room. + * + * @return a new message builder. + */ + public MessageBuilder buildMessage() { + return connection.getStanzaFactory() + .buildMessageStanza() + .ofType(Message.Type.groupchat) + .to(room) + ; } /** @@ -169,10 +188,23 @@ public class MultiUserChatLight { * the message. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. + * @deprecated use {@link #sendMessage(MessageBuilder)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void sendMessage(Message message) throws NotConnectedException, InterruptedException { - message.setTo(room); - message.setType(Message.Type.groupchat); + sendMessage(message.asBuilder()); + } + + /** + * Sends a Message to the chat room. + * + * @param messageBuilder the message. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + */ + public void sendMessage(MessageBuilder messageBuilder) throws NotConnectedException, InterruptedException { + Message message = messageBuilder.to(room).ofType(Message.Type.groupchat).build(); connection.sendStanza(message); } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/provider/RemoteDisablingProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/provider/RemoteDisablingProvider.java index a19e53cce..2f6c55fbc 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/provider/RemoteDisablingProvider.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/provider/RemoteDisablingProvider.java @@ -50,7 +50,9 @@ public class RemoteDisablingProvider extends ExtensionElementProvider extensions = message.getExtensions(); assertEquals(0, extensions.size()); + MessageBuilder messageBuilder = StanzaBuilder.buildMessage(); // Add OMEMO - ExplicitMessageEncryptionElement.set(message, + ExplicitMessageEncryptionElement.set(messageBuilder, ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl); + + message = messageBuilder.build(); extensions = message.getExtensions(); assertEquals(1, extensions.size()); assertTrue(ExplicitMessageEncryptionElement.hasProtocol(message, @@ -59,8 +64,10 @@ public class ExplicitMessageEncryptionElementTest extends SmackTestSuite { assertFalse(ExplicitMessageEncryptionElement.hasProtocol(message, ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.openpgpV0.getNamespace())); - ExplicitMessageEncryptionElement.set(message, + ExplicitMessageEncryptionElement.set(messageBuilder, ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.openpgpV0); + + message = messageBuilder.build(); extensions = message.getExtensions(); assertEquals(2, extensions.size()); assertTrue(ExplicitMessageEncryptionElement.hasProtocol(message, @@ -69,9 +76,10 @@ public class ExplicitMessageEncryptionElementTest extends SmackTestSuite { ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl)); // Check, if adding additional OMEMO wont add another element - ExplicitMessageEncryptionElement.set(message, + ExplicitMessageEncryptionElement.set(messageBuilder, ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl); + message = messageBuilder.build(); extensions = message.getExtensions(); assertEquals(2, extensions.size()); } diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/QueryArchiveTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/QueryArchiveTest.java index f523a8c3b..bc4360eef 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/QueryArchiveTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/QueryArchiveTest.java @@ -25,6 +25,7 @@ import java.util.TimeZone; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message.Type; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smackx.delay.packet.DelayInformation; @@ -62,21 +63,21 @@ public class QueryArchiveTest extends MamTest { @Test public void checkMamQueryResults() throws Exception { - Message message = new Message(); - message.setStanzaId("iasd207"); - message.setFrom(JidCreate.from("coven@chat.shakespeare.lit")); - message.setTo(JidCreate.from("hag66@shakespeare.lit/pda")); + Message message = StanzaBuilder.buildMessage("iasd207") + .from("coven@chat.shakespeare.lit") + .to("hag66@shakespeare.lit/pda") + .build(); GregorianCalendar calendar = new GregorianCalendar(2002, 10 - 1, 13, 23, 58, 37); calendar.setTimeZone(TimeZone.getTimeZone("UTC")); Date date = calendar.getTime(); DelayInformation delay = new DelayInformation(date); - Message forwardedMessage = new Message(); - forwardedMessage.setFrom(JidCreate.from("coven@chat.shakespeare.lit/firstwitch")); - forwardedMessage.setStanzaId("162BEBB1-F6DB-4D9A-9BD8-CFDCC801A0B2"); - forwardedMessage.setType(Type.chat); - forwardedMessage.setBody("Thrice the brinded cat hath mew."); + Message forwardedMessage = StanzaBuilder.buildMessage("162BEBB1-F6DB-4D9A-9BD8-CFDCC801A0B2") + .from(JidCreate.from("coven@chat.shakespeare.lit/firstwitch")) + .ofType(Type.chat) + .setBody("Thrice the brinded cat hath mew.") + .build(); Forwarded forwarded = new Forwarded(delay, forwardedMessage); diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/push_notifications/RemoteDisablingPushNotificationsTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/push_notifications/RemoteDisablingPushNotificationsTest.java index 2fe5dcbba..cc09aad4b 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/push_notifications/RemoteDisablingPushNotificationsTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/push_notifications/RemoteDisablingPushNotificationsTest.java @@ -18,7 +18,9 @@ package org.jivesoftware.smackx.push_notifications; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.IOException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.util.PacketParserUtils; @@ -56,18 +58,12 @@ public class RemoteDisablingPushNotificationsTest { @Test public void checkWrongRemoteDisablighPushNotifications() throws Exception { - Message message1 = PacketParserUtils.parseStanza(wrongRemoteDisabling1); - RemoteDisablingExtension remoteDisablingExtension1 = RemoteDisablingExtension.from(message1); - assertNull(remoteDisablingExtension1); + assertThrows(IOException.class, () -> PacketParserUtils.parseStanza(wrongRemoteDisabling1)); - Message message2 = PacketParserUtils.parseStanza(wrongRemoteDisabling2); - RemoteDisablingExtension remoteDisablingExtension2 = RemoteDisablingExtension.from(message2); - assertNull(remoteDisablingExtension2); + assertThrows(IOException.class, () -> PacketParserUtils.parseStanza(wrongRemoteDisabling2)); Message message3 = PacketParserUtils.parseStanza(wrongRemoteDisabling3); assertNotNull(message3); - // RemoteDisablingExtension remoteDisablingExtension3 = RemoteDisablingExtension.from(message3); - // assertNull(remoteDisablingExtension3); } } 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 a344b2bd6..3e6ac3027 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.StanzaBuilder; import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smack.util.PacketParserUtils; @@ -70,7 +71,7 @@ public class StableUniqueStanzaIdTest extends SmackTestSuite { @Test public void fromMessageTest() { - Message message = new Message(); + Message message = StanzaBuilder.buildMessage().build(); assertFalse(OriginIdElement.hasOriginId(message)); assertFalse(StanzaIdElement.hasStanzaId(message)); diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/spoiler/SpoilerTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/spoiler/SpoilerTest.java index 748035f9d..585d73a06 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/spoiler/SpoilerTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/spoiler/SpoilerTest.java @@ -25,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Map; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smack.xml.XmlPullParser; @@ -40,7 +41,7 @@ public class SpoilerTest extends SmackTestSuite { public void emptySpoilerTest() throws Exception { final String xml = ""; - Message message = new Message(); + Message message = StanzaBuilder.buildMessage().build(); SpoilerElement.addSpoiler(message); SpoilerElement empty = message.getExtension(SpoilerElement.ELEMENT, SpoilerManager.NAMESPACE_0); @@ -59,7 +60,7 @@ public class SpoilerTest extends SmackTestSuite { public void hintSpoilerTest() throws Exception { final String xml = "Love story end"; - Message message = new Message(); + Message message = StanzaBuilder.buildMessage().build(); SpoilerElement.addSpoiler(message, "Love story end"); SpoilerElement withHint = message.getExtension(SpoilerElement.ELEMENT, SpoilerManager.NAMESPACE_0); @@ -79,7 +80,7 @@ public class SpoilerTest extends SmackTestSuite { public void i18nHintSpoilerTest() throws Exception { final String xml = "Der Kuchen ist eine Lüge!"; - Message message = new Message(); + Message message = StanzaBuilder.buildMessage().build(); SpoilerElement.addSpoiler(message, "de", "Der Kuchen ist eine Lüge!"); SpoilerElement i18nHint = message.getExtension(SpoilerElement.ELEMENT, SpoilerManager.NAMESPACE_0); @@ -98,7 +99,7 @@ public class SpoilerTest extends SmackTestSuite { @Test public void getSpoilersTest() { - Message m = new Message(); + Message m = StanzaBuilder.buildMessage().build(); assertTrue(SpoilerElement.getSpoilers(m).isEmpty()); SpoilerElement.addSpoiler(m); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/Chat.java b/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/Chat.java index 2dd93d9ed..3b7c31d95 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/Chat.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/Chat.java @@ -40,9 +40,12 @@ public final class Chat extends Manager { } public void send(CharSequence message) throws NotConnectedException, InterruptedException { - Message stanza = new Message(); - stanza.setBody(message); - stanza.setType(Message.Type.chat); + Message stanza = connection() + .getStanzaFactory() + .buildMessageStanza() + .ofType(Message.Type.chat) + .setBody(message) + .build(); send(stanza); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/address/MultipleRecipientManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/address/MultipleRecipientManager.java index fc361c392..6406cbcd4 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/address/MultipleRecipientManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/address/MultipleRecipientManager.java @@ -159,7 +159,7 @@ public class MultipleRecipientManager { } // Any element from the initial message MUST be copied into the reply. if (original.getThread() != null) { - reply.setThread(original.getThread()); + reply.asBuilder().setThread(original.getThread()).build(); } MultipleAddresses.Address replyAddress = info.getReplyAddress(); if (replyAddress != null && replyAddress.getJid() != null) { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java index 0b98123dc..ea2948f86 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java @@ -34,6 +34,7 @@ import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smack.util.stringencoder.Base64; @@ -835,8 +836,9 @@ public class InBandBytestreamSession implements BytestreamSession { @Override protected synchronized void writeToXML(DataPacketExtension data) throws NotConnectedException, InterruptedException { // create message stanza containing data packet - Message message = new Message(remoteJID); - message.addExtension(data); + Message message = StanzaBuilder.buildMessage().to(remoteJID) + .addExtension(data) + .build(); connection.sendStanza(message); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java index 7b8acc674..f257efa6e 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java @@ -718,7 +718,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream * @throws InterruptedException if the calling thread was interrupted. */ protected void replyRejectPacket(IQ packet) throws NotConnectedException, InterruptedException { - StanzaError.Builder xmppError = StanzaError.getBuilder(StanzaError.Condition.not_acceptable); + StanzaError xmppError = StanzaError.getBuilder(StanzaError.Condition.not_acceptable).build(); IQ errorIQ = IQ.createErrorResponse(packet, xmppError); connection().sendStanza(errorIQ); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamRequest.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamRequest.java index 41669b52e..a5756cdc2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamRequest.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamRequest.java @@ -333,7 +333,7 @@ public class Socks5BytestreamRequest implements BytestreamRequest { errorMessage = couldNotConnectException.getMessage(); } - StanzaError.Builder error = StanzaError.from(StanzaError.Condition.item_not_found, errorMessage); + StanzaError error = StanzaError.from(StanzaError.Condition.item_not_found, errorMessage).build(); IQ errorIQ = IQ.createErrorResponse(this.bytestreamRequest, error); this.manager.getConnection().sendStanza(errorIQ); 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 5691685ff..0c4c9f4ef 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 @@ -43,6 +43,7 @@ import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smackx.chatstates.packet.ChatStateExtension; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; @@ -218,7 +219,7 @@ public final class ChatStateManager extends Manager { if (!updateChatState(chat, newState)) { return; } - Message message = new Message(); + Message message = StanzaBuilder.buildMessage().build(); ChatStateExtension extension = new ChatStateExtension(newState); message.addExtension(extension); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java index ec6724215..588ca2116 100755 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java @@ -329,7 +329,10 @@ public final class AdHocCommandManager extends Manager { } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { - StanzaError.Builder xmppError = StanzaError.getBuilder().setCondition(StanzaError.Condition.internal_server_error).setDescriptiveEnText(e.getMessage()); + StanzaError xmppError = StanzaError.getBuilder() + .setCondition(StanzaError.Condition.internal_server_error) + .setDescriptiveEnText(e.getMessage()) + .build(); return respondError(response, xmppError); } @@ -393,7 +396,7 @@ public final class AdHocCommandManager extends Manager { response.setStatus(Status.canceled); executingCommands.remove(sessionId); } - return respondError(response, StanzaError.getBuilder(error)); + return respondError(response, error); } } else { @@ -503,7 +506,7 @@ public final class AdHocCommandManager extends Manager { response.setStatus(Status.canceled); executingCommands.remove(sessionId); } - return respondError(response, StanzaError.getBuilder(error)); + return respondError(response, error); } } } @@ -559,7 +562,7 @@ public final class AdHocCommandManager extends Manager { */ private static IQ respondError(AdHocCommandData response, StanzaError.Condition condition) { - return respondError(response, StanzaError.getBuilder(condition)); + return respondError(response, StanzaError.getBuilder(condition).build()); } /** @@ -572,7 +575,9 @@ public final class AdHocCommandManager extends Manager { */ private static IQ respondError(AdHocCommandData response, StanzaError.Condition condition, AdHocCommand.SpecificErrorCondition specificCondition) { - StanzaError.Builder error = StanzaError.getBuilder(condition).addExtension(new AdHocCommandData.SpecificError(specificCondition)); + StanzaError error = StanzaError.getBuilder(condition) + .addExtension(new AdHocCommandData.SpecificError(specificCondition)) + .build(); return respondError(response, error); } @@ -583,7 +588,7 @@ public final class AdHocCommandManager extends Manager { * @param error the error to send. * @throws NotConnectedException if the XMPP connection is not connected. */ - private static IQ respondError(AdHocCommandData response, StanzaError.Builder error) { + private static IQ respondError(AdHocCommandData response, StanzaError error) { response.setType(IQ.Type.error); response.setError(error); return response; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/provider/AdHocCommandDataProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/provider/AdHocCommandDataProvider.java index 22d7f7498..4aeb9a700 100755 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/provider/AdHocCommandDataProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/provider/AdHocCommandDataProvider.java @@ -112,7 +112,7 @@ public class AdHocCommandDataProvider extends IQProvider { adHocCommandData.addNote(new AdHocCommandNote(type, value)); } else if (parser.getName().equals("error")) { - StanzaError.Builder error = PacketParserUtils.parseError(parser); + StanzaError error = PacketParserUtils.parseError(parser); adHocCommandData.setError(error); } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java index d59bb2fc7..f6de2aca8 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java @@ -146,7 +146,7 @@ public final class ServiceDiscoveryManager extends Manager { // Return error since client doesn't contain // the specified node response.setType(IQ.Type.error); - response.setError(StanzaError.getBuilder(StanzaError.Condition.item_not_found)); + response.setError(StanzaError.getBuilder(StanzaError.Condition.item_not_found).build()); } return response; } @@ -184,7 +184,7 @@ public final class ServiceDiscoveryManager extends Manager { } else { // Return error since specified node was not found response.setType(IQ.Type.error); - response.setError(StanzaError.getBuilder(StanzaError.Condition.item_not_found)); + response.setError(StanzaError.getBuilder(StanzaError.Condition.item_not_found).build()); } } return response; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferManager.java index f34ed352b..9c2221de0 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferManager.java @@ -172,7 +172,7 @@ public final class FileTransferManager extends Manager { // 'not-acceptable' should be returned. This is done by Smack in // Socks5BytestreamManager.replyRejectPacket(IQ). IQ rejection = IQ.createErrorResponse(initiation, StanzaError.getBuilder( - StanzaError.Condition.forbidden)); + StanzaError.Condition.forbidden).build()); connection().sendStanza(rejection); } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferNegotiator.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferNegotiator.java index c9195fa8c..cb5783206 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferNegotiator.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferNegotiator.java @@ -194,7 +194,7 @@ public final class FileTransferNegotiator extends Manager { if (streamMethodField == null) { String errorMessage = "No stream methods contained in stanza."; - StanzaError.Builder error = StanzaError.from(StanzaError.Condition.bad_request, errorMessage); + StanzaError error = StanzaError.from(StanzaError.Condition.bad_request, errorMessage).build(); IQ iqPacket = IQ.createErrorResponse(si, error); connection().sendStanza(iqPacket); throw new FileTransferException.NoStreamMethodsOfferedException(); @@ -206,7 +206,7 @@ public final class FileTransferNegotiator extends Manager { selectedStreamNegotiator = getNegotiator(streamMethodField); } catch (NoAcceptableTransferMechanisms e) { - IQ iqPacket = IQ.createErrorResponse(si, StanzaError.from(StanzaError.Condition.bad_request, "No acceptable transfer mechanism")); + IQ iqPacket = IQ.createErrorResponse(si, StanzaError.from(StanzaError.Condition.bad_request, "No acceptable transfer mechanism").build()); connection().sendStanza(iqPacket); throw e; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java index b8c0ff414..a12d975d1 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java @@ -80,8 +80,10 @@ public final class GeoLocationManager extends Manager { final XMPPConnection connection = connection(); - Message geoLocationMessage = new Message(jid); - geoLocationMessage.addExtension(geoLocation); + Message geoLocationMessage = connection.getStanzaFactory().buildMessageStanza() + .to(jid) + .addExtension(geoLocation) + .build(); connection.sendStanza(geoLocationMessage); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleUtil.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleUtil.java index 4e5c6eddf..1ac93c448 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleUtil.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleUtil.java @@ -424,9 +424,10 @@ public class JingleUtil { */ public IQ createErrorUnknownSession(Jingle request) { - StanzaError.Builder error = StanzaError.getBuilder(); - error.setCondition(StanzaError.Condition.item_not_found) - .addExtension(JingleError.UNKNOWN_SESSION); + StanzaError error = StanzaError.getBuilder() + .setCondition(StanzaError.Condition.item_not_found) + .addExtension(JingleError.UNKNOWN_SESSION) + .build(); return IQ.createErrorResponse(request, error); } @@ -445,9 +446,10 @@ public class JingleUtil { } public IQ createErrorUnsupportedInfo(Jingle request) { - StanzaError.Builder error = StanzaError.getBuilder(); - error.setCondition(StanzaError.Condition.feature_not_implemented) - .addExtension(JingleError.UNSUPPORTED_INFO); + StanzaError error = StanzaError.getBuilder() + .setCondition(StanzaError.Condition.feature_not_implemented) + .addExtension(JingleError.UNSUPPORTED_INFO) + .build(); return IQ.createErrorResponse(request, error); } @@ -457,9 +459,10 @@ public class JingleUtil { } public IQ createErrorTieBreak(Jingle request) { - StanzaError.Builder error = StanzaError.getBuilder(); - error.setCondition(StanzaError.Condition.conflict) - .addExtension(JingleError.TIE_BREAK); + StanzaError error = StanzaError.getBuilder() + .setCondition(StanzaError.Condition.conflict) + .addExtension(JingleError.TIE_BREAK) + .build(); return IQ.createErrorResponse(request, error); } @@ -469,9 +472,10 @@ public class JingleUtil { } public IQ createErrorOutOfOrder(Jingle request) { - StanzaError.Builder error = StanzaError.getBuilder(); - error.setCondition(StanzaError.Condition.unexpected_request) - .addExtension(JingleError.OUT_OF_ORDER); + StanzaError error = StanzaError.getBuilder() + .setCondition(StanzaError.Condition.unexpected_request) + .addExtension(JingleError.OUT_OF_ORDER) + .build(); return IQ.createErrorResponse(request, error); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/JivePropertiesManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/JivePropertiesManager.java index 8bbe7812d..b58970f23 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/JivePropertiesManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/JivePropertiesManager.java @@ -21,6 +21,8 @@ import java.util.Collections; import java.util.Map; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; +import org.jivesoftware.smack.packet.StanzaView; import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension; @@ -54,7 +56,10 @@ public class JivePropertiesManager { * @param packet the stanza to add the property to. * @param name the name of the property to add. * @param value the value of the property to add. + * @deprecated use {@link #addProperty(StanzaBuilder, String, Object)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public static void addProperty(Stanza packet, String name, Object value) { JivePropertiesExtension jpe = (JivePropertiesExtension) packet.getExtension(JivePropertiesExtension.NAMESPACE); if (jpe == null) { @@ -64,6 +69,22 @@ public class JivePropertiesManager { jpe.setProperty(name, value); } + /** + * Convenience method to add a property to a stanza. + * + * @param stanzaBuilder the stanza to add the property to. + * @param name the name of the property to add. + * @param value the value of the property to add. + */ + public static void addProperty(StanzaBuilder stanzaBuilder, String name, Object value) { + JivePropertiesExtension jpe = (JivePropertiesExtension) stanzaBuilder.getExtension(JivePropertiesExtension.QNAME); + if (jpe == null) { + jpe = new JivePropertiesExtension(); + stanzaBuilder.addExtension(jpe); + } + jpe.setProperty(name, value); + } + /** * Convenience method to get a property from a packet. Will return null if the stanza contains * not property with the given name. @@ -72,9 +93,9 @@ public class JivePropertiesManager { * @param name TODO javadoc me please * @return the property or null if none found. */ - public static Object getProperty(Stanza packet, String name) { + public static Object getProperty(StanzaView packet, String name) { Object res = null; - JivePropertiesExtension jpe = (JivePropertiesExtension) packet.getExtension(JivePropertiesExtension.NAMESPACE); + JivePropertiesExtension jpe = (JivePropertiesExtension) packet.getExtension(JivePropertiesExtension.QNAME); if (jpe != null) { res = jpe.getProperty(name); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/packet/JivePropertiesExtension.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/packet/JivePropertiesExtension.java index 5a9061c4f..5ca0a7087 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/packet/JivePropertiesExtension.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/packet/JivePropertiesExtension.java @@ -27,6 +27,8 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.util.XmlStringBuilder; @@ -47,6 +49,8 @@ public class JivePropertiesExtension implements ExtensionElement { public static final String ELEMENT = "properties"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); + private static final Logger LOGGER = Logger.getLogger(JivePropertiesExtension.class.getName()); private final Map properties; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucEnterConfiguration.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucEnterConfiguration.java index 681d1e8a9..51b79fb57 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucEnterConfiguration.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucEnterConfiguration.java @@ -18,7 +18,10 @@ package org.jivesoftware.smackx.muc; import java.util.Date; +import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.PresenceBuilder; +import org.jivesoftware.smack.util.Consumer; import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smackx.muc.packet.MUCInitialPresence; @@ -58,7 +61,7 @@ public final class MucEnterConfiguration { timeout = builder.timeout; if (builder.joinPresence == null) { - joinPresence = new Presence(Presence.Type.available); + joinPresence = builder.joinPresenceBuilder.ofType(Presence.Type.available).build(); } else { joinPresence = builder.joinPresence.clone(); @@ -87,11 +90,17 @@ public final class MucEnterConfiguration { private int seconds = -1; private Date since; private long timeout; + + private final PresenceBuilder joinPresenceBuilder; private Presence joinPresence; - Builder(Resourcepart nickname, long timeout) { + Builder(Resourcepart nickname, XMPPConnection connection) { this.nickname = Objects.requireNonNull(nickname, "Nickname must not be null"); + + timeout = connection.getReplyTimeout(); timeoutAfter(timeout); + + joinPresenceBuilder = connection.getStanzaFactory().buildPresenceStanza(); } /** @@ -103,7 +112,10 @@ public final class MucEnterConfiguration { * * @param presence TODO javadoc me please * @return a reference to this builder. + * @deprecated use {@link #withPresence(Consumer)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public Builder withPresence(Presence presence) { if (presence.getType() != Presence.Type.available) { throw new IllegalArgumentException("Presence must be of type 'available'"); @@ -113,6 +125,26 @@ public final class MucEnterConfiguration { return this; } + /** + * Set the presence used to join the MUC room. + *

+ * The consumer must not modify the presence type, otherwise an {@link IllegalArgumentException} will be thrown. + *

+ * + * @param presenceBuilderConsumer a consumer which will be passed the presence build. + * @return a reference to this builder. + * @since 4.5 + */ + public Builder withPresence(Consumer presenceBuilderConsumer) { + presenceBuilderConsumer.accept(joinPresenceBuilder); + + if (joinPresenceBuilder.getType() != Presence.Type.available) { + throw new IllegalArgumentException("Presence must be of type 'available'"); + } + + return this; + } + /** * Use the given password to join the MUC room. * 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 605eaff2e..b37f367ad 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 @@ -56,6 +56,7 @@ import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.filter.ToMatchesFilter; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.util.Objects; @@ -419,7 +420,7 @@ public class MultiUserChat { * @since 4.2 */ public MucEnterConfiguration.Builder getEnterConfigurationBuilder(Resourcepart nickname) { - return new MucEnterConfiguration.Builder(nickname, connection.getReplyTimeout()); + return new MucEnterConfiguration.Builder(nickname, connection); } /** @@ -744,8 +745,10 @@ public class MultiUserChat { // We leave a room by sending a presence packet where the "to" // field is in the form "roomName@service/nickname" - Presence leavePresence = new Presence(Presence.Type.unavailable); - leavePresence.setTo(myRoomJid); + Presence leavePresence = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.unavailable) + .to(myRoomJid) + .build(); StanzaFilter reflectedLeavePresenceFilter = new AndFilter( StanzaTypeFilter.PRESENCE, @@ -927,7 +930,7 @@ public class MultiUserChat { * @throws InterruptedException if the calling thread was interrupted. */ public void invite(EntityBareJid user, String reason) throws NotConnectedException, InterruptedException { - invite(new Message(), user, reason); + invite(connection.getStanzaFactory().buildMessageStanza(), user, reason); } /** @@ -942,7 +945,10 @@ public class MultiUserChat { * @param reason the reason why the user is being invited. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. + * @deprecated use {@link #invite(MessageBuilder, EntityBareJid, String)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void invite(Message message, EntityBareJid user, String reason) throws NotConnectedException, InterruptedException { // TODO listen for 404 error code when inviter supplies a non-existent JID message.setTo(room); @@ -957,6 +963,34 @@ public class MultiUserChat { connection.sendStanza(message); } + /** + * Invites another user to the room in which one is an occupant using a given Message. The invitation + * will be sent to the room which in turn will forward the invitation to the invitee.

+ * + * If the room is password-protected, the invitee will receive a password to use to join + * the room. If the room is members-only, the the invitee may be added to the member list. + * + * @param messageBuilder the message to use for sending the invitation. + * @param user the user to invite to the room.(e.g. hecate@shakespeare.lit) + * @param reason the reason why the user is being invited. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + */ + public void invite(MessageBuilder messageBuilder, EntityBareJid user, String reason) throws NotConnectedException, InterruptedException { + // TODO listen for 404 error code when inviter supplies a non-existent JID + messageBuilder.to(room); + + // Create the MUCUser packet that will include the invitation + MUCUser mucUser = new MUCUser(); + MUCUser.Invite invite = new MUCUser.Invite(reason, user); + mucUser.setInvite(invite); + // Add the MUCUser packet that includes the invitation to the message + messageBuilder.addExtension(mucUser); + + Message message = messageBuilder.build(); + connection.sendStanza(message); + } + /** * Adds a listener to invitation rejections notifications. The listener will be fired anytime * an invitation is declined. @@ -1126,8 +1160,10 @@ public class MultiUserChat { // We change the nickname by sending a presence packet where the "to" // field is in the form "roomName@service/nickname" // We don't have to signal the MUC support again - Presence joinPresence = new Presence(Presence.Type.available); - joinPresence.setTo(jid); + Presence joinPresence = connection.getStanzaFactory().buildPresenceStanza() + .to(jid) + .ofType(Presence.Type.available) + .build(); // Wait for a presence packet back from the server. StanzaFilter responseFilter = @@ -1167,10 +1203,12 @@ public class MultiUserChat { } // We change the availability status by sending a presence packet to the room with the // new presence status and mode - Presence joinPresence = new Presence(Presence.Type.available); - joinPresence.setStatus(status); - joinPresence.setMode(mode); - joinPresence.setTo(myRoomJid); + Presence joinPresence = connection.getStanzaFactory().buildPresenceStanza() + .to(myRoomJid) + .ofType(Presence.Type.available) + .setStatus(status) + .setMode(mode) + .build(); // Send join packet. connection.sendStanza(joinPresence); @@ -1220,8 +1258,11 @@ public class MultiUserChat { requestVoiceField.setLabel("Requested role"); requestVoiceField.addValue("participant"); form.addField(requestVoiceField.build()); - Message message = new Message(room); - message.addExtension(form); + + Message message = connection.getStanzaFactory().buildMessageStanza() + .to(room) + .addExtension(form) + .build(); connection.sendStanza(message); } @@ -1887,8 +1928,9 @@ public class MultiUserChat { * @throws InterruptedException if the calling thread was interrupted. */ public void sendMessage(String text) throws NotConnectedException, InterruptedException { - Message message = createMessage(); - message.setBody(text); + Message message = buildMessage() + .setBody(text) + .build(); connection.sendStanza(message); } @@ -1914,9 +1956,28 @@ public class MultiUserChat { * Creates a new Message to send to the chat room. * * @return a new Message addressed to the chat room. + * @deprecated use {@link #buildMessage()} instead. */ + @Deprecated + // TODO: Remove when stanza builder is ready. public Message createMessage() { - return new Message(room, Message.Type.groupchat); + return connection.getStanzaFactory().buildMessageStanza() + .ofType(Message.Type.groupchat) + .to(room) + .build(); + } + + /** + * Constructs a new message builder for messages send to this MUC room. + * + * @return a new message builder. + */ + public MessageBuilder buildMessage() { + return connection.getStanzaFactory() + .buildMessageStanza() + .ofType(Message.Type.groupchat) + .to(room) + ; } /** @@ -1925,10 +1986,23 @@ public class MultiUserChat { * @param message the message. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. + * @deprecated use {@link #sendMessage(MessageBuilder)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void sendMessage(Message message) throws NotConnectedException, InterruptedException { - message.setTo(room); - message.setType(Message.Type.groupchat); + sendMessage(message.asBuilder()); + } + + /** + * Sends a Message to the chat room. + * + * @param messageBuilder the message. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + */ + public void sendMessage(MessageBuilder messageBuilder) throws NotConnectedException, InterruptedException { + Message message = messageBuilder.to(room).ofType(Message.Type.groupchat).build(); connection.sendStanza(message); } @@ -2024,7 +2098,7 @@ public class MultiUserChat { * @throws InterruptedException if the calling thread was interrupted. */ public void changeSubject(final String subject) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - Message message = createMessage(); + MessageBuilder message = buildMessage(); message.setSubject(subject); // Wait for an error or confirmation message back from the server. StanzaFilter responseFilter = new AndFilter(fromRoomGroupchatFilter, new StanzaFilter() { @@ -2034,7 +2108,7 @@ public class MultiUserChat { return subject.equals(msg.getSubject()); } }); - StanzaCollector response = connection.createStanzaCollectorAndSend(responseFilter, message); + StanzaCollector response = connection.createStanzaCollectorAndSend(responseFilter, message.build()); // Wait up to a certain number of seconds for a reply. response.nextResultOrThrow(); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java index d2cb2e122..1a29ebe91 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java @@ -44,6 +44,7 @@ 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.util.Async; import org.jivesoftware.smack.util.CleaningWeakReferenceMap; @@ -438,16 +439,18 @@ public final class MultiUserChatManager extends Manager { * @throws InterruptedException if the calling thread was interrupted. */ public void decline(EntityBareJid room, EntityBareJid inviter, String reason) throws NotConnectedException, InterruptedException { - Message message = new Message(room); + XMPPConnection connection = connection(); + + MessageBuilder messageBuilder = connection.getStanzaFactory().buildMessageStanza().to(room); // Create the MUCUser packet that will include the rejection MUCUser mucUser = new MUCUser(); MUCUser.Decline decline = new MUCUser.Decline(reason, inviter); mucUser.setDecline(decline); // Add the MUCUser packet that includes the rejection - message.addExtension(mucUser); + messageBuilder.addExtension(mucUser); - connection().sendStanza(message); + connection.sendStanza(messageBuilder.build()); } /** diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/ping/PingManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/ping/PingManager.java index 0bb1b0e65..f30e58a9e 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/ping/PingManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/ping/PingManager.java @@ -193,8 +193,9 @@ public final class PingManager extends Manager { } }; - Ping ping = new Ping(jid); - connection().sendIqRequestAsync(ping, pongTimeout) + XMPPConnection connection = connection(); + Ping ping = new Ping(connection, jid); + connection.sendIqRequestAsync(ping, pongTimeout) .onSuccess(new SuccessCallback() { @Override public void onSuccess(IQ result) { @@ -233,7 +234,7 @@ public final class PingManager extends Manager { if (!connection.isAuthenticated()) { throw new NotConnectedException(); } - Ping ping = new Ping(jid); + Ping ping = new Ping(connection, jid); try { connection.createStanzaCollectorAndSend(ping).nextResultOrThrow(pingTimeout); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/ping/packet/Ping.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/ping/packet/Ping.java index 65d7186fa..13803354c 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/ping/packet/Ping.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/ping/packet/Ping.java @@ -1,6 +1,6 @@ /** * - * Copyright 2012-2015 Florian Schmaus + * Copyright 2012-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,7 +16,9 @@ */ package org.jivesoftware.smackx.ping.packet; +import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqBuilder; import org.jivesoftware.smack.packet.SimpleIQ; import org.jxmpp.jid.Jid; @@ -36,6 +38,18 @@ public class Ping extends SimpleIQ { setType(IQ.Type.get); } + public Ping(XMPPConnection connection, Jid to) { + this(connection.getStanzaFactory().buildIqStanza(), to); + } + + public Ping(IqBuilder iqBuilder, Jid to) { + super(iqBuilder.to(to).ofType(IQ.Type.get), ELEMENT, NAMESPACE); + } + + public Ping(IqBuilder iqBuilder) { + super(iqBuilder, ELEMENT, NAMESPACE); + } + /** * Create an XMPP Pong for this Ping. * 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 0fc5d1cdd..bab23aa5e 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 @@ -39,6 +39,7 @@ import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.util.StringUtils; @@ -342,8 +343,11 @@ public final class DeliveryReceiptManager extends Manager { if (StringUtils.isNullOrEmpty(stanzaId)) { return null; } - Message message = new Message(messageWithReceiptRequest.getFrom(), messageWithReceiptRequest.getType()); - message.addExtension(new DeliveryReceipt(stanzaId)); + Message message = StanzaBuilder.buildMessage() + .ofType(messageWithReceiptRequest.getType()) + .to(messageWithReceiptRequest.getFrom()) + .addExtension(new DeliveryReceipt(stanzaId)) + .build(); return message; } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/receipts/DeliveryReceiptRequest.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/receipts/DeliveryReceiptRequest.java index 23a129e24..7473d7a5f 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/receipts/DeliveryReceiptRequest.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/receipts/DeliveryReceiptRequest.java @@ -20,6 +20,7 @@ import java.io.IOException; 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.XmlEnvironment; import org.jivesoftware.smack.provider.ExtensionElementProvider; @@ -81,12 +82,28 @@ public class DeliveryReceiptRequest implements ExtensionElement { * @param message Message object to add a request to * @return the Message ID which will be used as receipt ID */ + // TODO: Deprecate in favor of addTo(MessageBuilder) once connection's stanza interceptors use StanzaBuilder. public static String addTo(Message message) { - message.ensureStanzaIdSet(); + message.throwIfNoStanzaId(); + message.addExtension(new DeliveryReceiptRequest()); return message.getStanzaId(); } + /** + * Add a delivery receipt request to an outgoing packet. + * + * Only message packets may contain receipt requests as of XEP-0184, + * therefore only allow Message as the parameter type. + * + * @param messageBuilder Message object to add a request to + */ + public static void addTo(MessageBuilder messageBuilder) { + messageBuilder.throwIfNoStanzaId(); + + messageBuilder.overrideExtension(new DeliveryReceiptRequest()); + } + /** * This Provider parses and returns DeliveryReceiptRequest packets. */ diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/VCardManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/VCardManager.java index 45c16f506..87346d513 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/VCardManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/VCardManager.java @@ -98,13 +98,15 @@ public final class VCardManager extends Manager { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ + // TODO: Split VCard into VCardIq and VCardData, then create saveVCard(VCardData) and deprecate this method. + @SuppressWarnings("deprecation") public void saveVCard(VCard vcard) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { // XEP-54 § 3.2 "A user may publish or update his or her vCard by sending an IQ of type "set" with no 'to' address…" vcard.setTo((Jid) null); vcard.setType(IQ.Type.set); // Also make sure to generate a new stanza id (the given vcard could be a vcard result), in which case we don't // want to use the same stanza id again (although it wouldn't break if we did) - vcard.setNewStanzaId(); + vcard.setStanzaId(); connection().createStanzaCollectorAndSend(vcard).nextResultOrThrow(); } diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/ibb/IBBPacketUtils.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/ibb/IBBPacketUtils.java index 28404544b..9aa69919c 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/ibb/IBBPacketUtils.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/ibb/IBBPacketUtils.java @@ -39,7 +39,7 @@ public class IBBPacketUtils { * @return an error IQ */ public static IQ createErrorIQ(Jid from, Jid to, StanzaError.Condition condition) { - StanzaError.Builder xmppError = StanzaError.getBuilder(condition); + StanzaError xmppError = StanzaError.getBuilder(condition).build(); IQ errorIQ = new ErrorIQ(xmppError); errorIQ.setType(IQ.Type.error); errorIQ.setFrom(from); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionMessageTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionMessageTest.java index eb172880a..443cb24de 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionMessageTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionMessageTest.java @@ -31,6 +31,7 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.util.stringencoder.Base64; import org.jivesoftware.smackx.InitExtensions; @@ -266,8 +267,9 @@ public class InBandBytestreamSessionMessageTest extends InitExtensions { // build invalid packet with out of order sequence String base64Data = Base64.encode("Data"); DataPacketExtension dpe = new DataPacketExtension(sessionID, 123, base64Data); - Message dataMessage = new Message(); - dataMessage.addExtension(dpe); + Message dataMessage = StanzaBuilder.buildMessage() + .addExtension(dpe) + .build(); // add data packets listener.processStanza(dataMessage); @@ -307,8 +309,9 @@ public class InBandBytestreamSessionMessageTest extends InitExtensions { for (int i = 0; i < controlData.length / blockSize; i++) { String base64Data = Base64.encodeToString(controlData, i * blockSize, blockSize); DataPacketExtension dpe = new DataPacketExtension(sessionID, i, base64Data); - Message dataMessage = new Message(); - dataMessage.addExtension(dpe); + Message dataMessage = StanzaBuilder.buildMessage() + .addExtension(dpe) + .build(); listener.processStanza(dataMessage); } @@ -352,8 +355,9 @@ public class InBandBytestreamSessionMessageTest extends InitExtensions { for (int i = 0; i < controlData.length / blockSize; i++) { String base64Data = Base64.encodeToString(controlData, i * blockSize, blockSize); DataPacketExtension dpe = new DataPacketExtension(sessionID, i, base64Data); - Message dataMessage = new Message(); - dataMessage.addExtension(dpe); + Message dataMessage = StanzaBuilder.buildMessage() + .addExtension(dpe) + .build(); listener.processStanza(dataMessage); } diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java index a84a90996..39869435e 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java @@ -413,8 +413,8 @@ public class Socks5ByteStreamManagerTest { Verification.requestTypeGET); // build error packet to reject SOCKS5 Bytestream - StanzaError.Builder builder = StanzaError.getBuilder(StanzaError.Condition.not_acceptable); - IQ rejectPacket = new ErrorIQ(builder); + StanzaError stanzaError = StanzaError.getBuilder(StanzaError.Condition.not_acceptable).build(); + IQ rejectPacket = new ErrorIQ(stanzaError); rejectPacket.setFrom(targetJID); rejectPacket.setTo(initiatorJID); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiatorTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiatorTest.java index fe3807eed..c824bb102 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiatorTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiatorTest.java @@ -184,7 +184,7 @@ public class Socks5ClientForInitiatorTest { XMPPConnection connection = ConnectionUtils.createMockedConnection(protocol, initiatorJID); // build error response as reply to the stream activation - IQ error = new ErrorIQ(StanzaError.getBuilder(StanzaError.Condition.internal_server_error)); + IQ error = new ErrorIQ(StanzaError.getBuilder(StanzaError.Condition.internal_server_error).build()); error.setFrom(proxyJID); error.setTo(initiatorJID); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/last_interaction/IdleTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/last_interaction/IdleTest.java index 74247bba1..407f48b20 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/last_interaction/IdleTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/last_interaction/IdleTest.java @@ -23,6 +23,7 @@ import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar; import java.util.Date; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smack.xml.XmlPullParser; @@ -50,7 +51,9 @@ public class IdleTest extends SmackTestSuite { @Test public void helperTest() { - Presence presence = new Presence(Presence.Type.available); + Presence presence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.available) + .build(); IdleElement.addToPresence(presence); IdleElement element = IdleElement.fromPresence(presence); assertNotNull(element); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/mood/MoodManagerTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/mood/MoodManagerTest.java index a650bc7b5..dfc4cf8f4 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/mood/MoodManagerTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/mood/MoodManagerTest.java @@ -22,6 +22,7 @@ import static junit.framework.TestCase.assertNotNull; import static junit.framework.TestCase.assertTrue; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smackx.mood.element.MoodElement; @@ -32,7 +33,7 @@ public class MoodManagerTest extends SmackTestSuite { @Test public void addMessageTest() { - Message message = new Message(); + Message message = StanzaBuilder.buildMessage().build(); MoodManager.addMoodToMessage(message, Mood.sad); assertTrue(message.hasExtension(MoodElement.ELEMENT, MoodElement.NAMESPACE)); @@ -43,7 +44,7 @@ public class MoodManagerTest extends SmackTestSuite { assertFalse(element.hasConcretisation()); assertFalse(element.hasText()); - message = new Message(); + message = StanzaBuilder.buildMessage().build(); MoodManager.addMoodToMessage(message, Mood.happy, new MoodConcretisationTest.EcstaticMoodConcretisation()); element = MoodElement.fromMessage(message); assertTrue(element.hasConcretisation()); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/pubsub/ConfigureFormTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/pubsub/ConfigureFormTest.java index 96034f920..a46a28bc4 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/pubsub/ConfigureFormTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/pubsub/ConfigureFormTest.java @@ -67,7 +67,7 @@ public class ConfigureFormTest extends InitExtensions { PubSub errorIq = new PubSub(); errorIq.setType(Type.error); errorIq.setFrom(PubSubManagerTest.DUMMY_PUBSUB_SERVICE); - StanzaError.Builder error = StanzaError.getBuilder(Condition.forbidden); + StanzaError error = StanzaError.getBuilder(Condition.forbidden).build(); errorIq.setError(error); con.addIQReply(errorIq); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/receipts/DeliveryReceiptTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/receipts/DeliveryReceiptTest.java index 645b54271..01d1a60e8 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/receipts/DeliveryReceiptTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/receipts/DeliveryReceiptTest.java @@ -27,7 +27,9 @@ import java.util.Properties; import org.jivesoftware.smack.DummyConnection; 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.test.util.WaitForPacketListener; import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.xml.XmlPullParser; @@ -38,7 +40,6 @@ import org.jivesoftware.smackx.receipts.DeliveryReceiptManager.AutoReceiptMode; import com.jamesmurty.utils.XMLBuilder; import org.junit.Test; import org.jxmpp.jid.Jid; -import org.jxmpp.jid.impl.JidCreate; public class DeliveryReceiptTest extends InitExtensions { @@ -66,10 +67,13 @@ public class DeliveryReceiptTest extends InitExtensions { assertTrue(DeliveryReceiptManager.hasDeliveryReceiptRequest(p)); - Message m = new Message(JidCreate.from("romeo@montague.com"), Message.Type.normal); - assertFalse(DeliveryReceiptManager.hasDeliveryReceiptRequest(m)); - DeliveryReceiptRequest.addTo(m); - assertTrue(DeliveryReceiptManager.hasDeliveryReceiptRequest(m)); + MessageBuilder messageBuilder = StanzaBuilder.buildMessage("request-id") + .to("romeo@montague.com") + .ofType(Message.Type.normal) + ; + assertFalse(DeliveryReceiptManager.hasDeliveryReceiptRequest(messageBuilder.build())); + DeliveryReceiptRequest.addTo(messageBuilder); + assertTrue(DeliveryReceiptManager.hasDeliveryReceiptRequest(messageBuilder.build())); } @Test @@ -81,10 +85,12 @@ public class DeliveryReceiptTest extends InitExtensions { TestReceiptReceivedListener rrl = new TestReceiptReceivedListener(); drm.addReceiptReceivedListener(rrl); - Message m = new Message(JidCreate.from("romeo@montague.com"), Message.Type.normal); - m.setFrom(JidCreate.from("julia@capulet.com")); - m.setStanzaId("reply-id"); - m.addExtension(new DeliveryReceipt("original-test-id")); + Message m = StanzaBuilder.buildMessage("reply-id") + .from("julia@capulet.com") + .to("romeo@montague.com") + .ofType(Message.Type.normal) + .addExtension(new DeliveryReceipt("original-test-id")) + .build(); c.processStanza(m); rrl.waitUntilInvocationOrTimeout(); @@ -110,13 +116,15 @@ public class DeliveryReceiptTest extends InitExtensions { assertEquals(AutoReceiptMode.always, drm.getAutoReceiptMode()); // test auto-receipts - Message m = new Message(JidCreate.from("julia@capulet.com"), Message.Type.normal); - m.setFrom(JidCreate.from("romeo@montague.com")); - m.setStanzaId("test-receipt-request"); - DeliveryReceiptRequest.addTo(m); + MessageBuilder messageBuilder = StanzaBuilder.buildMessage("test-receipt-request") + .to("julia@capulet.com") + .from("romeo@montague.com") + .ofType(Message.Type.normal) + ; + DeliveryReceiptRequest.addTo(messageBuilder); // the DRM will send a reply-packet - c.processStanza(m); + c.processStanza(messageBuilder.build()); Stanza reply = c.getSentPacket(); DeliveryReceipt r = DeliveryReceipt.from((Message) reply); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/usertune/UserTuneManagerTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/usertune/UserTuneManagerTest.java index bb21fae84..9e357963c 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/usertune/UserTuneManagerTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/usertune/UserTuneManagerTest.java @@ -24,6 +24,7 @@ import java.net.URI; import java.net.URISyntaxException; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smackx.usertune.element.UserTuneElement; @@ -45,8 +46,9 @@ public class UserTuneManagerTest extends SmackTestSuite{ builder.setUri(uri); UserTuneElement userTuneElement = builder.build(); - Message message = new Message(); - message.addExtension(userTuneElement); + Message message = StanzaBuilder.buildMessage() + .addExtension(userTuneElement) + .build(); assertTrue(message.hasExtension(UserTuneElement.ELEMENT, UserTuneElement.NAMESPACE)); assertTrue(UserTuneElement.hasUserTuneElement(message)); diff --git a/smack-im/src/main/java/org/jivesoftware/smack/chat/Chat.java b/smack-im/src/main/java/org/jivesoftware/smack/chat/Chat.java index f5df0834f..c57bc5e34 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/chat/Chat.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/chat/Chat.java @@ -24,6 +24,8 @@ import java.util.concurrent.CopyOnWriteArraySet; import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.StanzaCollector; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.util.StringUtils; import org.jxmpp.jid.EntityJid; @@ -98,11 +100,28 @@ public class Chat { * @throws InterruptedException if the calling thread was interrupted. */ public void sendMessage(String text) throws NotConnectedException, InterruptedException { - Message message = new Message(); - message.setBody(text); + MessageBuilder message = StanzaBuilder.buildMessage() + .setBody(text); sendMessage(message); } + /** + * Sends a message to the other chat participant. The thread ID, recipient, + * and message type of the message will automatically set to those of this chat. + * + * @param message the message to send. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + */ + public void sendMessage(MessageBuilder message) throws NotConnectedException, InterruptedException { + // Force the recipient, message type, and thread ID since the user elected + // to send the message through this chat object. + message.to(participant); + message.ofType(Message.Type.chat); + message.setThread(threadID); + chatManager.sendMessage(this, message.build()); + } + /** * Sends a message to the other chat participant. The thread ID, recipient, * and message type of the message will automatically set to those of this chat. diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java index e1d49d8ed..5bb91f283 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java @@ -56,7 +56,9 @@ import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ.Type; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.PresenceBuilder; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.packet.StanzaError.Condition; import org.jivesoftware.smack.roster.SubscribeListener.SubscribeAnswer; import org.jivesoftware.smack.roster.packet.RosterPacket; @@ -286,23 +288,26 @@ public final class Roster extends Manager { return; } - Presence response; + Presence.Type type; switch (subscribeAnswer) { case ApproveAndAlsoRequestIfRequired: BareJid bareFrom = from.asBareJid(); RosterUtil.askForSubscriptionIfRequired(Roster.this, bareFrom); // The fall through is intended. case Approve: - response = new Presence(Presence.Type.subscribed); + type = Presence.Type.subscribed; break; case Deny: - response = new Presence(Presence.Type.unsubscribed); + type = Presence.Type.unsubscribed; break; default: throw new AssertionError(); } - response.setTo(presence.getFrom()); + Presence response = connection.getStanzaFactory().buildPresenceStanza() + .ofType(type) + .to(presence.getFrom()) + .build(); connection.sendStanza(response); } }, PresenceTypeFilter.SUBSCRIBE); @@ -747,8 +752,10 @@ public final class Roster extends Manager { throw new FeatureNotSupportedException("Pre-approving"); } - Presence presencePacket = new Presence(Presence.Type.subscribed); - presencePacket.setTo(user); + Presence presencePacket = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.subscribed) + .to(user) + .build(); connection.sendStanza(presencePacket); } @@ -768,8 +775,10 @@ public final class Roster extends Manager { final XMPPConnection connection = getAuthenticatedConnectionOrThrow(); // Create a presence subscription packet and send. - Presence presencePacket = new Presence(Presence.Type.subscribe); - presencePacket.setTo(jid); + Presence presencePacket = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.subscribe) + .to(jid) + .build(); connection.sendStanza(presencePacket); } @@ -1000,8 +1009,7 @@ public final class Roster extends Manager { public Presence getPresence(BareJid jid) { Map userPresences = getPresencesInternal(jid); if (userPresences == null) { - Presence presence = new Presence(Presence.Type.unavailable); - presence.setFrom(jid); + Presence presence = synthesizeUnvailablePresence(jid); return presence; } else { @@ -1042,8 +1050,7 @@ public final class Roster extends Manager { return unavailable.clone(); } else { - presence = new Presence(Presence.Type.unavailable); - presence.setFrom(jid); + presence = synthesizeUnvailablePresence(jid); return presence; } } @@ -1067,15 +1074,13 @@ public final class Roster extends Manager { Resourcepart resource = userWithResource.getResourcepart(); Map userPresences = getPresencesInternal(key); if (userPresences == null) { - Presence presence = new Presence(Presence.Type.unavailable); - presence.setFrom(userWithResource); + Presence presence = synthesizeUnvailablePresence(userWithResource); return presence; } else { Presence presence = userPresences.get(resource); if (presence == null) { - presence = new Presence(Presence.Type.unavailable); - presence.setFrom(userWithResource); + presence = synthesizeUnvailablePresence(userWithResource); return presence; } else { @@ -1097,8 +1102,7 @@ public final class Roster extends Manager { List res; if (userPresences == null) { // Create an unavailable presence if none was found - Presence unavailable = new Presence(Presence.Type.unavailable); - unavailable.setFrom(bareJid); + Presence unavailable = synthesizeUnvailablePresence(bareJid); res = new ArrayList<>(Arrays.asList(unavailable)); } else { res = new ArrayList<>(userPresences.values().size()); @@ -1143,8 +1147,7 @@ public final class Roster extends Manager { List res; Map userPresences = getPresencesInternal(jid); if (userPresences == null) { - Presence presence = new Presence(Presence.Type.unavailable); - presence.setFrom(jid); + Presence presence = synthesizeUnvailablePresence(jid); res = Arrays.asList(presence); } else { @@ -1166,8 +1169,7 @@ public final class Roster extends Manager { res = Arrays.asList(unavailable.clone()); } else { - Presence presence = new Presence(Presence.Type.unavailable); - presence.setFrom(jid); + Presence presence = synthesizeUnvailablePresence(jid); res = Arrays.asList(presence); } } @@ -1266,20 +1268,20 @@ public final class Roster extends Manager { * presence sent from the server. */ private void setOfflinePresences() { - Presence packetUnavailable; outerloop: for (Jid user : presenceMap.keySet()) { Map resources = presenceMap.get(user); if (resources != null) { for (Resourcepart resource : resources.keySet()) { - packetUnavailable = new Presence(Presence.Type.unavailable); + PresenceBuilder presenceBuilder = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable); EntityBareJid bareUserJid = user.asEntityBareJidIfPossible(); if (bareUserJid == null) { LOGGER.warning("Can not transform user JID to bare JID: '" + user + "'"); continue; } - packetUnavailable.setFrom(JidCreate.fullFrom(bareUserJid, resource)); + presenceBuilder.from(JidCreate.fullFrom(bareUserJid, resource)); try { - presencePacketListener.processStanza(packetUnavailable); + presencePacketListener.processStanza(presenceBuilder.build()); } catch (NotConnectedException e) { throw new IllegalStateException( @@ -1471,6 +1473,13 @@ public final class Roster extends Manager { } } + private static Presence synthesizeUnvailablePresence(Jid from) { + return StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .from(from) + .build(); + } + /** * Check if the server supports roster versioning. * diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterEntry.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterEntry.java index 60b50cce9..fbb0c1188 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterEntry.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterEntry.java @@ -218,8 +218,12 @@ public final class RosterEntry extends Manager { * @since 4.2 */ public void cancelSubscription() throws NotConnectedException, InterruptedException { - Presence unsubscribed = new Presence(item.getJid(), Type.unsubscribed); - connection().sendStanza(unsubscribed); + XMPPConnection connection = connection(); + Presence unsubscribed = connection.getStanzaFactory().buildPresenceStanza() + .to(item.getJid()) + .ofType(Type.unsubscribed) + .build(); + connection.sendStanza(unsubscribed); } @Override diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/provider/RosterVerStreamFeatureProvider.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/provider/RosterVerStreamFeatureProvider.java index 0f71fafea..e2c9acb02 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/provider/RosterVerStreamFeatureProvider.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/provider/RosterVerStreamFeatureProvider.java @@ -19,7 +19,6 @@ package org.jivesoftware.smack.roster.provider; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.provider.ExtensionElementProvider; import org.jivesoftware.smack.roster.packet.RosterVer; - import org.jivesoftware.smack.xml.XmlPullParser; public class RosterVerStreamFeatureProvider extends ExtensionElementProvider { diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/provider/SubscriptionPreApprovalStreamFeatureProvider.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/provider/SubscriptionPreApprovalStreamFeatureProvider.java index 422ced505..40bd2ec39 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/provider/SubscriptionPreApprovalStreamFeatureProvider.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/provider/SubscriptionPreApprovalStreamFeatureProvider.java @@ -19,7 +19,6 @@ package org.jivesoftware.smack.roster.provider; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.provider.ExtensionElementProvider; import org.jivesoftware.smack.roster.packet.SubscriptionPreApproval; - import org.jivesoftware.smack.xml.XmlPullParser; public class SubscriptionPreApprovalStreamFeatureProvider extends ExtensionElementProvider { diff --git a/smack-im/src/test/java/org/jivesoftware/smack/chat/ChatConnectionTest.java b/smack-im/src/test/java/org/jivesoftware/smack/chat/ChatConnectionTest.java index c2f7bf049..a30c2e066 100644 --- a/smack-im/src/test/java/org/jivesoftware/smack/chat/ChatConnectionTest.java +++ b/smack-im/src/test/java/org/jivesoftware/smack/chat/ChatConnectionTest.java @@ -25,7 +25,9 @@ import static org.junit.Assert.assertTrue; import org.jivesoftware.smack.DummyConnection; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message.Type; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.test.util.WaitForPacketListener; import org.junit.After; @@ -89,49 +91,49 @@ public class ChatConnectionTest { @Test public void validateMessageTypeWithDefaults1() { - Message incomingChat = createChatPacket("134", true); - incomingChat.setType(Type.chat); - processServerMessage(incomingChat); + MessageBuilder incomingChat = createChatPacket("134", true); + incomingChat.ofType(Type.chat); + processServerMessage(incomingChat.build()); assertNotNull(listener.getNewChat()); } @Test public void validateMessageTypeWithDefaults2() { - Message incomingChat = createChatPacket("134", true); - incomingChat.setType(Type.normal); - processServerMessage(incomingChat); + MessageBuilder incomingChat = createChatPacket("134", true); + incomingChat.ofType(Type.normal); + processServerMessage(incomingChat.build()); assertNotNull(listener.getNewChat()); } @Test public void validateMessageTypeWithDefaults3() { - Message incomingChat = createChatPacket("134", true); - incomingChat.setType(Type.groupchat); - processServerMessage(incomingChat); + MessageBuilder incomingChat = createChatPacket("134", true); + incomingChat.ofType(Type.groupchat); + processServerMessage(incomingChat.build()); assertNull(listener.getNewChat()); } @Test public void validateMessageTypeWithDefaults4() { - Message incomingChat = createChatPacket("134", true); - incomingChat.setType(Type.headline); + MessageBuilder incomingChat = createChatPacket("134", true); + incomingChat.ofType(Type.headline); assertNull(listener.getNewChat()); } @Test public void validateMessageTypeWithNoNormal1() { cm.setNormalIncluded(false); - Message incomingChat = createChatPacket("134", true); - incomingChat.setType(Type.chat); - processServerMessage(incomingChat); + MessageBuilder incomingChat = createChatPacket("134", true); + incomingChat.ofType(Type.chat); + processServerMessage(incomingChat.build()); assertNotNull(listener.getNewChat()); } @Test public void validateMessageTypeWithNoNormal2() { cm.setNormalIncluded(false); - Message incomingChat = createChatPacket("134", true); - incomingChat.setType(Type.normal); - processServerMessage(incomingChat); + MessageBuilder incomingChat = createChatPacket("134", true); + incomingChat.ofType(Type.normal); + processServerMessage(incomingChat.build()); assertNull(listener.getNewChat()); } @@ -142,18 +144,18 @@ public class ChatConnectionTest { TestMessageListener msgListener = new TestMessageListener(); TestChatManagerListener listener = new TestChatManagerListener(msgListener); cm.addChatListener(listener); - Stanza incomingChat = createChatPacket(null, true); + Stanza incomingChat = createChatMessage(null, true); processServerMessage(incomingChat); Chat newChat = listener.getNewChat(); assertNotNull(newChat); // Should match on chat with full jid - incomingChat = createChatPacket(null, true); + incomingChat = createChatMessage(null, true); processServerMessage(incomingChat); assertEquals(2, msgListener.getNumMessages()); // Should match on chat with bare jid - incomingChat = createChatPacket(null, false); + incomingChat = createChatMessage(null, false); processServerMessage(incomingChat); assertEquals(3, msgListener.getNumMessages()); } @@ -164,21 +166,21 @@ public class ChatConnectionTest { TestChatManagerListener listener = new TestChatManagerListener(msgListener); cm.setMatchMode(ChatManager.MatchMode.SUPPLIED_JID); cm.addChatListener(listener); - Stanza incomingChat = createChatPacket(null, true); + Stanza incomingChat = createChatMessage(null, true); processServerMessage(incomingChat); Chat newChat = listener.getNewChat(); assertNotNull(newChat); cm.removeChatListener(listener); // Should match on chat with full jid - incomingChat = createChatPacket(null, true); + incomingChat = createChatMessage(null, true); processServerMessage(incomingChat); assertEquals(2, msgListener.getNumMessages()); // Should not match on chat with bare jid TestChatManagerListener listener2 = new TestChatManagerListener(); cm.addChatListener(listener2); - incomingChat = createChatPacket(null, false); + incomingChat = createChatMessage(null, false); processServerMessage(incomingChat); assertEquals(2, msgListener.getNumMessages()); assertNotNull(listener2.getNewChat()); @@ -190,7 +192,7 @@ public class ChatConnectionTest { TestChatManagerListener listener = new TestChatManagerListener(msgListener); cm.setMatchMode(ChatManager.MatchMode.NONE); cm.addChatListener(listener); - Stanza incomingChat = createChatPacket(null, true); + Stanza incomingChat = createChatMessage(null, true); processServerMessage(incomingChat); Chat newChat = listener.getNewChat(); assertNotNull(newChat); @@ -200,7 +202,7 @@ public class ChatConnectionTest { // Should not match on chat with full jid TestChatManagerListener listener2 = new TestChatManagerListener(); cm.addChatListener(listener2); - incomingChat = createChatPacket(null, true); + incomingChat = createChatMessage(null, true); processServerMessage(incomingChat); assertEquals(1, msgListener.getNumMessages()); assertNotNull(newChat); @@ -209,7 +211,7 @@ public class ChatConnectionTest { // Should not match on chat with bare jid TestChatManagerListener listener3 = new TestChatManagerListener(); cm.addChatListener(listener3); - incomingChat = createChatPacket(null, false); + incomingChat = createChatMessage(null, false); processServerMessage(incomingChat); assertEquals(1, msgListener.getNumMessages()); assertNotNull(listener3.getNewChat()); @@ -223,7 +225,7 @@ public class ChatConnectionTest { public void chatFoundWhenNoThreadEntityFullJid() { Chat outgoing = cm.createChat(JidTestUtil.DUMMY_AT_EXAMPLE_ORG, null); - Stanza incomingChat = createChatPacket(null, true); + Stanza incomingChat = createChatMessage(null, true); processServerMessage(incomingChat); Chat newChat = listener.getNewChat(); @@ -239,7 +241,7 @@ public class ChatConnectionTest { public void chatFoundWhenNoThreadBaseJid() { Chat outgoing = cm.createChat(JidTestUtil.DUMMY_AT_EXAMPLE_ORG, null); - Stanza incomingChat = createChatPacket(null, false); + Stanza incomingChat = createChatMessage(null, false); processServerMessage(incomingChat); Chat newChat = listener.getNewChat(); @@ -255,7 +257,7 @@ public class ChatConnectionTest { public void chatFoundWithSameThreadEntityFullJid() { Chat outgoing = cm.createChat(JidTestUtil.DUMMY_AT_EXAMPLE_ORG, null); - Stanza incomingChat = createChatPacket(outgoing.getThreadID(), true); + Stanza incomingChat = createChatMessage(outgoing.getThreadID(), true); processServerMessage(incomingChat); Chat newChat = listener.getNewChat(); @@ -271,7 +273,7 @@ public class ChatConnectionTest { public void chatFoundWithSameThreadBaseJid() { Chat outgoing = cm.createChat(JidTestUtil.DUMMY_AT_EXAMPLE_ORG, null); - Stanza incomingChat = createChatPacket(outgoing.getThreadID(), false); + Stanza incomingChat = createChatMessage(outgoing.getThreadID(), false); processServerMessage(incomingChat); Chat newChat = listener.getNewChat(); @@ -287,7 +289,7 @@ public class ChatConnectionTest { public void chatNotFoundWithDiffThreadBaseJid() { Chat outgoing = cm.createChat(JidTestUtil.DUMMY_AT_EXAMPLE_ORG, null); - Stanza incomingChat = createChatPacket(outgoing.getThreadID() + "ff", false); + Stanza incomingChat = createChatMessage(outgoing.getThreadID() + "ff", false); processServerMessage(incomingChat); Chat newChat = listener.getNewChat(); @@ -303,7 +305,7 @@ public class ChatConnectionTest { public void chatNotFoundWithDiffThreadEntityFullJid() { Chat outgoing = cm.createChat(JidTestUtil.DUMMY_AT_EXAMPLE_ORG, null); - Stanza incomingChat = createChatPacket(outgoing.getThreadID() + "ff", true); + Stanza incomingChat = createChatMessage(outgoing.getThreadID() + "ff", true); processServerMessage(incomingChat); Chat newChat = listener.getNewChat(); @@ -315,15 +317,17 @@ public class ChatConnectionTest { public void chatNotMatchedWithTypeNormal() { cm.setNormalIncluded(false); - Message incomingChat = createChatPacket(null, false); - incomingChat.setType(Type.normal); - processServerMessage(incomingChat); + MessageBuilder incomingChat = createChatPacket(null, false); + incomingChat.ofType(Type.normal); + processServerMessage(incomingChat.build()); assertNull(listener.getNewChat()); } - private static Message createChatPacket(final String threadId, final boolean isEntityFullJid) { - Message chatMsg = new Message(JidTestUtil.BARE_JID_1, Message.Type.chat); + private static MessageBuilder createChatPacket(final String threadId, final boolean isEntityFullJid) { + MessageBuilder chatMsg = StanzaBuilder.buildMessage() + .ofType(Message.Type.chat) + .to(JidTestUtil.BARE_JID_1); chatMsg.setBody("the body message - " + System.currentTimeMillis()); Jid jid; if (isEntityFullJid) { @@ -331,11 +335,15 @@ public class ChatConnectionTest { } else { jid = JidTestUtil.DUMMY_AT_EXAMPLE_ORG; } - chatMsg.setFrom(jid); + chatMsg.from(jid); chatMsg.setThread(threadId); return chatMsg; } + private static Message createChatMessage(final String threadId, final boolean isEntityFullJid) { + return createChatPacket(threadId, isEntityFullJid).build(); + } + private void processServerMessage(Stanza incomingChat) { TestChatServer chatServer = new TestChatServer(incomingChat, dc); chatServer.start(); diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/XmppConnectionStressTest.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/XmppConnectionStressTest.java index aa0965306..712d75783 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/XmppConnectionStressTest.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/XmppConnectionStressTest.java @@ -31,6 +31,7 @@ import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.filter.MessageTypeFilter; import org.jivesoftware.smack.filter.StanzaExtensionFilter; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.util.Async; import org.jivesoftware.smack.util.BooleansUtils; @@ -86,18 +87,19 @@ public class XmppConnectionStressTest { MultiMap toConnectionMessages = new MultiMap<>(); for (XMPPConnection toConnection : connections) { for (int i = 0; i < configuration.messagesPerConnection; i++) { - Message message = new Message(); - message.setTo(toConnection.getUser()); + MessageBuilder messageBuilder = fromConnection.getStanzaFactory().buildMessageStanza(); + messageBuilder.to(toConnection.getUser()); int payloadChunkCount = random.nextInt(configuration.maxPayloadChunks) + 1; for (int c = 0; c < payloadChunkCount; c++) { int payloadChunkSize = random.nextInt(configuration.maxPayloadChunkSize) + 1; String payloadCunk = StringUtils.randomString(payloadChunkSize, random); - JivePropertiesManager.addProperty(message, "payload-chunk-" + c, payloadCunk); + JivePropertiesManager.addProperty(messageBuilder, "payload-chunk-" + c, payloadCunk); } - JivePropertiesManager.addProperty(message, MESSAGE_NUMBER_PROPERTY, i); + JivePropertiesManager.addProperty(messageBuilder, MESSAGE_NUMBER_PROPERTY, i); + Message message = messageBuilder.build(); toConnectionMessages.put(toConnection, message); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smack/ChatTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/ChatTest.java index b206fdb5b..ec21761a5 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/ChatTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/ChatTest.java @@ -28,6 +28,9 @@ import java.util.Date; import org.jivesoftware.smack.chat.ChatManagerListener; import org.jivesoftware.smack.filter.ThreadFilter; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; + import org.jivesoftware.smackx.jiveproperties.JivePropertiesManager; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; @@ -69,17 +72,18 @@ public class ChatTest extends AbstractSmackIntegrationTest { org.jivesoftware.smack.chat.Chat newChat = chatManagerOne.createChat(conTwo.getUser()); StanzaCollector collector = conTwo.createStanzaCollector(new ThreadFilter(newChat.getThreadID())); - Message msg = new Message(); + MessageBuilder messageBuilder = StanzaBuilder.buildMessage(); - msg.setSubject("Subject of the chat"); - msg.setBody("Body of the chat"); - addProperty(msg, "favoriteColor", "red"); - addProperty(msg, "age", 30); - addProperty(msg, "distance", 30f); - addProperty(msg, "weight", 30d); - addProperty(msg, "male", true); - addProperty(msg, "birthdate", new Date()); + messageBuilder.setSubject("Subject of the chat"); + messageBuilder.setBody("Body of the chat"); + addProperty(messageBuilder, "favoriteColor", "red"); + addProperty(messageBuilder, "age", 30); + addProperty(messageBuilder, "distance", 30f); + addProperty(messageBuilder, "weight", 30d); + addProperty(messageBuilder, "male", true); + addProperty(messageBuilder, "birthdate", new Date()); + Message msg = messageBuilder.build(); newChat.sendMessage(msg); Message msg2 = collector.nextResult(2000); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smack/StreamManagementTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/StreamManagementTest.java index 999f14684..a26cf8e17 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/StreamManagementTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/StreamManagementTest.java @@ -77,8 +77,10 @@ public class StreamManagementTest extends AbstractSmackSpecificLowLevelIntegrati private static void send(String messageString, XMPPConnection from, XMPPConnection to) throws NotConnectedException, InterruptedException { - Message message = new Message(to.getUser()); - message.setBody(messageString); + Message message = from.getStanzaFactory().buildMessageStanza() + .to(to.getUser()) + .setBody(messageString) + .build(); from.sendStanza(message); } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java index d2ffb6327..c236d8aa4 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java @@ -19,6 +19,7 @@ package org.jivesoftware.smackx.chatstate; import org.jivesoftware.smack.chat2.Chat; import org.jivesoftware.smack.chat2.ChatManager; import org.jivesoftware.smack.packet.Message; + import org.jivesoftware.smackx.chatstates.ChatState; import org.jivesoftware.smackx.chatstates.ChatStateListener; import org.jivesoftware.smackx.chatstates.ChatStateManager; diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/mam/MamIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/mam/MamIntegrationTest.java index f09832b25..0ee3d295b 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/mam/MamIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/mam/MamIntegrationTest.java @@ -32,6 +32,7 @@ import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.filter.MessageWithBodiesFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smackx.mam.MamManager.MamQuery; import org.jivesoftware.smackx.mam.MamManager.MamQueryArgs; @@ -66,10 +67,12 @@ public class MamIntegrationTest extends AbstractSmackIntegrationTest { EntityBareJid userOne = conOne.getUser().asEntityBareJid(); EntityBareJid userTwo = conTwo.getUser().asEntityBareJid(); - Message message = new Message(userTwo); - String messageId = message.ensureStanzaIdSet(); final String messageBody = "Test MAM message (" + testRunId + ')'; - message.setBody(messageBody); + Message message = conTwo.getStanzaFactory().buildMessageStanza() + .to(userTwo) + .setBody(messageBody) + .build(); + final String messageId = message.getStanzaId(); final SimpleResultSyncPoint messageReceived = new SimpleResultSyncPoint(); @@ -122,7 +125,10 @@ public class MamIntegrationTest extends AbstractSmackIntegrationTest { for (int i = 0; i < totalMessages; i++) { String messageBody = "MAM Page Test " + testRunId + ' ' + (i + 1); - Message message = new Message(userTwo, messageBody); + Message message = StanzaBuilder.buildMessage() + .to(userTwo) + .setBody(messageBody) + .build(); outgoingMessages.add(message); } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java index 5d96468c3..c7651a052 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java @@ -28,6 +28,7 @@ import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.util.StringUtils; + import org.jivesoftware.smackx.muc.MultiUserChat.MucCreateConfigFormHandle; import org.jivesoftware.smackx.muc.MultiUserChatException.MucNotJoinedException; import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceException; diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/AbstractOmemoMessageListener.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/AbstractOmemoMessageListener.java index 073c82e7e..48ffb202b 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/AbstractOmemoMessageListener.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/AbstractOmemoMessageListener.java @@ -18,6 +18,7 @@ package org.jivesoftware.smackx.omemo; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; + import org.jivesoftware.smackx.carbons.packet.CarbonExtension; import org.jivesoftware.smackx.omemo.listener.OmemoMessageListener; diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/MessageEncryptionIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/MessageEncryptionIntegrationTest.java index 6a9ba5e20..938696441 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/MessageEncryptionIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/MessageEncryptionIntegrationTest.java @@ -20,7 +20,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.MessageBuilder; + import org.jivesoftware.smackx.omemo.element.OmemoBundleElement; import org.igniterealtime.smack.inttest.SmackIntegrationTest; @@ -68,7 +71,10 @@ public class MessageEncryptionIntegrationTest extends AbstractTwoUsersOmemoInteg new AbstractOmemoMessageListener.PreKeyMessageListener(body1); bob.addOmemoMessageListener(listener1); OmemoMessage.Sent e1 = alice.encrypt(bob.getOwnJid(), body1); - alice.getConnection().sendStanza(e1.asMessage(bob.getOwnJid())); + + XMPPConnection alicesConnection = alice.getConnection(); + MessageBuilder messageBuilder = alicesConnection.getStanzaFactory().buildMessageStanza(); + alicesConnection.sendStanza(e1.buildMessage(messageBuilder, bob.getOwnJid())); listener1.getSyncPoint().waitForResult(10 * 1000); bob.removeOmemoMessageListener(listener1); @@ -88,7 +94,9 @@ public class MessageEncryptionIntegrationTest extends AbstractTwoUsersOmemoInteg new AbstractOmemoMessageListener.MessageListener(body3); alice.addOmemoMessageListener(listener3); OmemoMessage.Sent e3 = bob.encrypt(alice.getOwnJid(), body3); - bob.getConnection().sendStanza(e3.asMessage(alice.getOwnJid())); + XMPPConnection bobsConnection = bob.getConnection(); + messageBuilder = bobsConnection.getStanzaFactory().buildMessageStanza(); + bobsConnection.sendStanza(e3.buildMessage(messageBuilder, alice.getOwnJid())); listener3.getSyncPoint().waitForResult(10 * 1000); alice.removeOmemoMessageListener(listener3); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMamDecryptionTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMamDecryptionTest.java index b562db8f8..8a36a2f22 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMamDecryptionTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMamDecryptionTest.java @@ -22,7 +22,10 @@ import java.io.IOException; import java.util.List; import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.MessageBuilder; + import org.jivesoftware.smackx.mam.MamManager; import org.jivesoftware.smackx.mam.element.MamPrefsIQ; import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException; @@ -62,7 +65,10 @@ public class OmemoMamDecryptionTest extends AbstractTwoUsersOmemoIntegrationTest String body = "This message will be stored in MAM!"; OmemoMessage.Sent encrypted = alice.encrypt(bob.getOwnJid(), body); - alice.getConnection().sendStanza(encrypted.asMessage(bob.getOwnJid())); + + XMPPConnection alicesConnection = alice.getConnection(); + MessageBuilder messageBuilder = alicesConnection.getStanzaFactory().buildMessageStanza(); + alicesConnection.sendStanza(encrypted.buildMessage(messageBuilder, bob.getOwnJid())); MamManager.MamQuery query = bobsMamManager.queryArchive(MamManager.MamQueryArgs.builder().limitResultsToJid(alice.getOwnJid()).build()); assertEquals(1, query.getMessageCount()); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoManagerSetupHelper.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoManagerSetupHelper.java index fba866790..f330880ad 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoManagerSetupHelper.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoManagerSetupHelper.java @@ -28,6 +28,7 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.RosterEntry; + import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException; import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException; import org.jivesoftware.smackx.omemo.internal.OmemoCachedDeviceList; diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/ReadOnlyDeviceIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/ReadOnlyDeviceIntegrationTest.java index 815d4a032..dc13bdb8f 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/ReadOnlyDeviceIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/ReadOnlyDeviceIntegrationTest.java @@ -24,6 +24,7 @@ import java.io.IOException; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; + import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException; import org.jivesoftware.smackx.omemo.exceptions.ReadOnlyDeviceException; import org.jivesoftware.smackx.omemo.exceptions.UndecidedOmemoIdentityException; diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/SessionRenegotiationIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/SessionRenegotiationIntegrationTest.java index ae1324b22..fa863f1be 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/SessionRenegotiationIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/SessionRenegotiationIntegrationTest.java @@ -17,7 +17,9 @@ package org.jivesoftware.smackx.omemo; import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.MessageBuilder; import org.igniterealtime.smack.inttest.SmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; @@ -46,7 +48,10 @@ public class SessionRenegotiationIntegrationTest extends AbstractTwoUsersOmemoIn new AbstractOmemoMessageListener.PreKeyMessageListener(body1); OmemoMessage.Sent e1 = alice.encrypt(bob.getOwnJid(), body1); bob.addOmemoMessageListener(listener1); - alice.getConnection().sendStanza(e1.asMessage(bob.getOwnJid())); + + XMPPConnection alicesConnection = alice.getConnection(); + MessageBuilder messageBuilder = alicesConnection.getStanzaFactory().buildMessageStanza(); + alicesConnection.sendStanza(e1.buildMessage(messageBuilder, bob.getOwnJid())); listener1.getSyncPoint().waitForResult(10 * 1000); bob.removeOmemoMessageListener(listener1); @@ -61,7 +66,9 @@ public class SessionRenegotiationIntegrationTest extends AbstractTwoUsersOmemoIn new AbstractOmemoMessageListener.PreKeyKeyTransportListener(); OmemoMessage.Sent e2 = alice.encrypt(bob.getOwnJid(), body2); alice.addOmemoMessageListener(listener2); - alice.getConnection().sendStanza(e2.asMessage(bob.getOwnJid())); + + messageBuilder = alicesConnection.getStanzaFactory().buildMessageStanza(); + alicesConnection.sendStanza(e2.buildMessage(messageBuilder, bob.getOwnJid())); listener2.getSyncPoint().waitForResult(10 * 1000); alice.removeOmemoMessageListener(listener2); @@ -70,7 +77,9 @@ public class SessionRenegotiationIntegrationTest extends AbstractTwoUsersOmemoIn AbstractOmemoMessageListener.MessageListener listener3 = new AbstractOmemoMessageListener.MessageListener(body3); OmemoMessage.Sent e3 = alice.encrypt(bob.getOwnJid(), body3); bob.addOmemoMessageListener(listener3); - alice.getConnection().sendStanza(e3.asMessage(bob.getOwnJid())); + + messageBuilder = alicesConnection.getStanzaFactory().buildMessageStanza(); + alicesConnection.sendStanza(e3.buildMessage(messageBuilder, bob.getOwnJid())); listener3.getSyncPoint().waitForResult(10 * 1000); bob.removeOmemoMessageListener(listener3); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/AbstractOpenPgpIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/AbstractOpenPgpIntegrationTest.java index 2399c6999..d02d4f3f5 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/AbstractOpenPgpIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/AbstractOpenPgpIntegrationTest.java @@ -19,6 +19,7 @@ package org.jivesoftware.smackx.ox; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; + import org.jivesoftware.smackx.ox.util.OpenPgpPubSubUtil; import org.jivesoftware.smackx.pep.PepManager; diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/OXSecretKeyBackupIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/OXSecretKeyBackupIntegrationTest.java index b72636bc8..897dda339 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/OXSecretKeyBackupIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/OXSecretKeyBackupIntegrationTest.java @@ -33,6 +33,7 @@ import java.util.logging.Level; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.util.StringUtils; + import org.jivesoftware.smackx.ox.callback.backup.AskForBackupCodeCallback; import org.jivesoftware.smackx.ox.callback.backup.DisplayBackupCodeCallback; import org.jivesoftware.smackx.ox.callback.backup.SecretKeyBackupSelectionCallback; diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingIntegrationTest.java index 1b469953d..1f68eeb4d 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingIntegrationTest.java @@ -27,6 +27,7 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.util.StringUtils; + import org.jivesoftware.smackx.ox.AbstractOpenPgpIntegrationTest; import org.jivesoftware.smackx.ox.OpenPgpContact; import org.jivesoftware.smackx.ox.OpenPgpManager; diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java index 86383a819..c766bc6e5 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java @@ -22,6 +22,7 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException.NotLoggedInException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Message; + import org.jivesoftware.smackx.usertune.element.UserTuneElement; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; @@ -30,7 +31,6 @@ import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.util.IntegrationTestRosterUtil; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; import org.junit.AfterClass; - import org.jxmpp.jid.BareJid; public class UserTuneIntegrationTest extends AbstractSmackIntegrationTest { diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/xdata/FormTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/xdata/FormTest.java index 682f3b82f..cf89a68f2 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/xdata/FormTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/xdata/FormTest.java @@ -25,6 +25,8 @@ import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.StanzaCollector; import org.jivesoftware.smack.filter.ThreadFilter; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; + import org.jivesoftware.smackx.xdata.FormField.Type; import org.jivesoftware.smackx.xdata.packet.DataForm; @@ -96,9 +98,10 @@ public class FormTest extends AbstractSmackIntegrationTest { StanzaCollector collector2 = conTwo.createStanzaCollector( new ThreadFilter(chat.getThreadID())); - Message msg = new Message(); - msg.setBody("To enter a case please fill out this form and send it back to me"); - msg.addExtension(formToSend.getDataFormToSend()); + Message msg = StanzaBuilder.buildMessage() + .setBody("To enter a case please fill out this form and send it back to me") + .addExtension(formToSend.getDataFormToSend()) + .build(); try { // Send the message with the form to fill out @@ -130,13 +133,14 @@ public class FormTest extends AbstractSmackIntegrationTest { completedForm.setAnswer("time", true); completedForm.setAnswer("age", 20); // Create a new message to send with the completed form - msg2 = new Message(); - msg2.setTo(conOne.getUser().asBareJid()); - msg2.setThread(msg.getThread()); - msg2.setType(Message.Type.chat); - msg2.setBody("To enter a case please fill out this form and send it back to me"); - // Add the completed form to the message - msg2.addExtension(completedForm.getDataFormToSend()); + msg2 = StanzaBuilder.buildMessage() + .to(conOne.getUser().asBareJid()) + .setThread(msg.getThread()) + .ofType(Message.Type.chat) + .setBody("To enter a case please fill out this form and send it back to me") + // Add the completed form to the message + .addExtension(completedForm.getDataFormToSend()) + .build(); // Send the message with the completed form conTwo.sendStanza(msg2); diff --git a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/unittest/SmackIntegrationTestFrameworkUnitTest.java b/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/unittest/SmackIntegrationTestFrameworkUnitTest.java index d94a9b16c..fe943873b 100644 --- a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/unittest/SmackIntegrationTestFrameworkUnitTest.java +++ b/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/unittest/SmackIntegrationTestFrameworkUnitTest.java @@ -31,6 +31,7 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.packet.StanzaError; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; @@ -112,7 +113,7 @@ public class SmackIntegrationTestFrameworkUnitTest { @SmackIntegrationTest public void throwRuntimeExceptionTest() throws XMPPErrorException { - Message message = new Message(); + Message message = StanzaBuilder.buildMessage().build(); throw new XMPPException.XMPPErrorException(message, StanzaError.from(StanzaError.Condition.bad_request, DESCRIPTIVE_TEXT).build()); } diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSession.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSession.java index 03aba4ff4..43b92937f 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSession.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSession.java @@ -1070,8 +1070,10 @@ public final class JingleSession extends JingleNegotiator implements MediaReceiv IQ errorPacket = null; if (jingleError != null) { // TODO This is wrong according to XEP-166 § 10, but this jingle implementation is deprecated anyways - StanzaError.Builder builder = StanzaError.getBuilder(StanzaError.Condition.undefined_condition); - builder.addExtension(jingleError); + StanzaError builder = StanzaError.getBuilder() + .setCondition(StanzaError.Condition.undefined_condition) + .addExtension(jingleError) + .build(); errorPacket = IQ.createErrorResponse(iq, builder); diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java index 1a0fc285f..199031b87 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java @@ -34,7 +34,7 @@ import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Stanza; - +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smackx.workgroup.packet.AgentStatus; import org.jivesoftware.smackx.workgroup.packet.AgentStatusRequest; @@ -213,8 +213,10 @@ public class AgentRoster { Jid key = getPresenceMapKey(user); Map userPresences = presenceMap.get(key); if (userPresences == null) { - Presence presence = new Presence(Presence.Type.unavailable); - presence.setFrom(user); + Presence presence = StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .from(user) + .build(); return presence; } else { @@ -236,8 +238,7 @@ public class AgentRoster { } } if (presence == null) { - presence = new Presence(Presence.Type.unavailable); - presence.setFrom(user); + presence = synthesizeUnvailablePresence(user); return presence; } else { @@ -289,6 +290,13 @@ public class AgentRoster { } } + private static Presence synthesizeUnvailablePresence(Jid from) { + return StanzaBuilder.buildPresence() + .ofType(Presence.Type.unavailable) + .from(from) + .build(); + } + /** * Listens for all presence packets and processes them. */ diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentSession.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentSession.java index e608fc683..00461afd4 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentSession.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentSession.java @@ -45,9 +45,9 @@ import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.PresenceBuilder; import org.jivesoftware.smack.packet.StandardExtensionElement; import org.jivesoftware.smack.packet.Stanza; - import org.jivesoftware.smackx.muc.packet.MUCUser; import org.jivesoftware.smackx.search.ReportedData; import org.jivesoftware.smackx.workgroup.MetaData; @@ -335,8 +335,11 @@ public class AgentSession { // If the user is going online... if (online) { - presence = new Presence(Presence.Type.available); - presence.setTo(workgroupJID); + presence = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.available) + .to(workgroupJID) + .build(); + presence.addExtension(new StandardExtensionElement(AgentStatus.ELEMENT_NAME, AgentStatus.NAMESPACE)); @@ -353,8 +356,10 @@ public class AgentSession { // Update this iv now since we don't care at this point of any error this.online = online; - presence = new Presence(Presence.Type.unavailable); - presence.setTo(workgroupJID); + presence = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.unavailable) + .to(workgroupJID) + .build(); presence.addExtension(new StandardExtensionElement(AgentStatus.ELEMENT_NAME, AgentStatus.NAMESPACE)); connection.sendStanza(presence); @@ -427,21 +432,21 @@ public class AgentSession { this.presenceMode = presenceMode; this.maxChats = maxChats; - Presence presence = new Presence(Presence.Type.available); - presence.setMode(presenceMode); - presence.setTo(this.getWorkgroupJID()); - - if (status != null) { - presence.setStatus(status); - } + PresenceBuilder presenceBuilder = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.available) + .setMode(presenceMode) + .to(workgroupJID) + .setStatus(status) + ; // Send information about max chats and current chats as a packet extension. StandardExtensionElement.Builder builder = StandardExtensionElement.builder(AgentStatus.ELEMENT_NAME, AgentStatus.NAMESPACE); builder.addElement("max_chats", Integer.toString(maxChats)); - presence.addExtension(builder.build()); - presence.addExtension(new MetaData(this.metaData)); + presenceBuilder.addExtension(builder.build()); + presenceBuilder.addExtension(new MetaData(this.metaData)); + Presence presence = presenceBuilder.build(); StanzaCollector collector = this.connection.createStanzaCollectorAndSend(new AndFilter( new StanzaTypeFilter(Presence.class), FromMatchesFilter.create(workgroupJID)), presence); @@ -478,13 +483,16 @@ public class AgentSession { } this.presenceMode = presenceMode; - Presence presence = new Presence(Presence.Type.available); - presence.setMode(presenceMode); - presence.setTo(this.getWorkgroupJID()); + PresenceBuilder presenceBuilder = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.available) + .setMode(presenceMode) + .to(getWorkgroupJID()); if (status != null) { - presence.setStatus(status); + presenceBuilder.setStatus(status); } + + Presence presence = presenceBuilder.build(); presence.addExtension(new MetaData(this.metaData)); StanzaCollector collector = this.connection.createStanzaCollectorAndSend(new AndFilter(new StanzaTypeFilter(Presence.class), diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/user/Workgroup.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/user/Workgroup.java index 99907adc6..8f1319173 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/user/Workgroup.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/user/Workgroup.java @@ -188,8 +188,11 @@ public class Workgroup { * @throws InterruptedException if the calling thread was interrupted. */ public boolean isAvailable() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - Presence directedPresence = new Presence(Presence.Type.available); - directedPresence.setTo(workgroupJID); + Presence directedPresence = connection.getStanzaFactory().buildPresenceStanza() + .ofType(Presence.Type.available) + .to(workgroupJID) + .build(); + StanzaFilter typeFilter = new StanzaTypeFilter(Presence.class); StanzaFilter fromFilter = FromMatchesFilter.create(workgroupJID); StanzaCollector collector = connection.createStanzaCollectorAndSend(new AndFilter(fromFilter, diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/xevent/MessageEventManager.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/xevent/MessageEventManager.java index a2ca8d17b..23b048ec0 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/xevent/MessageEventManager.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/xevent/MessageEventManager.java @@ -213,15 +213,18 @@ public final class MessageEventManager extends Manager { * @throws InterruptedException if the calling thread was interrupted. */ public void sendDeliveredNotification(Jid to, String packetID) throws NotConnectedException, InterruptedException { - // Create the message to send - Message msg = new Message(to); // Create a MessageEvent Package and add it to the message MessageEvent messageEvent = new MessageEvent(); messageEvent.setDelivered(true); messageEvent.setStanzaId(packetID); - msg.addExtension(messageEvent); + + XMPPConnection connection = connection(); + Message msg = connection.getStanzaFactory().buildMessageStanza() + .to(to) + .addExtension(messageEvent) + .build(); // Send the packet - connection().sendStanza(msg); + connection.sendStanza(msg); } /** @@ -233,15 +236,18 @@ public final class MessageEventManager extends Manager { * @throws InterruptedException if the calling thread was interrupted. */ public void sendDisplayedNotification(Jid to, String packetID) throws NotConnectedException, InterruptedException { - // Create the message to send - Message msg = new Message(to); // Create a MessageEvent Package and add it to the message MessageEvent messageEvent = new MessageEvent(); messageEvent.setDisplayed(true); messageEvent.setStanzaId(packetID); - msg.addExtension(messageEvent); + + XMPPConnection connection = connection(); + Message msg = connection.getStanzaFactory().buildMessageStanza() + .to(to) + .addExtension(messageEvent) + .build(); // Send the packet - connection().sendStanza(msg); + connection.sendStanza(msg); } /** @@ -253,15 +259,18 @@ public final class MessageEventManager extends Manager { * @throws InterruptedException if the calling thread was interrupted. */ public void sendComposingNotification(Jid to, String packetID) throws NotConnectedException, InterruptedException { - // Create the message to send - Message msg = new Message(to); // Create a MessageEvent Package and add it to the message MessageEvent messageEvent = new MessageEvent(); messageEvent.setComposing(true); messageEvent.setStanzaId(packetID); - msg.addExtension(messageEvent); + + XMPPConnection connection = connection(); + Message msg = connection.getStanzaFactory().buildMessageStanza() + .to(to) + .addExtension(messageEvent) + .build(); // Send the packet - connection().sendStanza(msg); + connection.sendStanza(msg); } /** @@ -273,13 +282,17 @@ public final class MessageEventManager extends Manager { * @throws InterruptedException if the calling thread was interrupted. */ public void sendCancelledNotification(Jid to, String packetID) throws NotConnectedException, InterruptedException { - // Create the message to send - Message msg = new Message(to); // Create a MessageEvent Package and add it to the message MessageEvent messageEvent = new MessageEvent(); messageEvent.setCancelled(true); messageEvent.setStanzaId(packetID); - msg.addExtension(messageEvent); + + XMPPConnection connection = connection(); + + Message msg = connection.getStanzaFactory().buildMessageStanza() + .to(to) + .addExtension(messageEvent) + .build(); // Send the packet connection().sendStanza(msg); } diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/RosterExchangeManager.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/RosterExchangeManager.java index 1f42c6f02..6af000028 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/RosterExchangeManager.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/RosterExchangeManager.java @@ -30,6 +30,7 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.filter.StanzaExtensionFilter; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.RosterEntry; @@ -121,15 +122,16 @@ public class RosterExchangeManager { * @throws InterruptedException if the calling thread was interrupted. */ public void send(Roster roster, Jid targetUserID) throws NotConnectedException, InterruptedException { + XMPPConnection connection = weakRefConnection.get(); + // Create a new message to send the roster - Message msg = new Message(targetUserID); + MessageBuilder messageBuilder = connection.getStanzaFactory().buildMessageStanza().to(targetUserID); // Create a RosterExchange Package and add it to the message RosterExchange rosterExchange = new RosterExchange(roster); - msg.addExtension(rosterExchange); + messageBuilder.addExtension(rosterExchange); - XMPPConnection connection = weakRefConnection.get(); // Send the message that contains the roster - connection.sendStanza(msg); + connection.sendStanza(messageBuilder.build()); } /** @@ -141,16 +143,17 @@ public class RosterExchangeManager { * @throws InterruptedException if the calling thread was interrupted. */ public void send(RosterEntry rosterEntry, Jid targetUserID) throws NotConnectedException, InterruptedException { + XMPPConnection connection = weakRefConnection.get(); + // Create a new message to send the roster - Message msg = new Message(targetUserID); + MessageBuilder messageBuilder = connection.getStanzaFactory().buildMessageStanza().to(targetUserID); // Create a RosterExchange Package and add it to the message RosterExchange rosterExchange = new RosterExchange(); rosterExchange.addRosterEntry(rosterEntry); - msg.addExtension(rosterExchange); + messageBuilder.addExtension(rosterExchange); - XMPPConnection connection = weakRefConnection.get(); // Send the message that contains the roster - connection.sendStanza(msg); + connection.sendStanza(messageBuilder.build()); } /** @@ -163,8 +166,10 @@ public class RosterExchangeManager { * @throws InterruptedException if the calling thread was interrupted. */ public void send(RosterGroup rosterGroup, Jid targetUserID) throws NotConnectedException, InterruptedException { + XMPPConnection connection = weakRefConnection.get(); + // Create a new message to send the roster - Message msg = new Message(targetUserID); + MessageBuilder msg = connection.getStanzaFactory().buildMessageStanza().to(targetUserID); // Create a RosterExchange Package and add it to the message RosterExchange rosterExchange = new RosterExchange(); for (RosterEntry entry : rosterGroup.getEntries()) { @@ -172,9 +177,8 @@ public class RosterExchangeManager { } msg.addExtension(rosterExchange); - XMPPConnection connection = weakRefConnection.get(); // Send the message that contains the roster - connection.sendStanza(msg); + connection.sendStanza(msg.build()); } /** diff --git a/smack-omemo-signal/src/test/java/org/jivesoftware/smackx/omemo/SignalOmemoManagerTest.java b/smack-omemo-signal/src/test/java/org/jivesoftware/smackx/omemo/SignalOmemoManagerTest.java index 64d07a9ff..15299a259 100644 --- a/smack-omemo-signal/src/test/java/org/jivesoftware/smackx/omemo/SignalOmemoManagerTest.java +++ b/smack-omemo-signal/src/test/java/org/jivesoftware/smackx/omemo/SignalOmemoManagerTest.java @@ -28,6 +28,7 @@ import static junit.framework.TestCase.assertTrue; import org.jivesoftware.smack.DummyConnection; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smackx.omemo.element.OmemoElement; @@ -83,9 +84,9 @@ public class SignalOmemoManagerTest extends SmackTestSuite { public void stanzaRecognitionTest() throws Exception { String omemoXML = "

MwohBfRqBm2atj3fT0/KUDg59Cnvfpgoe/PLNIu1xgSXujEZEAAYACIwKh6TTC7VBQZcCcKnQlO+6s1GQ9DIRKH4JU7XrJ+JJnkPUwJ4VLSeOEQD7HmFbhQPTLZO0u/qlng=sN0amy4e2NBrlb4G/OjNIQ==
4xVUAeg4M0Mhk+5n3YG1x12Dw/cYTc0Z"; OmemoElement omemoElement = new OmemoVAxolotlProvider().parse(TestUtils.getParser(omemoXML)); - Message m = new Message(); - m.addExtension(omemoElement); - Message n = new Message(); + + Message m = StanzaBuilder.buildMessage().addExtension(omemoElement).build(); + Message n = StanzaBuilder.buildMessage().build(); assertTrue(OmemoManager.stanzaContainsOmemoElement(m)); assertFalse(OmemoManager.stanzaContainsOmemoElement(n)); diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoManager.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoManager.java index 04f226b9f..ba53e452c 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoManager.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoManager.java @@ -43,6 +43,7 @@ import org.jivesoftware.smack.XMPPException; 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.util.Async; @@ -491,16 +492,17 @@ public final class OmemoManager extends Manager { throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, InterruptedException, SmackException.NoResponseException, NoSuchAlgorithmException, SmackException.NotConnectedException, CryptoFailedException, CannotEstablishOmemoSessionException, IOException { - Message message = new Message(); - message.setFrom(getOwnJid()); - message.setTo(recipient.getJid()); + XMPPConnection connection = connection(); + MessageBuilder message = connection.getStanzaFactory() + .buildMessageStanza() + .to(recipient.getJid()); OmemoElement element = getOmemoService().createRatchetUpdateElement(new LoggedInOmemoManager(this), recipient); message.addExtension(element); // Set MAM Storage hint StoreHint.set(message); - connection().sendStanza(message); + connection.sendStanza(message.build()); } /** diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessage.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessage.java index 0bfa1847e..2d5554e7f 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessage.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessage.java @@ -25,6 +25,7 @@ import java.util.HashSet; import java.util.Set; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smackx.eme.element.ExplicitMessageEncryptionElement; import org.jivesoftware.smackx.hints.element.StoreHint; @@ -123,22 +124,23 @@ public class OmemoMessage { * as well as an optional clear text hint as body, a MAM storage hint * and an EME hint about OMEMO encryption. * + * @param messageBuilder a message builder which will be used to build the message. * @param recipient recipient for the to-field of the message. - * @return Message TODO javadoc me please + * @return the build message. */ - public Message asMessage(Jid recipient) { + public Message buildMessage(MessageBuilder messageBuilder, Jid recipient) { + messageBuilder.ofType(Message.Type.chat).to(recipient); - Message messageStanza = new Message(recipient, Message.Type.chat); - messageStanza.addExtension(getElement()); + messageBuilder.addExtension(getElement()); if (OmemoConfiguration.getAddOmemoHintBody()) { - messageStanza.setBody(BODY_OMEMO_HINT); + messageBuilder.setBody(BODY_OMEMO_HINT); } - StoreHint.set(messageStanza); - messageStanza.addExtension(new ExplicitMessageEncryptionElement(OMEMO_NAMESPACE_V_AXOLOTL, OMEMO)); + StoreHint.set(messageBuilder); + messageBuilder.addExtension(new ExplicitMessageEncryptionElement(OMEMO_NAMESPACE_V_AXOLOTL, OMEMO)); - return messageStanza; + return messageBuilder.build(); } } diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java index c5cac27e5..b5ace3d69 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java @@ -45,6 +45,7 @@ import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.StanzaError; + import org.jivesoftware.smackx.carbons.packet.CarbonExtension; import org.jivesoftware.smackx.mam.MamManager; import org.jivesoftware.smackx.muc.MultiUserChat; @@ -1343,10 +1344,13 @@ public abstract class OmemoServicesingletonList(mBody)); - OpenPgpMetadata metadata = addOxMessage(message, contact, Collections.singletonList(mBody)); - + Message message = messageBuilder.build(); ChatManager.getInstanceFor(connection()).chatWith(contact.getJid().asEntityBareJidIfPossible()).send(message); return metadata; @@ -241,7 +246,7 @@ public final class OXInstantMessagingManager extends Manager { /** * Add an OX-IM message element to a message. * - * @param message message + * @param messageBuilder a message builder. * @param contact recipient of the message * @param payload payload which will be encrypted and signed * @@ -251,15 +256,15 @@ public final class OXInstantMessagingManager extends Manager { * @throws PGPException in case something goes wrong during encryption * @throws IOException IO is dangerous (we need to read keys) */ - public OpenPgpMetadata addOxMessage(Message message, OpenPgpContact contact, List payload) + public OpenPgpMetadata addOxMessage(MessageBuilder messageBuilder, OpenPgpContact contact, List payload) throws SmackException.NotLoggedInException, PGPException, IOException { - return addOxMessage(message, Collections.singleton(contact), payload); + return addOxMessage(messageBuilder, Collections.singleton(contact), payload); } /** * Add an OX-IM message element to a message. * - * @param message message + * @param messageBuilder message * @param contacts recipients of the message * @param payload payload which will be encrypted and signed * @@ -269,7 +274,7 @@ public final class OXInstantMessagingManager extends Manager { * @throws PGPException in case something goes wrong during encryption * @throws IOException IO is dangerous (we need to read keys) */ - public OpenPgpMetadata addOxMessage(Message message, Set contacts, List payload) + public OpenPgpMetadata addOxMessage(MessageBuilder messageBuilder, Set contacts, List payload) throws SmackException.NotLoggedInException, IOException, PGPException { HashSet recipients = new HashSet<>(contacts); @@ -277,13 +282,13 @@ public final class OXInstantMessagingManager extends Manager { recipients.add(self); OpenPgpElementAndMetadata openPgpElementAndMetadata = signAndEncrypt(recipients, payload); - message.addExtension(openPgpElementAndMetadata.getElement()); + messageBuilder.addExtension(openPgpElementAndMetadata.getElement()); // Set hints on message - ExplicitMessageEncryptionElement.set(message, + ExplicitMessageEncryptionElement.set(messageBuilder, ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.openpgpV0); - StoreHint.set(message); - setOXBodyHint(message); + StoreHint.set(messageBuilder); + setOXBodyHint(messageBuilder); return openPgpElementAndMetadata.getMetadata(); } @@ -349,7 +354,7 @@ public final class OXInstantMessagingManager extends Manager { * * @param message message */ - private static void setOXBodyHint(Message message) { + private static void setOXBodyHint(MessageBuilder message) { message.setBody("This message is encrypted using XEP-0374: OpenPGP for XMPP: Instant Messaging."); } diff --git a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManagerTest.java b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManagerTest.java index 85de7aae0..fbf33e6a3 100644 --- a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManagerTest.java +++ b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManagerTest.java @@ -34,6 +34,8 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.ExtensionElement; 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.util.StringUtils; import org.jivesoftware.smack.xml.XmlPullParserException; @@ -138,11 +140,13 @@ public class OXInstantMessagingManagerTest extends SmackTestSuite { assertFalse(aliceForBob.hasUndecidedKeys()); assertFalse(bobForAlice.hasUndecidedKeys()); - Message message = new Message(); - assertFalse(ExplicitMessageEncryptionElement.hasProtocol(message, ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.openpgpV0)); + MessageBuilder messageBuilder = StanzaBuilder.buildMessage(); + assertFalse(ExplicitMessageEncryptionElement.hasProtocol(messageBuilder.build(), ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.openpgpV0)); - aliceOxim.addOxMessage(message, bobForAlice, + aliceOxim.addOxMessage(messageBuilder, bobForAlice, Collections.singletonList(new Message.Body(null, "Hello World!"))); + + Message message = messageBuilder.build(); assertTrue(ExplicitMessageEncryptionElement.hasProtocol(message, ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.openpgpV0)); assertNotNull(OpenPgpElement.fromStanza(message)); diff --git a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java index 05f0096e7..9f73c42c5 100644 --- a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java @@ -95,8 +95,10 @@ public class Nio { connection.login(); - Message message = new Message("flo@geekplace.eu", - "It is alive! " + XmppDateTime.formatXEP0082Date(new Date())); + Message message = connection.getStanzaFactory().buildMessageStanza() + .to("flo@geekplace.eu") + .setBody("It is alive! " + XmppDateTime.formatXEP0082Date(new Date())) + .build(); connection.sendStanza(message); Thread.sleep(1000); diff --git a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/OmemoClient.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/OmemoClient.java index 7518ba18e..dc4b343e6 100644 --- a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/OmemoClient.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/OmemoClient.java @@ -36,6 +36,7 @@ import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotLoggedInException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; @@ -166,8 +167,9 @@ public class OmemoClient { BareJid recipient = JidCreate.bareFrom(com[1]); String body = com[2]; + MessageBuilder messageBuilder = connection.getStanzaFactory().buildMessageStanza(); try { - Message omemoMessage = omemoManager.encrypt(recipient, body).asMessage(recipient); + Message omemoMessage = omemoManager.encrypt(recipient, body).buildMessage(messageBuilder, recipient); connection.sendStanza(omemoMessage); } catch (UndecidedOmemoIdentityException e) { print("Undecided Identities!\n" + Arrays.toString(e.getUndecidedDevices().toArray())); diff --git a/smack-tcp/src/test/java/org/jivesoftware/smack/tcp/PacketWriterTest.java b/smack-tcp/src/test/java/org/jivesoftware/smack/tcp/PacketWriterTest.java index 940c8910f..9658b9f7f 100644 --- a/smack-tcp/src/test/java/org/jivesoftware/smack/tcp/PacketWriterTest.java +++ b/smack-tcp/src/test/java/org/jivesoftware/smack/tcp/PacketWriterTest.java @@ -31,7 +31,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.jivesoftware.smack.AbstractXMPPConnection; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException.NotConnectedException; -import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.tcp.XMPPTCPConnection.PacketWriter; import org.jivesoftware.smack.util.ExceptionUtil; @@ -80,7 +80,7 @@ public class PacketWriterTest { // full capacity. The +1 is because the writer thread will dequeue one stanza and try to write it into the // blocking writer. for (int i = 0; i < XMPPTCPConnection.PacketWriter.QUEUE_SIZE + 1; i++) { - pw.sendStreamElement(new Message()); + pw.sendStreamElement(StanzaBuilder.buildMessage().build()); } final CyclicBarrier barrier = new CyclicBarrier(2); @@ -93,7 +93,7 @@ public class PacketWriterTest { public void run() { try { barrier.await(); - pw.sendStreamElement(new Message()); + pw.sendStreamElement(StanzaBuilder.buildMessage().build()); // should only return after the pw was interrupted if (!shutdown) { prematureUnblocked = true;