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/resources/fix-a-javadoc.sh b/resources/fix-a-javadoc.sh index 07209cd22..6354147d6 100755 --- a/resources/fix-a-javadoc.sh +++ b/resources/fix-a-javadoc.sh @@ -28,17 +28,17 @@ SMACK_EXCEPTIONS[InterruptedException]="if the calling thread was interrupted." SMACK_EXCEPTIONS[XMPPErrorException]="if there was an XMPP error returned." SMACK_EXCEPTIONS[NoResponseException]="if there was no response from the remote entity." SMACK_EXCEPTIONS[NotLoggedInException]="if the XMPP connection is not authenticated." -SMACK_EXCEPTIONS[BOSHException]="if an BOSH related error occured." -SMACK_EXCEPTIONS[IOException]="if an I/O error occured." +SMACK_EXCEPTIONS[BOSHException]="if an BOSH related error occurred." +SMACK_EXCEPTIONS[IOException]="if an I/O error occurred." SMACK_EXCEPTIONS[SmackException]="if Smack detected an exceptional situation." SMACK_EXCEPTIONS[XMPPException]="if an XMPP protocol error was received." -SMACK_EXCEPTIONS[SmackSaslException]="if a SASL specific error occured." +SMACK_EXCEPTIONS[SmackSaslException]="if a SASL specific error occurred." SMACK_EXCEPTIONS[SASLErrorException]="if a SASL protocol error was returned." SMACK_EXCEPTIONS[NotAMucServiceException]="if the entity is not a MUC serivce." SMACK_EXCEPTIONS[NoSuchAlgorithmException]="if no such algorithm is available." SMACK_EXCEPTIONS[KeyManagementException]="if there was a key mangement error." SMACK_EXCEPTIONS[XmppStringprepException]="if the provided string is invalid." -SMACK_EXCEPTIONS[XmlPullParserException]="if an error in the XML parser occured." +SMACK_EXCEPTIONS[XmlPullParserException]="if an error in the XML parser occurred." SMACK_EXCEPTIONS[SmackParsingException]="if the Smack parser (provider) encountered invalid input." SMACK_EXCEPTIONS[MucNotJoinedException]="if not joined to the Multi-User Chat." SMACK_EXCEPTIONS[MucAlreadyJoinedException]="if already joined the Multi-User Chat."7y @@ -54,7 +54,7 @@ SMACK_EXCEPTIONS[IllegalArgumentException]="if an illegal argument was given." SMACK_EXCEPTIONS[NotAPubSubNodeException]="if a involved node is not a PubSub node." SMACK_EXCEPTIONS[NoAcceptableTransferMechanisms]="if no acceptable transfer mechanisms are available" SMACK_EXCEPTIONS[NoSuchMethodException]="if no such method is declared" -SMACK_EXCEPTIONS[Exception]="if an exception occured." +SMACK_EXCEPTIONS[Exception]="if an exception occurred." SMACK_EXCEPTIONS[TestNotPossibleException]="if the test is not possible." SMACK_EXCEPTIONS[TimeoutException]="if there was a timeout." SMACK_EXCEPTIONS[IllegalStateException]="if an illegal state was encountered" 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..4d344376d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -100,16 +100,22 @@ import org.jivesoftware.smack.packet.FullyQualifiedElement; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Mechanisms; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.MessageOrPresence; +import org.jivesoftware.smack.packet.MessageOrPresenceBuilder; import org.jivesoftware.smack.packet.Nonza; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.PresenceBuilder; import org.jivesoftware.smack.packet.Session; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.StanzaError; +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; @@ -121,11 +127,13 @@ import org.jivesoftware.smack.sasl.core.SASLAnonymous; import org.jivesoftware.smack.sasl.packet.SaslNonza; import org.jivesoftware.smack.util.Async; import org.jivesoftware.smack.util.CollectionUtil; +import org.jivesoftware.smack.util.Consumer; import org.jivesoftware.smack.util.DNSUtil; import org.jivesoftware.smack.util.MultiMap; import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.ParserUtils; +import org.jivesoftware.smack.util.Predicate; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.dns.HostAddress; import org.jivesoftware.smack.util.dns.SmackDaneProvider; @@ -241,6 +249,10 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { private final Map interceptors = new HashMap<>(); + private final Map, GenericInterceptorWrapper> messageInterceptors = new HashMap<>(); + + private final Map, GenericInterceptorWrapper> presenceInterceptors = new HashMap<>(); + private XmlEnvironment incomingStreamXmlEnvironment; protected XmlEnvironment outgoingStreamXmlEnvironment; @@ -402,6 +414,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 +454,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { for (ConnectionCreationListener listener : XMPPConnectionRegistry.getConnectionCreationListeners()) { listener.connectionCreated(this); } + + StanzaIdSource stanzaIdSource = configuration.constructStanzaIdSource(); + stanzaFactory = new StanzaFactory(stanzaIdSource); } /** @@ -518,7 +535,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { * * @throws XMPPException if an error occurs on the XMPP protocol level. * @throws SmackException if an error occurs somewhere else besides XMPP protocol level. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @return a reference to this object, to chain connect() with login(). * @throws InterruptedException if the calling thread was interrupted. */ @@ -558,7 +575,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { * login if the previous connection state was logged (authenticated). * * @throws SmackException if Smack detected an exceptional situation. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws XMPPException if an XMPP protocol error was received. * @throws InterruptedException if the calling thread was interrupted. */ @@ -611,7 +628,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { * @param password TODO javadoc me please * @throws XMPPException if an XMPP protocol error was received. * @throws SmackException if Smack detected an exceptional situation. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws InterruptedException if the calling thread was interrupted. * @see #login */ @@ -629,7 +646,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { * @param resource TODO javadoc me please * @throws XMPPException if an XMPP protocol error was received. * @throws SmackException if Smack detected an exceptional situation. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws InterruptedException if the calling thread was interrupted. * @see #login */ @@ -733,7 +750,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 +835,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"); @@ -833,8 +859,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } // Invoke interceptors for the new stanza that is about to be sent. Interceptors may modify // the content of the stanza. - firePacketInterceptors(stanza); - sendStanzaInternal(stanza); + Stanza stanzaAfterInterceptors = firePacketInterceptors(stanza); + sendStanzaInternal(stanzaAfterInterceptors); } /** @@ -847,9 +873,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { * @return the used SASLMechanism. * @throws XMPPErrorException if there was an XMPP error returned. * @throws SASLErrorException if a SASL protocol error was returned. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws InterruptedException if the calling thread was interrupted. - * @throws SmackSaslException if a SASL specific error occured. + * @throws SmackSaslException if a SASL specific error occurred. * @throws NotConnectedException if the XMPP connection is not connected. * @throws NoResponseException if there was no response from the remote entity. * @throws SmackWrappedException in case of an exception. @@ -893,7 +919,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); @@ -1186,6 +1214,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { }); } + @Deprecated @Override public void addStanzaInterceptor(StanzaListener packetInterceptor, StanzaFilter packetFilter) { @@ -1198,6 +1227,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } } + @Deprecated @Override public void removeStanzaInterceptor(StanzaListener packetInterceptor) { synchronized (interceptors) { @@ -1205,15 +1235,83 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } } + private static , MP extends MessageOrPresence> void addInterceptor( + Map, GenericInterceptorWrapper> interceptors, Consumer interceptor, + Predicate filter) { + Objects.requireNonNull(interceptor, "Interceptor must not be null"); + + GenericInterceptorWrapper interceptorWrapper = new GenericInterceptorWrapper<>(interceptor, filter); + + synchronized (interceptors) { + interceptors.put(interceptor, interceptorWrapper); + } + } + + private static , MP extends MessageOrPresence> void removeInterceptor( + Map, GenericInterceptorWrapper> interceptors, Consumer interceptor) { + synchronized (interceptors) { + interceptors.remove(interceptor); + } + } + + @Override + public void addMessageInterceptor(Consumer messageInterceptor, Predicate messageFilter) { + addInterceptor(messageInterceptors, messageInterceptor, messageFilter); + } + + @Override + public void removeMessageInterceptor(Consumer messageInterceptor) { + removeInterceptor(messageInterceptors, messageInterceptor); + } + + @Override + public void addPresenceInterceptor(Consumer presenceInterceptor, + Predicate presenceFilter) { + addInterceptor(presenceInterceptors, presenceInterceptor, presenceFilter); + } + + @Override + public void removePresenceInterceptor(Consumer presenceInterceptor) { + removeInterceptor(presenceInterceptors, presenceInterceptor); + } + + private static , MP extends MessageOrPresence> MP fireMessageOrPresenceInterceptors( + MP messageOrPresence, Map, GenericInterceptorWrapper> interceptors) { + List> interceptorsToInvoke = new LinkedList<>(); + synchronized (interceptors) { + for (GenericInterceptorWrapper interceptorWrapper : interceptors.values()) { + if (interceptorWrapper.filterMatches(messageOrPresence)) { + Consumer interceptor = interceptorWrapper.getInterceptor(); + interceptorsToInvoke.add(interceptor); + } + } + } + + // Avoid transforming the stanza to a builder if there is no interceptor. + if (interceptorsToInvoke.isEmpty()) { + return messageOrPresence; + } + + MPB builder = messageOrPresence.asBuilder(); + for (Consumer interceptor : interceptorsToInvoke) { + interceptor.accept(builder); + } + + // Now that the interceptors have (probably) modified the stanza in its builder form, we need to re-assemble it. + messageOrPresence = builder.build(); + return messageOrPresence; + } + /** * Process interceptors. Interceptors may modify the stanza that is about to be sent. * Since the thread that requested to send the stanza will invoke all interceptors, it * is important that interceptors perform their work as soon as possible so that the * thread does not remain blocked for a long period. * - * @param packet the stanza that is going to be sent to the server + * @param packet the stanza that is going to be sent to the server. + * @return the, potentially modified stanza, after the interceptors are run. */ - private void firePacketInterceptors(Stanza packet) { + private Stanza firePacketInterceptors(Stanza packet) { List interceptorsToInvoke = new LinkedList<>(); synchronized (interceptors) { for (InterceptorWrapper interceptorWrapper : interceptors.values()) { @@ -1229,6 +1327,22 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { LOGGER.log(Level.SEVERE, "Packet interceptor threw exception", e); } } + + final Stanza stanzaAfterInterceptors; + if (packet instanceof Message) { + Message message = (Message) packet; + stanzaAfterInterceptors = fireMessageOrPresenceInterceptors(message, messageInterceptors); + } + else if (packet instanceof Presence) { + Presence presence = (Presence) packet; + stanzaAfterInterceptors = fireMessageOrPresenceInterceptors(presence, presenceInterceptors); + } else { + // We do not (yet) support interceptors for IQ stanzas. + assert packet instanceof IQ; + stanzaAfterInterceptors = packet; + } + + return stanzaAfterInterceptors; } /** @@ -1416,7 +1530,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(() -> { @@ -1656,6 +1770,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { /** * A wrapper class to associate a stanza filter with an interceptor. */ + @Deprecated + // TODO: Remove once addStanzaInterceptor is gone. protected static class InterceptorWrapper { private final StanzaListener packetInterceptor; @@ -1681,6 +1797,24 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } } + private static final class GenericInterceptorWrapper, MP extends MessageOrPresence> { + private final Consumer stanzaInterceptor; + private final Predicate stanzaFilter; + + private GenericInterceptorWrapper(Consumer stanzaInterceptor, Predicate stanzaFilter) { + this.stanzaInterceptor = stanzaInterceptor; + this.stanzaFilter = stanzaFilter; + } + + private boolean filterMatches(MP stanza) { + return stanzaFilter == null || stanzaFilter.test(stanza); + } + + public Consumer getInterceptor() { + return stanzaInterceptor; + } + } + @Override public int getConnectionCounter() { return connectionCounterValue; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AsyncButOrdered.java b/smack-core/src/main/java/org/jivesoftware/smack/AsyncButOrdered.java index 6fb6244ab..526e3cd2e 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AsyncButOrdered.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AsyncButOrdered.java @@ -1,6 +1,6 @@ /** * - * Copyright 2018 Florian Schmaus + * Copyright 2018-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,6 +16,7 @@ */ package org.jivesoftware.smack; +import java.util.HashMap; import java.util.Map; import java.util.Queue; import java.util.WeakHashMap; @@ -51,9 +52,17 @@ import java.util.concurrent.Executor; */ public class AsyncButOrdered { + /** + * A map with the currently pending runnables for a given key. Note that this is a weak hash map so we do not have + * to take care of removing the keys ourselfs from the map. + */ private final Map> pendingRunnables = new WeakHashMap<>(); - private final Map threadActiveMap = new WeakHashMap<>(); + /** + * A marker map if there is an active thread for the given key. Holds the responsible handler thread if one is + * active, otherwise the key is non-existend in the map. + */ + private final Map threadActiveMap = new HashMap<>(); private final Executor executor; @@ -65,6 +74,14 @@ public class AsyncButOrdered { this.executor = executor; } + private void scheduleHandler(Handler handler) { + if (executor == null) { + AbstractXMPPConnection.asyncGo(handler); + } else { + executor.execute(handler); + } + } + /** * Invoke the given {@link Runnable} asynchronous but ordered in respect to the given key. * @@ -73,6 +90,7 @@ public class AsyncButOrdered { * @return true if a new thread was created */ public boolean performAsyncButOrdered(K key, Runnable runnable) { + // First check if a key queue already exists, create one if not. Queue keyQueue; synchronized (pendingRunnables) { keyQueue = pendingRunnables.get(key); @@ -82,29 +100,27 @@ public class AsyncButOrdered { } } + // Then add the task to the queue. keyQueue.add(runnable); - boolean newHandler; + // Finally check if there is already a handler working on that queue, create one if not. + Handler newlyCreatedHandler = null; synchronized (threadActiveMap) { - Boolean threadActive = threadActiveMap.get(key); - if (threadActive == null) { - threadActive = false; - threadActiveMap.put(key, threadActive); - } + if (!threadActiveMap.containsKey(key)) { + newlyCreatedHandler = new Handler(keyQueue, key); - newHandler = !threadActive; - if (newHandler) { - Handler handler = new Handler(keyQueue, key); - threadActiveMap.put(key, true); - if (executor == null) { - AbstractXMPPConnection.asyncGo(handler); - } else { - executor.execute(handler); - } + // Mark that there is thread active for the given key. Note that this has to be done before scheduling + // the handler thread. + threadActiveMap.put(key, newlyCreatedHandler); } } - return newHandler; + if (newlyCreatedHandler != null) { + scheduleHandler(newlyCreatedHandler); + return true; + } + + return false; } public Executor asExecutorFor(final K key) { @@ -134,11 +150,14 @@ public class AsyncButOrdered { try { runnable.run(); } catch (Throwable t) { - // The run() method threw, this handler thread is going to terminate because of that. Ensure we note - // that in the map. + // The run() method threw, this handler thread is going to terminate because of that. We create + // a new handler to continue working on the queue while throwing the throwable so that the + // executor can handle it. + Handler newlyCreatedHandler = new Handler(keyQueue, key); synchronized (threadActiveMap) { - threadActiveMap.put(key, false); + threadActiveMap.put(key, newlyCreatedHandler); } + scheduleHandler(newlyCreatedHandler); throw t; } } @@ -146,7 +165,7 @@ public class AsyncButOrdered { synchronized (threadActiveMap) { // If the queue is empty, stop this handler, otherwise continue looping. if (keyQueue.isEmpty()) { - threadActiveMap.put(key, false); + threadActiveMap.remove(key); break mainloop; } } 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/SASLAuthentication.java b/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java index 91018d6d8..6c1c31a5d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java @@ -175,9 +175,9 @@ public final class SASLAuthentication { * @return the used SASLMechanism. * @throws XMPPErrorException if there was an XMPP error returned. * @throws SASLErrorException if a SASL protocol error was returned. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws InterruptedException if the calling thread was interrupted. - * @throws SmackSaslException if a SASL specific error occured. + * @throws SmackSaslException if a SASL specific error occurred. * @throws NotConnectedException if the XMPP connection is not connected. * @throws NoResponseException if there was no response from the remote entity. */ @@ -233,7 +233,7 @@ public final class SASLAuthentication { * * @param challenge a base64 encoded string representing the challenge. * @param finalChallenge true if this is the last challenge send by the server within the success stanza - * @throws SmackSaslException if a SASL specific error occured. + * @throws SmackSaslException if a SASL specific error occurred. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ @@ -252,7 +252,7 @@ public final class SASLAuthentication { * @throws SmackException if Smack detected an exceptional situation. * @throws InterruptedException if the calling thread was interrupted. * @throws NotConnectedException if the XMPP connection is not connected. - * @throws SmackSaslException if a SASL specific error occured. + * @throws SmackSaslException if a SASL specific error occurred. */ void authenticated(Success success) throws InterruptedException, SmackSaslException, NotConnectedException { // RFC6120 6.3.10 "At the end of the authentication exchange, the SASL server (the XMPP 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..842007f1e 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java @@ -27,8 +27,15 @@ import org.jivesoftware.smack.iqrequest.IQRequestHandler; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.FullyQualifiedElement; import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Nonza; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.PresenceBuilder; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaFactory; +import org.jivesoftware.smack.util.Consumer; +import org.jivesoftware.smack.util.Predicate; import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.EntityFullJid; @@ -178,6 +185,8 @@ public interface XMPPConnection { */ boolean isUsingCompression(); + StanzaFactory getStanzaFactory(); + /** * Sends the specified stanza to the server. * @@ -358,7 +367,7 @@ public interface XMPPConnection { boolean removeStanzaListener(StanzaListener stanzaListener); /** - * Registers a synchronous stanza listener with this connection. A stanza listener will be invoked only when + * Registers a synchronous stanza listener with this connection. A stanza listener will be invoked only when * an incoming stanza is received. A stanza filter determines which stanzas will be delivered to the listener. If * the same stanza listener is added again with a different filter, only the new filter will be used. *

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

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

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

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

+ * + * @param presenceInterceptor the stanza interceptor to notify of stanzas about to be sent. + * @param presenceFilter the stanza filter to use. + */ + void addPresenceInterceptor(Consumer presenceInterceptor, Predicate presenceFilter); + + /** + * Removes a presence interceptor. + * + * @param presenceInterceptor the stanza interceptor to remove. + */ + void removePresenceInterceptor(Consumer presenceInterceptor); /** * Returns the current value of the reply timeout in milliseconds for request for this * XMPPConnection instance. diff --git a/smack-core/src/main/java/org/jivesoftware/smack/compress/provider/CompressedProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/compress/provider/CompressedProvider.java index fbed9abd3..c8a4cc02d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/compress/provider/CompressedProvider.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/compress/provider/CompressedProvider.java @@ -19,7 +19,6 @@ package org.jivesoftware.smack.compress.provider; import org.jivesoftware.smack.compress.packet.Compressed; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.provider.NonzaProvider; - import org.jivesoftware.smack.xml.XmlPullParser; public final class CompressedProvider extends NonzaProvider { 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/compression/Java7ZlibInputOutputStream.java b/smack-core/src/main/java/org/jivesoftware/smack/compression/Java7ZlibInputOutputStream.java index b5e190a73..fd71d90ef 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/compression/Java7ZlibInputOutputStream.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/compression/Java7ZlibInputOutputStream.java @@ -76,7 +76,7 @@ public class Java7ZlibInputOutputStream extends XMPPInputOutputStream { * byte without blocking, 0 means that the system is known to block for more input. * * @return 0 if no data is available, 1 otherwise - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ @Override public int available() throws IOException { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java b/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java index db0d1da72..f37d08b11 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java @@ -18,6 +18,7 @@ package org.jivesoftware.smack.filter; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.util.Predicate; /** * Defines a way to filter stanzas for particular attributes. Stanza filters are used when @@ -51,7 +52,7 @@ import org.jivesoftware.smack.packet.Stanza; * @see org.jivesoftware.smack.StanzaListener * @author Matt Tucker */ -public interface StanzaFilter { +public interface StanzaFilter extends Predicate { /** * Tests whether or not the specified stanza should pass the filter. @@ -60,4 +61,9 @@ public interface StanzaFilter { * @return true if and only if stanza passes the filter. */ boolean accept(Stanza stanza); + + @Override + default boolean test(Stanza stanza) { + return accept(stanza); + } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractIqBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractIqBuilder.java new file mode 100644 index 000000000..d975db0ef --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractIqBuilder.java @@ -0,0 +1,69 @@ +/** + * + * 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; +import org.jivesoftware.smack.util.ToStringUtil; + +public abstract class AbstractIqBuilder> extends StanzaBuilder implements IqView { + + protected IQ.Type type = IQ.Type.get; + + AbstractIqBuilder(AbstractIqBuilder other) { + super(other); + type = other.type; + } + + AbstractIqBuilder(StanzaIdSource stanzaIdSource) { + super(stanzaIdSource); + } + + AbstractIqBuilder(String stanzaId) { + super(stanzaId); + } + + public static IqData createResponse(IqView request) { + return createResponse(request, IQ.ResponseType.result); + } + + public static IqData createErrorResponse(IqView request) { + return createResponse(request, IQ.ResponseType.error); + } + + protected static IqData createResponse(IqView request, IQ.ResponseType responseType) { + if (!(request.getType() == IQ.Type.get || request.getType() == IQ.Type.set)) { + throw new IllegalArgumentException("IQ request must be of type 'set' or 'get'. Original IQ: " + request); + } + + IqData commonResponseIqData = buildResponse(request, s -> { + return StanzaBuilder.buildIqData(s); + }); + commonResponseIqData.ofType(responseType.getType()); + + return commonResponseIqData; + } + + @Override + protected final void addStanzaSpecificAttributes(ToStringUtil.Builder builder) { + builder.addValue("type", getType()); + } + + @Override + public final IQ.Type getType() { + return type; + } +} 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..248f0ebaa 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(IqData 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(AbstractIqBuilder.createResponse(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..0f412b602 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,7 +54,7 @@ public abstract class IQ extends Stanza { private Type type = Type.get; - public IQ(IQ iq) { + protected IQ(IQ iq) { super(iq); type = iq.getType(); this.childElementName = iq.childElementName; @@ -62,7 +62,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(IqData.EMPTY, childElementName, childElementNamespace); + } + + protected IQ(AbstractIqBuilder iqBuilder, String childElementName, String childElementNamespace) { + super(iqBuilder); + + type = iqBuilder.type; + this.childElementName = childElementName; this.childElementNamespace = childElementNamespace; if (childElementName == null) { @@ -72,11 +81,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 +95,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 +266,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 +304,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 +314,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:
    - *
  • The sender set to the recipient of the originating IQ. - *
  • The recipient set to the sender of the originating IQ. - *
  • The type set to {@link Type#error IQ.Type.error}. - *
  • The id set to the id of the originating IQ. - *
  • The child element contained in the associated originating IQ. - *
  • The provided {@link StanzaError XMPPError}. - *
- * - * @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()); } /** @@ -392,6 +375,25 @@ public abstract class IQ extends Stanza { } } + public enum ResponseType { + + result(Type.result), + + error(Type.error), + + ; + + final Type type; + + ResponseType(Type type) { + this.type = type; + } + + Type getType() { + return type; + } + } + public static class IQChildElementXmlStringBuilder extends XmlStringBuilder { private final String element; 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..2e24f53b2 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/IqBuilder.java @@ -0,0 +1,44 @@ +/** + * + * 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.XMPPConnection; +import org.jivesoftware.smack.util.Objects; + +public abstract class IqBuilder, I extends IQ> + extends AbstractIqBuilder { + + protected IqBuilder(AbstractIqBuilder other) { + super(other); + } + + protected IqBuilder(XMPPConnection connection) { + super(connection.getStanzaFactory().getStanzaIdSource()); + } + + protected IqBuilder(String stanzaId) { + super(stanzaId); + } + + public IB ofType(IQ.Type type) { + this.type = Objects.requireNonNull(type); + return getThis(); + } + + public abstract I build(); + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/IqData.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/IqData.java new file mode 100644 index 000000000..deba5486e --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/IqData.java @@ -0,0 +1,44 @@ +/** + * + * 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.StandardStanzaIdSource; +import org.jivesoftware.smack.packet.id.StanzaIdSource; +import org.jivesoftware.smack.util.Objects; + +public final class IqData extends AbstractIqBuilder { + + static final IqData EMPTY = new IqData(StandardStanzaIdSource.DEFAULT); + + IqData(StanzaIdSource stanzaIdSource) { + super(stanzaIdSource); + } + + IqData(String stanzaId) { + super(stanzaId); + } + + public IqData ofType(IQ.Type type) { + this.type = Objects.requireNonNull(type); + return getThis(); + } + + @Override + public IqData getThis() { + return this; + } +} 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..58d69da59 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java @@ -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,8 @@ import org.jxmpp.stringprep.XmppStringprepException; * * @author Matt Tucker */ -public final class Message extends Stanza implements TypedCloneable { +public final class Message extends MessageOrPresence + implements MessageView, TypedCloneable { public static final String ELEMENT = "message"; public static final String BODY = "body"; @@ -66,11 +69,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 +82,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 +95,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 +109,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 +124,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 +138,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 +166,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 +180,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 +217,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 +233,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 +246,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 +266,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 +289,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 +307,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 +321,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 +390,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 +408,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 +428,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 +447,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 +469,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 +510,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 +535,11 @@ public final class Message extends Stanza implements TypedCloneable { return ELEMENT; } + @Override + public MessageBuilder asBuilder() { + return StanzaBuilder.buildMessageFrom(this, getStanzaId()); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -491,18 +559,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 +593,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."); } @@ -608,6 +666,7 @@ public final class Message extends Stanza implements TypedCloneable { public static final String ELEMENT = "body"; public static final String NAMESPACE = StreamOpen.CLIENT_NAMESPACE; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); enum BodyElementNamespace { client(StreamOpen.CLIENT_NAMESPACE), diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageBuilder.java new file mode 100644 index 000000000..027e2b0cc --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageBuilder.java @@ -0,0 +1,165 @@ +/** + * + * 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 MessageOrPresenceBuilder 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; + } + + @Override + 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/MessageOrPresence.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresence.java new file mode 100644 index 000000000..c885e941c --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresence.java @@ -0,0 +1,36 @@ +/** + * + * Copyright 2019 Florian Schmaus + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smack.packet; + +public abstract class MessageOrPresence> extends Stanza { + + @Deprecated + // TODO: Remove in Smack 4.5. + protected MessageOrPresence() { + } + + protected MessageOrPresence(StanzaBuilder stanzaBuilder) { + super(stanzaBuilder); + } + + protected MessageOrPresence(Stanza other) { + super(other); + } + + public abstract MPB asBuilder(); + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresenceBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresenceBuilder.java new file mode 100644 index 000000000..9a3ff66a0 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresenceBuilder.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2019 Florian Schmaus + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smack.packet; + +import org.jivesoftware.smack.packet.id.StanzaIdSource; + +public abstract class MessageOrPresenceBuilder>, SB extends StanzaBuilder> + extends StanzaBuilder { + + protected MessageOrPresenceBuilder(Stanza stanza, StanzaIdSource stanzaIdSource) { + super(stanza, stanzaIdSource); + } + + protected MessageOrPresenceBuilder(Stanza stanza, String stanzaId) { + super(stanza, stanzaId); + } + + protected MessageOrPresenceBuilder(StanzaIdSource stanzaIdSource) { + super(stanzaIdSource); + } + + protected MessageOrPresenceBuilder(String stanzaId) { + super(stanzaId); + } + + public abstract MP build(); + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/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..9a1d1a43d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java @@ -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,8 @@ import org.jxmpp.jid.Jid; * * @author Matt Tucker */ -public final class Presence extends Stanza implements TypedCloneable { +public final class Presence extends MessageOrPresence + implements PresenceView, TypedCloneable { public static final String ELEMENT = "presence"; @@ -81,7 +83,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 +99,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 +115,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 +128,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 +182,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 +191,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 +209,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 +236,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 +252,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 +265,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 +278,11 @@ public final class Presence extends Stanza implements TypedCloneable { return ELEMENT; } + @Override + public PresenceBuilder asBuilder() { + return StanzaBuilder.buildPresenceFrom(this, getStanzaId()); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -326,7 +348,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..9c34fb89c --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/PresenceBuilder.java @@ -0,0 +1,141 @@ +/** + * + * 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 MessageOrPresenceBuilder 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; + } + + @Override + 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..f230949fd 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(IqData 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..b4bdd6aba 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,31 +90,47 @@ 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. - */ - public String getStanzaId() { + @Override + public final String getStanzaId() { return id; } @@ -127,7 +153,7 @@ public abstract class Stanza implements TopLevelStreamElement { * @return true if the stanza ID is set, false otherwise. * @since 4.1 */ - public boolean hasStanzaIdSet() { + public final boolean hasStanzaIdSet() { // setStanzaId ensures that the id is either null or not empty, // so we can assume that it is set if it's not null. return id != null; @@ -138,57 +164,51 @@ 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 Jid getTo() { + 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 final Jid getTo() { return to; } @@ -198,19 +218,13 @@ 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. - */ - public Jid getFrom() { + @Override + public final Jid getFrom() { return from; } @@ -221,35 +235,39 @@ 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. - */ - public StanzaError getError() { + @Override + public final StanzaError getError() { return error; } /** * 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 - public String getLanguage() { + public final String getLanguage() { return language; } @@ -257,23 +275,32 @@ 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. - */ - public List getExtensions() { + @Override + public final List getExtensions() { synchronized (extensionElements) { // No need to create a new list, values() will already create a new one for us return extensionElements.values(); } } + 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. *

@@ -285,11 +312,27 @@ public abstract class Stanza implements TopLevelStreamElement { * @return a set of all matching extensions. * @since 4.1 */ - public List getExtensions(String elementName, String namespace) { + public final List getExtensions(String elementName, String namespace) { 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 final List getExtensions(QName qname) { + List res; + synchronized (extensionElements) { + res = extensionElements.getAll(qname); + } + return Collections.unmodifiableList(res); + } + + @Override + public final List getExtensions(Class extensionElementClass) { + synchronized (extensionElements) { + return XmppElementUtil.getElementsFrom(extensionElements, extensionElementClass); + } } /** @@ -301,7 +344,7 @@ public abstract class Stanza implements TopLevelStreamElement { * @param namespace the namespace of the extension that is desired. * @return the stanza extension with the given namespace. */ - public ExtensionElement getExtension(String namespace) { + public final ExtensionElement getExtension(String namespace) { return PacketUtil.extensionElementFrom(getExtensions(), null, namespace); } @@ -317,27 +360,37 @@ public abstract class Stanza implements TopLevelStreamElement { * @return the extension, or null if it doesn't exist. */ @SuppressWarnings("unchecked") - public PE getExtension(String elementName, String namespace) { + public final PE getExtension(String elementName, String namespace) { if (namespace == null) { 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. */ - public void addExtension(ExtensionElement extension) { + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. + public final void addExtension(ExtensionElement extension) { if (extension == null) return; QName key = extension.getQName(); synchronized (extensionElements) { @@ -348,12 +401,17 @@ 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 */ - public ExtensionElement overrideExtension(ExtensionElement extension) { + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. + public final ExtensionElement overrideExtension(ExtensionElement extension) { if (extension == null) return null; synchronized (extensionElements) { // Note that we need to use removeExtension(String, String) here. If would use @@ -370,7 +428,8 @@ public abstract class Stanza implements TopLevelStreamElement { * * @param extensions a collection of stanza extensions */ - public void addExtensions(Collection extensions) { + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. + public final void addExtensions(Collection extensions) { if (extensions == null) return; for (ExtensionElement packetExtension : extensions) { addExtension(packetExtension); @@ -387,7 +446,7 @@ public abstract class Stanza implements TopLevelStreamElement { * @param namespace TODO javadoc me please * @return true if a stanza extension exists, false otherwise. */ - public boolean hasExtension(String elementName, String namespace) { + public final boolean hasExtension(String elementName, String namespace) { if (elementName == null) { return hasExtension(namespace); } @@ -397,13 +456,9 @@ public abstract class Stanza implements TopLevelStreamElement { } } - /** - * Check if a stanza extension with the given namespace exists. - * - * @param namespace TODO javadoc me please - * @return true if a stanza extension exists, false otherwise. - */ - public boolean hasExtension(String namespace) { + // Overridden in order to avoid an extra copy. + @Override + public final boolean hasExtension(String namespace) { synchronized (extensionElements) { for (ExtensionElement packetExtension : extensionElements.values()) { if (packetExtension.getNamespace().equals(namespace)) { @@ -421,7 +476,8 @@ public abstract class Stanza implements TopLevelStreamElement { * @param namespace TODO javadoc me please * @return the removed stanza extension or null. */ - public ExtensionElement removeExtension(String elementName, String namespace) { + // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. + public final ExtensionElement removeExtension(String elementName, String namespace) { QName key = new QName(namespace, elementName); synchronized (extensionElements) { return extensionElements.remove(key); @@ -433,8 +489,11 @@ 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. */ - public ExtensionElement removeExtension(ExtensionElement extension) { + @Deprecated + // TODO: Remove in Smack 4.5. + public final ExtensionElement removeExtension(ExtensionElement extension) { QName key = extension.getQName(); synchronized (extensionElements) { List list = extensionElements.getAll(key); @@ -494,7 +553,7 @@ public abstract class Stanza implements TopLevelStreamElement { * * @param xml the XmlStringBuilder to append the error to. */ - protected void appendErrorIfExists(XmlStringBuilder xml) { + protected final void appendErrorIfExists(XmlStringBuilder xml) { StanzaError error = getError(); if (error != null) { xml.append(error); 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..3539d22bd --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaBuilder.java @@ -0,0 +1,306 @@ +/** + * + * 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.id.StanzaIdSource; +import org.jivesoftware.smack.util.Function; +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(StanzaBuilder other) { + stanzaIdSource = other.stanzaIdSource; + stanzaId = other.stanzaId; + + to = other.to; + from = other.from; + stanzaError = other.stanzaError; + language = other.language; + extensionElements = other.extensionElements.clone(); + } + + 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 IqData buildIqData(String stanzaId) { + return new IqData(stanzaId); + } + + public static > SB buildResponse(StanzaView request, Function builderFromStanzaId) { + SB responseBuilder = builderFromStanzaId.apply(request.getStanzaId()); + + responseBuilder.to(request.getFrom()) + .from(request.getTo()) + ; + + return responseBuilder; + } + +} 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..9f69ee638 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaFactory.java @@ -0,0 +1,53 @@ +/** + * + * 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; + + StanzaIdSource getStanzaIdSource() { + return 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 IqData buildIqData() { + return new IqData(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..ff9874f13 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaView.java @@ -0,0 +1,102 @@ +/** + * + * 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); + + default boolean hasExtension(QName qname) { + return getExtension(qname) != null; + } + + /** + * Check if a extension element with the given namespace exists. + * + * @param namespace the namespace of the extension element to check for. + * @return true if a stanza extension exists, false otherwise. + */ + default boolean hasExtension(String namespace) { + for (ExtensionElement packetExtension : getExtensions()) { + if (packetExtension.getNamespace().equals(namespace)) { + return true; + } + } + + return false; + } + + @SuppressWarnings("unchecked") + default E getExtension(Class extensionElementClass) { + QName qname = XmppElementUtil.getQNameFor(extensionElementClass); + 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/StartTls.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StartTls.java index 3da2c3a53..aebb1ad3f 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/StartTls.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StartTls.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2018 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. @@ -52,9 +52,15 @@ public class StartTls implements Nonza { @Override public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) { XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace); - xml.rightAngleBracket(); - xml.condEmptyElement(required, "required"); - xml.closeElement(this); + + if (required) { + xml.rightAngleBracket(); + xml.emptyElement("required"); + xml.closeElement(this); + } else { + xml.closeEmptyElement(); + } + return xml; } 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/parsing/ParsingExceptionCallback.java b/smack-core/src/main/java/org/jivesoftware/smack/parsing/ParsingExceptionCallback.java index e5b3c1b4d..c2fda0d4d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/parsing/ParsingExceptionCallback.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/parsing/ParsingExceptionCallback.java @@ -39,7 +39,7 @@ public interface ParsingExceptionCallback { * Called when parsing a stanza caused an exception. * * @param stanzaData the raw stanza data that caused the exception - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ void handleUnparsableStanza(UnparseableStanza stanzaData) throws IOException; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/parsing/StandardExtensionElementProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/parsing/StandardExtensionElementProvider.java index cceaf4216..607c64198 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/parsing/StandardExtensionElementProvider.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/parsing/StandardExtensionElementProvider.java @@ -25,7 +25,6 @@ import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.provider.ExtensionElementProvider; import org.jivesoftware.smack.util.ParserUtils; import org.jivesoftware.smack.util.StringUtils; - import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/AbstractProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/AbstractProvider.java new file mode 100644 index 000000000..5eda3b494 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/AbstractProvider.java @@ -0,0 +1,45 @@ +/** + * + * 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.provider; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import org.jivesoftware.smack.packet.Element; + +public class AbstractProvider { + + private final Class elementClass; + + @SuppressWarnings("unchecked") + protected AbstractProvider() { + Type currentType = getClass().getGenericSuperclass(); + while (!(currentType instanceof ParameterizedType)) { + Class currentClass = (Class) currentType; + currentType = currentClass.getGenericSuperclass(); + } + ParameterizedType parameterizedGenericSuperclass = (ParameterizedType) currentType; + Type[] actualTypeArguments = parameterizedGenericSuperclass.getActualTypeArguments(); + Type elementType = actualTypeArguments[0]; + + elementClass = (Class) elementType; + } + + public final Class getElementClass() { + return elementClass; + } +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/BodyElementProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/BodyElementProvider.java index df85d067c..80a33781c 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/BodyElementProvider.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/BodyElementProvider.java @@ -23,7 +23,6 @@ import java.io.IOException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.util.ParserUtils; - import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/EmbeddedExtensionProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/EmbeddedExtensionProvider.java index 40ab16fb5..995751211 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/EmbeddedExtensionProvider.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/EmbeddedExtensionProvider.java @@ -26,7 +26,6 @@ import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.util.PacketParserUtils; - import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/IQProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/IQProvider.java index 66e7aa0f1..d0e1f8fc3 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/IQProvider.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/IQProvider.java @@ -17,15 +17,53 @@ package org.jivesoftware.smack.provider; +import java.io.IOException; + import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.parsing.SmackParsingException; +import org.jivesoftware.smack.util.ParserUtils; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; /** + *

+ * Deprecation Notice: This class is deprecated, use {@link IQProvider} instead. + *

* An abstract class for parsing custom IQ packets. Each IQProvider must be registered with * the ProviderManager class for it to be used. Every implementation of this * abstract class must have a public, no-argument constructor. * * @author Matt Tucker */ -public abstract class IQProvider extends Provider { +public abstract class IQProvider extends IqProvider { + + public final I parse(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException { + return parse(parser, (XmlEnvironment) null); + } + + public final I parse(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws IOException, XmlPullParserException, SmackParsingException { + // XPP3 calling convention assert: Parser should be at start tag + ParserUtils.assertAtStartTag(parser); + + final int initialDepth = parser.getDepth(); + final XmlEnvironment xmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment); + + I e = parse(parser, initialDepth, xmlEnvironment); + + // XPP3 calling convention assert: Parser should be at end tag of the consumed/parsed element + ParserUtils.forwardToEndTagOfDepth(parser, initialDepth); + return e; + } + + @Override + public final I parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment) + throws XmlPullParserException, IOException, SmackParsingException { + // Old-style IQ parsers do not need IqData. + return parse(parser, initialDepth, xmlEnvironment); + } + + public abstract I parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/IQProviderInfo.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/IQProviderInfo.java index abb14a62f..ec9baee99 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/IQProviderInfo.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/IQProviderInfo.java @@ -34,7 +34,7 @@ public final class IQProviderInfo extends AbstractProviderInfo { * @param namespace Namespace that provider parses. * @param iqProvider The provider implementation. */ - public IQProviderInfo(String elementName, String namespace, IQProvider iqProvider) { + public IQProviderInfo(String elementName, String namespace, IqProvider iqProvider) { super(elementName, namespace, iqProvider); } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/IntrospectionProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/IntrospectionProvider.java index a4c58f406..2f3df5724 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/IntrospectionProvider.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/IntrospectionProvider.java @@ -23,7 +23,6 @@ import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.util.ParserUtils; - import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/IqProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/IqProvider.java new file mode 100644 index 000000000..14ceecd15 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/IqProvider.java @@ -0,0 +1,46 @@ +/** + * + * 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.provider; + +import java.io.IOException; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; +import org.jivesoftware.smack.packet.XmlEnvironment; +import org.jivesoftware.smack.parsing.SmackParsingException; +import org.jivesoftware.smack.xml.XmlPullParser; +import org.jivesoftware.smack.xml.XmlPullParserException; + +public abstract class IqProvider extends AbstractProvider { + + public final I parse(XmlPullParser parser, IqData iqCommon) + throws XmlPullParserException, IOException, SmackParsingException { + return parse(parser, iqCommon, null); + } + + public final I parse(XmlPullParser parser, IqData iqData, XmlEnvironment outerXmlEnvironment) + throws XmlPullParserException, IOException, SmackParsingException { + final int initialDepth = parser.getDepth(); + final XmlEnvironment xmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment); + + return parse(parser, initialDepth, iqData, xmlEnvironment); + } + + public abstract I parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment) + throws XmlPullParserException, IOException, SmackParsingException; + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/Provider.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/Provider.java index ef1a225d9..b41ae7161 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/Provider.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/Provider.java @@ -18,14 +18,11 @@ package org.jivesoftware.smack.provider; import java.io.IOException; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; import org.jivesoftware.smack.packet.Element; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.util.ParserUtils; - import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; @@ -40,27 +37,7 @@ import org.jivesoftware.smack.xml.XmlPullParserException; * @author Florian Schmaus * @param the type of the resulting element. */ -public abstract class Provider { - - private final Class elementClass; - - @SuppressWarnings("unchecked") - protected Provider() { - Type currentType = getClass().getGenericSuperclass(); - while (!(currentType instanceof ParameterizedType)) { - Class currentClass = (Class) currentType; - currentType = currentClass.getGenericSuperclass(); - } - ParameterizedType parameterizedGenericSuperclass = (ParameterizedType) currentType; - Type[] actualTypeArguments = parameterizedGenericSuperclass.getActualTypeArguments(); - Type elementType = actualTypeArguments[0]; - - elementClass = (Class) elementType; - } - - public final Class getElementClass() { - return elementClass; - } +public abstract class Provider extends AbstractProvider { public final E parse(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException { return parse(parser, null); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderFileLoader.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderFileLoader.java index e39f81d26..6d3ea9f76 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderFileLoader.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderFileLoader.java @@ -80,8 +80,8 @@ public class ProviderFileLoader implements ProviderLoader { // an IQ class, add the class object itself, then we'll use // reflection later to create instances of the class. // Add the provider to the map. - if (IQProvider.class.isAssignableFrom(provider)) { - IQProvider iqProvider = (IQProvider) provider.getConstructor().newInstance(); + if (IqProvider.class.isAssignableFrom(provider)) { + IqProvider iqProvider = (IqProvider) provider.getConstructor().newInstance(); iqProviders.add(new IQProviderInfo(elementName, namespace, iqProvider)); } else { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderManager.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderManager.java index 377e6e47b..7527b330f 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderManager.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderManager.java @@ -113,7 +113,7 @@ import org.jivesoftware.smack.util.XmppElementUtil; public final class ProviderManager { private static final Map> extensionProviders = new ConcurrentHashMap<>(); - private static final Map> iqProviders = new ConcurrentHashMap<>(); + private static final Map> iqProviders = new ConcurrentHashMap<>(); private static final Map> streamFeatureProviders = new ConcurrentHashMap<>(); private static final Map> nonzaProviders = new ConcurrentHashMap<>(); @@ -167,7 +167,7 @@ public final class ProviderManager { * @param namespace the XML namespace. * @return the IQ provider. */ - public static IQProvider getIQProvider(String elementName, String namespace) { + public static IqProvider getIQProvider(String elementName, String namespace) { QName key = getQName(elementName, namespace); return iqProviders.get(key); } @@ -179,8 +179,8 @@ public final class ProviderManager { * * @return all IQProvider instances. */ - public static List> getIQProviders() { - List> providers = new ArrayList<>(iqProviders.size()); + public static List> getIQProviders() { + List> providers = new ArrayList<>(iqProviders.size()); providers.addAll(iqProviders.values()); return providers; } @@ -200,10 +200,10 @@ public final class ProviderManager { validate(elementName, namespace); // First remove existing providers QName key = removeIQProvider(elementName, namespace); - if (provider instanceof IQProvider) { - iqProviders.put(key, (IQProvider) provider); + if (provider instanceof IqProvider) { + iqProviders.put(key, (IqProvider) provider); } else { - throw new IllegalArgumentException("Provider must be an IQProvider"); + throw new IllegalArgumentException("Provider must be an instance of IqProvider"); } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/TlsFailureProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/TlsFailureProvider.java index 2509d89c8..2100e4e42 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/TlsFailureProvider.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/TlsFailureProvider.java @@ -18,7 +18,6 @@ package org.jivesoftware.smack.provider; import org.jivesoftware.smack.packet.TlsProceed; import org.jivesoftware.smack.packet.XmlEnvironment; - import org.jivesoftware.smack.xml.XmlPullParser; public final class TlsFailureProvider extends NonzaProvider { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/TlsProceedProvider.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/TlsProceedProvider.java index f8e8b1158..282e4c2f1 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/TlsProceedProvider.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/TlsProceedProvider.java @@ -18,7 +18,6 @@ package org.jivesoftware.smack.provider; import org.jivesoftware.smack.packet.TlsFailure; import org.jivesoftware.smack.packet.XmlEnvironment; - import org.jivesoftware.smack.xml.XmlPullParser; public final class TlsProceedProvider extends NonzaProvider { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java b/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java index e2d674bc0..e821e8e91 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java @@ -222,7 +222,7 @@ public abstract class SASLMechanism implements Comparable { * empty array here. * * @return the initial response or null - * @throws SmackSaslException if a SASL specific error occured. + * @throws SmackSaslException if a SASL specific error occurred. */ protected abstract byte[] getAuthenticationText() throws SmackSaslException; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java b/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java index ff34fd979..6fadfd3a8 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java @@ -259,7 +259,7 @@ public abstract class ScramMechanism extends SASLMechanism { /** * * @return the Channel Binding data. - * @throws SmackSaslException if a SASL specific error occured. + * @throws SmackSaslException if a SASL specific error occurred. */ protected byte[] getChannelBindingData() throws SmackSaslException { return null; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/FileUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/FileUtils.java index 74effc014..2cdac90a4 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/FileUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/FileUtils.java @@ -110,7 +110,7 @@ public final class FileUtils { * * @param file TODO javadoc me please * @return the content of file or null in case of an error - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ @SuppressWarnings("DefaultCharset") public static String readFileOrThrow(File file) throws IOException { 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..4943b91bf 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; @@ -35,10 +36,14 @@ import org.jivesoftware.smack.packet.EmptyResultIQ; import org.jivesoftware.smack.packet.ErrorIQ; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; 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; @@ -47,7 +52,7 @@ import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.parsing.StandardExtensionElementProvider; import org.jivesoftware.smack.provider.ExtensionElementProvider; -import org.jivesoftware.smack.provider.IQProvider; +import org.jivesoftware.smack.provider.IqProvider; import org.jivesoftware.smack.provider.ProviderManager; import org.jivesoftware.smack.xml.SmackXmlParser; import org.jivesoftware.smack.xml.XmlPullParser; @@ -101,9 +106,9 @@ public class PacketParserUtils { * @param parser TODO javadoc me please * @param outerXmlEnvironment the outer XML environment (optional). * @return a stanza which is either a Message, IQ or Presence. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws XmlPullParserException if an error in the XML parser occurred. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public static Stanza parseStanza(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, SmackParsingException, IOException { ParserUtils.assertAtStartTag(parser); @@ -120,18 +125,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 { @@ -144,8 +156,8 @@ public class PacketParserUtils { * @param parser the XML parser, positioned at the start of a message packet. * @param outerXmlEnvironment the outer XML environment (optional). * @return a Message packet. - * @throws XmlPullParserException if an error in the XML parser occured. - * @throws IOException if an I/O error occured. + * @throws XmlPullParserException if an error in the XML parser occurred. + * @throws IOException if an I/O error occurred. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input. */ public static Message parseMessage(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { @@ -154,11 +166,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 +191,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 +203,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 +223,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(); } /** @@ -223,8 +238,8 @@ public class PacketParserUtils { * * @param parser TODO javadoc me please * @return the textual content of the element as String - * @throws XmlPullParserException if an error in the XML parser occured. - * @throws IOException if an I/O error occured. + * @throws XmlPullParserException if an error in the XML parser occurred. + * @throws IOException if an I/O error occurred. */ public static String parseElementText(XmlPullParser parser) throws XmlPullParserException, IOException { assert parser.getEventType() == XmlPullParser.Event.START_ELEMENT; @@ -262,8 +277,8 @@ public class PacketParserUtils { * * @param parser the XML pull parser * @return the element as string - * @throws XmlPullParserException if an error in the XML parser occured. - * @throws IOException if an I/O error occured. + * @throws XmlPullParserException if an error in the XML parser occurred. + * @throws IOException if an I/O error occurred. */ public static CharSequence parseElement(XmlPullParser parser) throws XmlPullParserException, IOException { return parseElement(parser, false); @@ -301,8 +316,8 @@ public class PacketParserUtils { * @param depth TODO javadoc me please * @param fullNamespaces TODO javadoc me please * @return the content of the current depth - * @throws XmlPullParserException if an error in the XML parser occured. - * @throws IOException if an I/O error occured. + * @throws XmlPullParserException if an error in the XML parser occurred. + * @throws IOException if an I/O error occurred. */ public static CharSequence parseContentDepth(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException { if (parser.supportsRoundtrip()) { @@ -427,8 +442,8 @@ public class PacketParserUtils { * @param parser the XML parser, positioned at the start of a presence packet. * @param outerXmlEnvironment the outer XML environment (optional). * @return a Presence packet. - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input. */ public static Presence parsePresence(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { @@ -436,13 +451,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 +486,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 +498,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 +516,8 @@ public class PacketParserUtils { break; } } - return presence; + + return presence.build(); } public static IQ parseIQ(XmlPullParser parser) throws Exception { @@ -513,9 +530,9 @@ public class PacketParserUtils { * @param parser the XML parser, positioned at the start of an IQ packet. * @param outerXmlEnvironment the outer XML environment (optional). * @return an IQ object. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmppStringprepException if the provided string is invalid. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input. */ public static IQ parseIQ(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, XmppStringprepException, IOException, SmackParsingException { @@ -523,12 +540,19 @@ 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"); + IqData iqData = StanzaBuilder.buildIqData(id); + final Jid to = ParserUtils.getJidAttribute(parser, "to"); + iqData.to(to); + final Jid from = ParserUtils.getJidAttribute(parser, "from"); + iqData.from(from); + final IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type")); + iqData.ofType(type); outerloop: while (true) { XmlPullParser.Event eventType = parser.next(); @@ -544,9 +568,9 @@ public class PacketParserUtils { // Otherwise, see if there is a registered provider for // this element name and namespace. default: - IQProvider provider = ProviderManager.getIQProvider(elementName, namespace); + IqProvider provider = ProviderManager.getIQProvider(elementName, namespace); if (provider != null) { - iqPacket = provider.parse(parser, outerXmlEnvironment); + iqPacket = provider.parse(parser, iqData, outerXmlEnvironment); } // Note that if we reach this code, it is guranteed that the result IQ contained a child element // (RFC 6120 § 8.2.3 6) because otherwhise we would have reached the END_ELEMENT first. @@ -598,8 +622,8 @@ public class PacketParserUtils { * * @param parser the XML parser, positioned at the start of the mechanisms stanza. * @return a collection of Stings with the mechanisms included in the mechanisms stanza. - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. */ public static Collection parseMechanisms(XmlPullParser parser) throws XmlPullParserException, IOException { @@ -628,7 +652,7 @@ public class PacketParserUtils { * * @param parser the XML parser, positioned at the start of the compression stanza. * @return The CompressionFeature stream element - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws XmlPullParserException if an exception occurs while parsing the stanza. */ public static Compress.Feature parseCompressionFeature(XmlPullParser parser) @@ -695,8 +719,8 @@ public class PacketParserUtils { * @param parser the XML parser. * @param outerXmlEnvironment the outer XML environment (optional). * @return an stream error packet. - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input. */ public static StreamError parseStreamError(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { @@ -747,7 +771,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); } @@ -757,11 +781,11 @@ public class PacketParserUtils { * @param parser the XML parser. * @param outerXmlEnvironment the outer XML environment (optional). * @return an error sub-packet. - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. * @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 +832,8 @@ public class PacketParserUtils { } } builder.setExtensions(extensions).setDescriptiveTexts(descriptiveTexts); - return builder; + + return builder.build(); } /** @@ -820,8 +845,8 @@ public class PacketParserUtils { * @param outerXmlEnvironment the outer XML environment (optional). * * @return an extension element. - * @throws XmlPullParserException if an error in the XML parser occured. - * @throws IOException if an I/O error occured. + * @throws XmlPullParserException if an error in the XML parser occurred. + * @throws IOException if an I/O error occurred. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input. */ public static ExtensionElement parseExtensionElement(String elementName, String namespace, @@ -898,6 +923,18 @@ public class PacketParserUtils { return new Session.Feature(optional); } + public static void addExtensionElement(StanzaBuilder stanzaBuilder, XmlPullParser parser, XmlEnvironment outerXmlEnvironment) + throws XmlPullParserException, IOException, SmackParsingException { + ParserUtils.assertAtStartTag(parser); + addExtensionElement(stanzaBuilder, parser, parser.getName(), parser.getNamespace(), outerXmlEnvironment); + } + + public static void addExtensionElement(StanzaBuilder stanzaBuilder, XmlPullParser parser, String elementName, + String namespace, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { + ExtensionElement extensionElement = parseExtensionElement(elementName, namespace, parser, outerXmlEnvironment); + stanzaBuilder.addExtension(extensionElement); + } + public static void addExtensionElement(Stanza packet, XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { ParserUtils.assertAtStartTag(parser); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/Predicate.java b/smack-core/src/main/java/org/jivesoftware/smack/util/Predicate.java new file mode 100644 index 000000000..ad4c11d0c --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/Predicate.java @@ -0,0 +1,24 @@ +/** + * + * Copyright 2019 Florian Schmaus + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smack.util; + +// TODO: Replace with java.util.function.Predicate once Smack's minimum Android SDK level is 24 or higher. +public interface Predicate { + + boolean test(T t); + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java index eefccf862..ff01779ed 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) { @@ -524,7 +535,7 @@ public class StringUtils { if (cs == null) { return null; } - if (cs.toString().isEmpty()) { + if (isEmpty(cs)) { throw new IllegalArgumentException(message); } return cs; 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/XmlStringBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java index 436f9e5ad..b9c7e5ca6 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java @@ -628,7 +628,7 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element { * * @param writer TODO javadoc me please * @param enclosingXmlEnvironment the enclosing XML environment. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public void write(Writer writer, XmlEnvironment enclosingXmlEnvironment) throws IOException { try { 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/chat_markers/ChatMarkersManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java index 7854204be..b2f99bd76 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java @@ -120,18 +120,10 @@ public final class ChatMarkersManager extends Manager { chatManager = ChatManager.getInstanceFor(connection); - connection.addStanzaInterceptor(new StanzaListener() { - @Override - public void processStanza(Stanza packet) - throws - NotConnectedException, - InterruptedException, - SmackException.NotLoggedInException { - Message message = (Message) packet; - // add a markable extension - message.addExtension(ChatMarkersElements.MarkableExtension.INSTANCE); - } - }, OUTGOING_MESSAGE_FILTER); + connection.addMessageInterceptor(mb -> mb.addExtension(ChatMarkersElements.MarkableExtension.INSTANCE), + m -> { + return OUTGOING_MESSAGE_FILTER.accept(m); + }); connection.addSyncStanzaListener(new StanzaListener() { @Override diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/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/hashes/HashManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hashes/HashManager.java index 318a7dad9..096a7b85b 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hashes/HashManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hashes/HashManager.java @@ -43,6 +43,7 @@ import java.util.WeakHashMap; import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.util.SecurityUtil; + import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.hashes.element.HashElement; 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/hoxt/provider/AbstractHttpOverXmppProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java index 5805d090a..18cbf9fd0 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java @@ -55,8 +55,8 @@ public abstract class AbstractHttpOverXmppProvider 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/data/element/NodeElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/NodeElement.java index bde5d94f8..e84ec5f80 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/NodeElement.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/NodeElement.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.List; import org.jivesoftware.smack.util.XmlStringBuilder; + import org.jivesoftware.smackx.iot.element.NodeInfo; public class NodeElement extends IoTDataExtensionElement { 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/jid_prep/provider/JidPrepIqProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jid_prep/provider/JidPrepIqProvider.java index 82f81f1a9..d7ee7b072 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jid_prep/provider/JidPrepIqProvider.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jid_prep/provider/JidPrepIqProvider.java @@ -23,6 +23,7 @@ import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.provider.IQProvider; import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; + import org.jivesoftware.smackx.jid_prep.element.JidPrepIq; public class JidPrepIqProvider extends IQProvider { 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..6ada795b3 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,6 +35,7 @@ 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; @@ -126,9 +127,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 +158,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 +189,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 ADD_ORIGIN_ID_INTERCEPTOR = mb -> OriginIdElement.addOriginId(mb); + + // We need a filter for outgoing messages that do not carry an origin-id already. + private static final StanzaFilter ADD_ORIGIN_ID_FILTER = new AndFilter(OUTGOING_FILTER, new NotFilter(ORIGIN_ID_FILTER)); + private static final Predicate ADD_ORIGIN_ID_PREDICATE = m -> { + return ADD_ORIGIN_ID_FILTER.accept(m); }; static { @@ -112,10 +113,8 @@ public final class StableUniqueStanzaIdManager extends Manager { * Start appending origin-id elements to outgoing stanzas and add the feature to disco. */ public synchronized void enable() { + connection().addMessageInterceptor(ADD_ORIGIN_ID_INTERCEPTOR, ADD_ORIGIN_ID_PREDICATE); ServiceDiscoveryManager.getInstanceFor(connection()).addFeature(NAMESPACE); - // We need a filter for outgoing messages that do not carry an origin-id already - StanzaFilter filter = new AndFilter(OUTGOING_FILTER, new NotFilter(ORIGIN_ID_FILTER)); - connection().addStanzaInterceptor(ADD_ORIGIN_ID_INTERCEPTOR, filter); } /** @@ -123,7 +122,7 @@ public final class StableUniqueStanzaIdManager extends Manager { */ public synchronized void disable() { ServiceDiscoveryManager.getInstanceFor(connection()).removeFeature(NAMESPACE); - connection().removeStanzaInterceptor(ADD_ORIGIN_ID_INTERCEPTOR); + connection().removeMessageInterceptor(ADD_ORIGIN_ID_INTERCEPTOR); } /** diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java index 4291084bb..10531c4e3 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java @@ -17,6 +17,7 @@ package org.jivesoftware.smackx.sid.element; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager; @@ -38,7 +39,10 @@ public class OriginIdElement extends StableAndUniqueIdElement { * * @param message message. * @return the added origin-id element. + * @deprecated use {@link #addOriginId(MessageBuilder)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public static OriginIdElement addOriginId(Message message) { OriginIdElement originId = new OriginIdElement(); message.addExtension(originId); @@ -47,6 +51,20 @@ public class OriginIdElement extends StableAndUniqueIdElement { return originId; } + /** + * Add an origin-id element to a message and set the stanzas id to the same id as in the origin-id element. + * + * @param messageBuilder the message builder to add an origin ID to. + * @return the added origin-id element. + */ + public static OriginIdElement addOriginId(MessageBuilder messageBuilder) { + OriginIdElement originId = new OriginIdElement(); + messageBuilder.addExtension(originId); + // TODO: Find solution to have both the originIds stanzaId and a nice to look at incremental stanzaID. + // message.setStanzaId(originId.getId()); + return originId; + } + /** * Return true, if the message contains a origin-id element. * diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/xmlelement/element/DataFormsXmlElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/xmlelement/element/DataFormsXmlElement.java index a23296e9c..bb2364af6 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/xmlelement/element/DataFormsXmlElement.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/xmlelement/element/DataFormsXmlElement.java @@ -21,6 +21,7 @@ import javax.xml.namespace.QName; import org.jivesoftware.smack.packet.StandardExtensionElement; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.util.XmlStringBuilder; + import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.FormFieldChildElement; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/xmlelement/provider/DataFormsXmlElementProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/xmlelement/provider/DataFormsXmlElementProvider.java index 4de486db2..9f7058e97 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/xmlelement/provider/DataFormsXmlElementProvider.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/xmlelement/provider/DataFormsXmlElementProvider.java @@ -26,6 +26,7 @@ import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.parsing.StandardExtensionElementProvider; import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; + import org.jivesoftware.smackx.xdata.provider.FormFieldChildElementProvider; import org.jivesoftware.smackx.xmlelement.element.DataFormsXmlElement; diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/AcknowledgedExtensionTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/AcknowledgedExtensionTest.java index ed8b4fbfa..58a5d9dcb 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/AcknowledgedExtensionTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/AcknowledgedExtensionTest.java @@ -19,6 +19,7 @@ package org.jivesoftware.smackx.chat_markers; import static org.junit.jupiter.api.Assertions.assertEquals; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.xml.XmlPullParser; @@ -28,7 +29,6 @@ import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements.Acknowle import org.jivesoftware.smackx.chat_markers.provider.AcknowledgedProvider; import org.junit.jupiter.api.Test; -import org.jxmpp.jid.impl.JidCreate; public class AcknowledgedExtensionTest { @@ -39,9 +39,10 @@ public class AcknowledgedExtensionTest { @Test public void checkDisplayedExtension() throws Exception { - Message message = new Message(JidCreate.from("northumberland@shakespeare.lit/westminster")); - message.setStanzaId("message-2"); - message.addExtension(new ChatMarkersElements.AcknowledgedExtension("message-1")); + Message message = StanzaBuilder.buildMessage("message-2") + .to("northumberland@shakespeare.lit/westminster") + .addExtension(new ChatMarkersElements.AcknowledgedExtension("message-1")) + .build(); assertEquals(acknowledgedMessageStanza, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/DisplayedExtensionTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/DisplayedExtensionTest.java index f4f1295e7..86dad6936 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/DisplayedExtensionTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/DisplayedExtensionTest.java @@ -19,6 +19,7 @@ package org.jivesoftware.smackx.chat_markers; import static org.junit.jupiter.api.Assertions.assertEquals; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.xml.XmlPullParser; @@ -28,7 +29,6 @@ import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements.Displaye import org.jivesoftware.smackx.chat_markers.provider.DisplayedProvider; import org.junit.jupiter.api.Test; -import org.jxmpp.jid.impl.JidCreate; public class DisplayedExtensionTest { @@ -39,9 +39,10 @@ public class DisplayedExtensionTest { @Test public void checkDisplayedExtension() throws Exception { - Message message = new Message(JidCreate.from("northumberland@shakespeare.lit/westminster")); - message.setStanzaId("message-2"); - message.addExtension(new ChatMarkersElements.DisplayedExtension("message-1")); + Message message = StanzaBuilder.buildMessage("message-2") + .to("northumberland@shakespeare.lit/westminster") + .addExtension(new ChatMarkersElements.DisplayedExtension("message-1")) + .build(); assertEquals(displayedMessageStanza, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/MarkableExtensionTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/MarkableExtensionTest.java index 91944acc1..2b08e1c1b 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/MarkableExtensionTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/MarkableExtensionTest.java @@ -19,6 +19,7 @@ package org.jivesoftware.smackx.chat_markers; import static org.junit.jupiter.api.Assertions.assertEquals; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.xml.XmlPullParser; @@ -39,10 +40,12 @@ public class MarkableExtensionTest { @Test public void checkMarkableExtension() throws Exception { - Message message = new Message(JidCreate.from("ingrichard@royalty.england.lit/throne")); - message.setStanzaId("message-1"); - message.setBody("My lord, dispatch; read o'er these articles."); - message.addExtension(ChatMarkersElements.MarkableExtension.INSTANCE); + Message message = StanzaBuilder.buildMessage("message-1") + .to(JidCreate.from("ingrichard@royalty.england.lit/throne")) + .setBody("My lord, dispatch; read o'er these articles.") + .addExtension(ChatMarkersElements.MarkableExtension.INSTANCE) + .build(); + assertEquals(markableMessageStanza, message.toXML().toString()); } diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/ReceivedExtensionTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/ReceivedExtensionTest.java index be80449b9..d1732c88f 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/ReceivedExtensionTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/chat_markers/ReceivedExtensionTest.java @@ -19,6 +19,7 @@ package org.jivesoftware.smackx.chat_markers; import static org.junit.jupiter.api.Assertions.assertEquals; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.xml.XmlPullParser; @@ -28,7 +29,6 @@ import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements.Received import org.jivesoftware.smackx.chat_markers.provider.ReceivedProvider; import org.junit.jupiter.api.Test; -import org.jxmpp.jid.impl.JidCreate; public class ReceivedExtensionTest { @@ -39,9 +39,10 @@ public class ReceivedExtensionTest { @Test public void checkReceivedExtension() throws Exception { - Message message = new Message(JidCreate.from("northumberland@shakespeare.lit/westminster")); - message.setStanzaId("message-2"); - message.addExtension(new ChatMarkersElements.ReceivedExtension("message-1")); + Message message = StanzaBuilder.buildMessage("message-2") + .to("northumberland@shakespeare.lit/westminster") + .addExtension(new ChatMarkersElements.ReceivedExtension("message-1")) + .build(); assertEquals(receivedMessageStanza, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); } diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/colors/ConsistentColorsTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/colors/ConsistentColorsTest.java index 3bf012d9d..931208284 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/colors/ConsistentColorsTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/colors/ConsistentColorsTest.java @@ -19,6 +19,7 @@ package org.jivesoftware.smackx.colors; import static org.junit.jupiter.api.Assertions.assertEquals; import org.jivesoftware.smack.test.util.SmackTestSuite; + import org.jivesoftware.smackx.colors.ConsistentColor.Deficiency; import org.junit.jupiter.api.Test; diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/eme/ExplicitMessageEncryptionElementTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/eme/ExplicitMessageEncryptionElementTest.java index 3d1cd04df..85a3ef60f 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/eme/ExplicitMessageEncryptionElementTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/eme/ExplicitMessageEncryptionElementTest.java @@ -25,6 +25,8 @@ import java.util.List; 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.smackx.eme.element.ExplicitMessageEncryptionElement; @@ -35,7 +37,7 @@ public class ExplicitMessageEncryptionElementTest extends SmackTestSuite { @Test public void addToMessageTest() { - Message message = new Message(); + Message message = StanzaBuilder.buildMessage().build(); // Check inital state (no elements) assertNull(ExplicitMessageEncryptionElement.from(message)); @@ -45,9 +47,12 @@ public class ExplicitMessageEncryptionElementTest extends SmackTestSuite { List 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..c9c4367a8 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdTest.java @@ -23,6 +23,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smack.util.PacketParserUtils; @@ -70,12 +72,15 @@ public class StableUniqueStanzaIdTest extends SmackTestSuite { @Test public void fromMessageTest() { - Message message = new Message(); + MessageBuilder messageBuilder = StanzaBuilder.buildMessage(); + + Message message = messageBuilder.build(); assertFalse(OriginIdElement.hasOriginId(message)); assertFalse(StanzaIdElement.hasStanzaId(message)); - OriginIdElement.addOriginId(message); + OriginIdElement.addOriginId(messageBuilder); + message = messageBuilder.build(); assertTrue(OriginIdElement.hasOriginId(message)); StanzaIdElement stanzaId = new StanzaIdElement("alice@wonderland.lit"); diff --git a/smack-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/integration-test/java/org/jivesoftware/smackx/MessageEventManagerTest.java b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/MessageEventManagerTest.java index 8f117b04e..13c3977be 100644 --- a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/MessageEventManagerTest.java +++ b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/MessageEventManagerTest.java @@ -58,7 +58,7 @@ public class MessageEventManagerTest extends SmackTestCase { try { chat1.sendMessage(msg); } catch (Exception e) { - fail("An error occured sending the message"); + fail("An error occurred sending the message"); } } @@ -113,7 +113,7 @@ public class MessageEventManagerTest extends SmackTestCase { // Wait a few seconds so that the XMPP client can send any event Thread.sleep(200); } catch (Exception e) { - fail("An error occured sending the message"); + fail("An error occurred sending the message"); } } @@ -229,7 +229,7 @@ public class MessageEventManagerTest extends SmackTestCase { results.containsAll(resultsExpected)); } catch (Exception e) { - fail("An error occured sending the message"); + fail("An error occurred sending the message"); } } diff --git a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/RosterExchangeManagerTest.java b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/RosterExchangeManagerTest.java index 378ccc4f4..b91e45b5b 100644 --- a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/RosterExchangeManagerTest.java +++ b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/RosterExchangeManagerTest.java @@ -56,7 +56,7 @@ public class RosterExchangeManagerTest extends SmackTestCase { } catch (Exception e) { e.printStackTrace(); - fail("An error occured sending the roster"); + fail("An error occurred sending the roster"); } } @@ -76,7 +76,7 @@ public class RosterExchangeManagerTest extends SmackTestCase { } catch (Exception e) { e.printStackTrace(); - fail("An error occured sending the roster"); + fail("An error occurred sending the roster"); } } @@ -121,7 +121,7 @@ public class RosterExchangeManagerTest extends SmackTestCase { } } catch (Exception e) { - fail("An error occured sending the message with the roster"); + fail("An error occurred sending the message with the roster"); } assertEquals( "Number of sent and received entries does not match", @@ -179,7 +179,7 @@ public class RosterExchangeManagerTest extends SmackTestCase { } } catch (Exception e) { - fail("An error occured sending the message with the roster"); + fail("An error occurred sending the message with the roster"); } assertEquals( "Number of sent and received entries does not match", diff --git a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/XHTMLManagerTest.java b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/XHTMLManagerTest.java index 1d104adfa..5482fc0e5 100644 --- a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/XHTMLManagerTest.java +++ b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/XHTMLManagerTest.java @@ -75,7 +75,7 @@ public class XHTMLManagerTest extends SmackTestCase { chat1.sendMessage(msg); Thread.sleep(200); } catch (Exception e) { - fail("An error occured sending the message with XHTML"); + fail("An error occurred sending the message with XHTML"); } } @@ -116,7 +116,7 @@ public class XHTMLManagerTest extends SmackTestCase { try { chat1.sendMessage(msg); } catch (Exception e) { - fail("An error occured sending the message with XHTML"); + fail("An error occurred sending the message with XHTML"); } Packet packet = chat2.nextResult(2000); @@ -197,7 +197,7 @@ public class XHTMLManagerTest extends SmackTestCase { bodiesReceived = 0; chat1.sendMessage(msg); } catch (Exception e) { - fail("An error occured sending the message with XHTML"); + fail("An error occurred sending the message with XHTML"); } Packet packet = chat2.nextResult(2000); diff --git a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/MessageEventTest.java b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/MessageEventTest.java index e34b04301..0ac8c8850 100644 --- a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/MessageEventTest.java +++ b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/MessageEventTest.java @@ -64,7 +64,7 @@ public class MessageEventTest extends SmackTestCase { Thread.sleep(200); } catch (Exception e) { - fail("An error occured sending the message"); + fail("An error occurred sending the message"); } } @@ -122,7 +122,7 @@ public class MessageEventTest extends SmackTestCase { Thread.sleep(200); } catch (Exception e) { - fail("An error occured sending the message"); + fail("An error occurred sending the message"); } } diff --git a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/RosterExchangeTest.java b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/RosterExchangeTest.java index 97f9001d9..305b2728e 100644 --- a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/RosterExchangeTest.java +++ b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/RosterExchangeTest.java @@ -58,7 +58,7 @@ public class RosterExchangeTest extends SmackTestCase { try { chat1.sendMessage(msg); } catch (Exception e) { - fail("An error occured sending the message with the roster"); + fail("An error occurred sending the message with the roster"); } } @@ -87,7 +87,7 @@ public class RosterExchangeTest extends SmackTestCase { try { chat1.sendMessage(msg); } catch (Exception e) { - fail("An error occured sending the message with the roster"); + fail("An error occurred sending the message with the roster"); } // Wait for 2 seconds for a reply Packet packet = chat2.nextResult(2000); @@ -131,7 +131,7 @@ public class RosterExchangeTest extends SmackTestCase { try { chat1.sendMessage(msg); } catch (Exception e) { - fail("An error occured sending the message with the roster"); + fail("An error occurred sending the message with the roster"); } // Wait for 10 seconds for a reply Packet packet = chat2.nextResult(5000); diff --git a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/XHTMLExtensionTest.java b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/XHTMLExtensionTest.java index fe447c9c0..d665a7b9c 100644 --- a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/XHTMLExtensionTest.java +++ b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/packet/XHTMLExtensionTest.java @@ -68,7 +68,7 @@ public class XHTMLExtensionTest extends SmackTestCase { Thread.sleep(200); } catch (Exception e) { - fail("An error occured sending the message with XHTML"); + fail("An error occurred sending the message with XHTML"); } } @@ -101,7 +101,7 @@ public class XHTMLExtensionTest extends SmackTestCase { chat1.sendMessage(msg); } catch (Exception e) { - fail("An error occured sending the message with XHTML"); + fail("An error occurred sending the message with XHTML"); } Packet packet = chat2.nextResult(2000); Message message = (Message) packet; @@ -172,7 +172,7 @@ public class XHTMLExtensionTest extends SmackTestCase { chat1.sendMessage(msg); } catch (Exception e) { - fail("An error occured sending the message with XHTML"); + fail("An error occurred sending the message with XHTML"); } Packet packet = chat2.nextResult(2000); int received = 0; 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/smack/chat2/ChatManager.java b/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/ChatManager.java index 4066b1d4d..e8349b6c6 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/ChatManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/ChatManager.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017-2018 Florian Schmaus. + * Copyright 2017-2019 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ import java.util.concurrent.CopyOnWriteArraySet; import org.jivesoftware.smack.AsyncButOrdered; import org.jivesoftware.smack.Manager; -import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.StanzaListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.filter.AndFilter; @@ -36,6 +35,7 @@ import org.jivesoftware.smack.filter.StanzaExtensionFilter; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.filter.ToTypeFilter; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageView; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.roster.AbstractRosterListener; @@ -124,22 +124,20 @@ public final class ChatManager extends Manager { } }, INCOMING_MESSAGE_FILTER); - connection.addStanzaInterceptor(new StanzaListener() { - @Override - public void processStanza(Stanza stanza) throws NotConnectedException, InterruptedException { - Message message = (Message) stanza; - if (!shouldAcceptMessage(message)) { - return; - } - - final EntityBareJid to = message.getTo().asEntityBareJidOrThrow(); - final Chat chat = chatWith(to); - - for (OutgoingChatMessageListener listener : outgoingListeners) { - listener.newOutgoingMessage(to, message, chat); - } + connection.addMessageInterceptor(messageBuilder -> { + if (!shouldAcceptMessage(messageBuilder)) { + return; } - }, OUTGOING_MESSAGE_FILTER); + + final EntityBareJid to = messageBuilder.getTo().asEntityBareJidOrThrow(); + final Chat chat = chatWith(to); + + for (OutgoingChatMessageListener listener : outgoingListeners) { + listener.newOutgoingMessage(to, messageBuilder, chat); + } + }, m -> { + return OUTGOING_MESSAGE_FILTER.accept(m); + }); Roster roster = Roster.getInstanceFor(connection); roster.addRosterListener(new AbstractRosterListener() { @@ -181,8 +179,8 @@ public final class ChatManager extends Manager { }); } - private boolean shouldAcceptMessage(Message message) { - if (!message.getBodies().isEmpty()) { + private boolean shouldAcceptMessage(MessageView message) { + if (message.hasExtension(Message.Body.QNAME)) { return true; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/OutgoingChatMessageListener.java b/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/OutgoingChatMessageListener.java index 4ceba2c6f..75a9918fd 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/OutgoingChatMessageListener.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smack/chat2/OutgoingChatMessageListener.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * Copyright 2017-2019 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,12 @@ */ package org.jivesoftware.smack.chat2; -import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jxmpp.jid.EntityBareJid; public interface OutgoingChatMessageListener { - void newOutgoingMessage(EntityBareJid to, Message message, Chat chat); + void newOutgoingMessage(EntityBareJid to, MessageBuilder messageBuilder, Chat chat); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/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/amp/provider/AMPExtensionProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/amp/provider/AMPExtensionProvider.java index b503c9850..55e09769d 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/amp/provider/AMPExtensionProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/amp/provider/AMPExtensionProvider.java @@ -38,8 +38,8 @@ public class AMPExtensionProvider extends ExtensionElementProvider * * @param parser the XML parser, positioned at the starting element of the extension. * @return a PacketExtension. - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. */ @Override public AMPExtension parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) 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/bytestreams/socks5/Socks5Client.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java index fb7368576..7f80e8260 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java @@ -130,7 +130,7 @@ public class Socks5Client { * supported by the Socks5Client. * * @param socket connected to a SOCKS5 proxy - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws SmackMessageException if there was an error. */ protected void establish(Socket socket) throws IOException, SmackMessageException { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java index 8d9b0df7f..6591d7512 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java @@ -51,9 +51,11 @@ import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.PresenceBuilder; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.roster.AbstractPresenceEventListener; import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.util.Consumer; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.stringencoder.Base64; @@ -66,6 +68,8 @@ import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature; import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity; +import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder; +import org.jivesoftware.smackx.disco.packet.DiscoverInfoView; import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.packet.DataForm; @@ -308,6 +312,15 @@ public final class EntityCapsManager extends Manager { */ private String entityNode = DEFAULT_ENTITY_NODE; + // Intercept presence packages and add caps data when intended. + // XEP-0115 specifies that a client SHOULD include entity capabilities + // with every presence notification it sends. + private final Consumer presenceInterceptor = presenceBuilder -> { + CapsVersionAndHash capsVersionAndHash = getCapsVersionAndHash(); + CapsExtension caps = new CapsExtension(entityNode, capsVersionAndHash.version, capsVersionAndHash.hash); + presenceBuilder.overrideExtension(caps); + }; + private EntityCapsManager(XMPPConnection connection) { super(connection); this.sdm = ServiceDiscoveryManager.getInstanceFor(connection); @@ -379,23 +392,9 @@ public final class EntityCapsManager extends Manager { } }, PresenceTypeFilter.OUTGOING_PRESENCE_BROADCAST); - // Intercept presence packages and add caps data when intended. - // XEP-0115 specifies that a client SHOULD include entity capabilities - // with every presence notification it sends. - StanzaListener packetInterceptor = new StanzaListener() { - @Override - public void processStanza(Stanza packet) { - if (!entityCapsEnabled) { - // Be sure to not send stanzas with the caps extension if it's not enabled - packet.removeExtension(CapsExtension.ELEMENT, CapsExtension.NAMESPACE); - return; - } - CapsVersionAndHash capsVersionAndHash = getCapsVersionAndHash(); - CapsExtension caps = new CapsExtension(entityNode, capsVersionAndHash.version, capsVersionAndHash.hash); - packet.overrideExtension(caps); - } - }; - connection.addStanzaInterceptor(packetInterceptor, PresenceTypeFilter.AVAILABLE); + + enableEntityCaps(); + // It's important to do this as last action. Since it changes the // behavior of the SDM in some ways sdm.addEntityCapabilitiesChangedListener(new EntityCapabilitiesChangedListener() { @@ -424,6 +423,10 @@ public final class EntityCapsManager extends Manager { } public synchronized void enableEntityCaps() { + connection().addPresenceInterceptor(presenceInterceptor, p -> { + return PresenceTypeFilter.AVAILABLE.accept(p); + }); + // Add Entity Capabilities (XEP-0115) feature node. sdm.addFeature(NAMESPACE); updateLocalEntityCaps(); @@ -433,6 +436,8 @@ public final class EntityCapsManager extends Manager { public synchronized void disableEntityCaps() { entityCapsEnabled = false; sdm.removeFeature(NAMESPACE); + + connection().removePresenceInterceptor(presenceInterceptor); } public boolean entityCapsEnabled() { @@ -518,16 +523,19 @@ public final class EntityCapsManager extends Manager { private void updateLocalEntityCaps() { XMPPConnection connection = connection(); - DiscoverInfo discoverInfo = new DiscoverInfo(); - discoverInfo.setType(IQ.Type.result); - sdm.addDiscoverInfoTo(discoverInfo); + DiscoverInfoBuilder discoverInfoBuilder = DiscoverInfo.builder("synthetized-disco-info-response") + .ofType(IQ.Type.result); + sdm.addDiscoverInfoTo(discoverInfoBuilder); // getLocalNodeVer() will return a result only after currentCapsVersion is set. Therefore // set it first and then call getLocalNodeVer() - currentCapsVersion = generateVerificationString(discoverInfo); + currentCapsVersion = generateVerificationString(discoverInfoBuilder); final String localNodeVer = getLocalNodeVer(); - discoverInfo.setNode(localNodeVer); + discoverInfoBuilder.setNode(localNodeVer); + + final DiscoverInfo discoverInfo = discoverInfoBuilder.build(); addDiscoverInfoByNode(localNodeVer, discoverInfo); + if (lastLocalCapsVersions.size() > 10) { CapsVersionAndHash oldCapsVersion = lastLocalCapsVersions.poll(); sdm.removeNodeInformationProvider(entityNode + '#' + oldCapsVersion.version); @@ -627,7 +635,7 @@ public final class EntityCapsManager extends Manager { return false; } - protected static CapsVersionAndHash generateVerificationString(DiscoverInfo discoverInfo) { + protected static CapsVersionAndHash generateVerificationString(DiscoverInfoView discoverInfo) { return generateVerificationString(discoverInfo, null); } @@ -643,7 +651,7 @@ public final class EntityCapsManager extends Manager { * @return The generated verification String or null if the hash is not * supported */ - protected static CapsVersionAndHash generateVerificationString(DiscoverInfo discoverInfo, String hash) { + protected static CapsVersionAndHash generateVerificationString(DiscoverInfoView discoverInfo, String hash) { if (hash == null) { hash = DEFAULT_HASH; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/cache/SimpleDirectoryPersistentCache.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/cache/SimpleDirectoryPersistentCache.java index f965f7a72..7a93df444 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/cache/SimpleDirectoryPersistentCache.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/cache/SimpleDirectoryPersistentCache.java @@ -127,7 +127,7 @@ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache * * @param file TODO javadoc me please * @param info TODO javadoc me please - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ private static void writeInfoToFile(File file, DiscoverInfo info) throws IOException { try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) { 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..8e5060172 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/chatstates/ChatStateManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/chatstates/ChatStateManager.java @@ -37,12 +37,13 @@ import org.jivesoftware.smack.chat2.OutgoingChatMessageListener; import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.filter.FromTypeFilter; import org.jivesoftware.smack.filter.MessageTypeFilter; -import org.jivesoftware.smack.filter.NotFilter; import org.jivesoftware.smack.filter.StanzaExtensionFilter; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smackx.chatstates.packet.ChatStateExtension; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; @@ -72,7 +73,6 @@ public final class ChatStateManager extends Manager { private static final Map INSTANCES = new WeakHashMap<>(); - private static final StanzaFilter filter = new NotFilter(new StanzaExtensionFilter(NAMESPACE)); private static final StanzaFilter INCOMING_MESSAGE_FILTER = new AndFilter(MessageTypeFilter.NORMAL_OR_CHAT, FromTypeFilter.ENTITY_FULL_JID); private static final StanzaFilter INCOMING_CHAT_STATE_FILTER = new AndFilter(INCOMING_MESSAGE_FILTER, new StanzaExtensionFilter(NAMESPACE)); @@ -116,13 +116,13 @@ public final class ChatStateManager extends Manager { ChatManager chatManager = ChatManager.getInstanceFor(connection); chatManager.addOutgoingListener(new OutgoingChatMessageListener() { @Override - public void newOutgoingMessage(EntityBareJid to, Message message, Chat chat) { + public void newOutgoingMessage(EntityBareJid to, MessageBuilder message, Chat chat) { if (chat == null) { return; } // if message already has a chatStateExtension, then do nothing, - if (!filter.accept(message)) { + if (message.hasExtension(ChatStateExtension.NAMESPACE)) { return; } @@ -218,7 +218,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..62fc38d1d 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 @@ -47,6 +47,7 @@ import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity; +import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder; import org.jivesoftware.smackx.disco.packet.DiscoverItems; import org.jivesoftware.smackx.xdata.packet.DataForm; @@ -146,7 +147,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; } @@ -159,34 +160,33 @@ public final class ServiceDiscoveryManager extends Manager { public IQ handleIQRequest(IQ iqRequest) { DiscoverInfo discoverInfo = (DiscoverInfo) iqRequest; // Answer the client's supported features if the request is of the GET type - DiscoverInfo response = new DiscoverInfo(); - response.setType(IQ.Type.result); - response.setTo(discoverInfo.getFrom()); - response.setStanzaId(discoverInfo.getStanzaId()); - response.setNode(discoverInfo.getNode()); + DiscoverInfoBuilder responseBuilder = DiscoverInfoBuilder.buildResponseFor(discoverInfo, IQ.ResponseType.result); + // Add the client's identity and features only if "node" is null // and if the request was not send to a node. If Entity Caps are // enabled the client's identity and features are may also added // if the right node is chosen if (discoverInfo.getNode() == null) { - addDiscoverInfoTo(response); + addDiscoverInfoTo(responseBuilder); } else { // Disco#info was sent to a node. Check if we have information of the // specified node NodeInformationProvider nodeInformationProvider = getNodeInformationProvider(discoverInfo.getNode()); if (nodeInformationProvider != null) { // Node was found. Add node features - response.addFeatures(nodeInformationProvider.getNodeFeatures()); + responseBuilder.addFeatures(nodeInformationProvider.getNodeFeatures()); // Add node identities - response.addIdentities(nodeInformationProvider.getNodeIdentities()); + responseBuilder.addIdentities(nodeInformationProvider.getNodeIdentities()); // Add packet extensions - response.addExtensions(nodeInformationProvider.getNodePacketExtensions()); + responseBuilder.addExtensions(nodeInformationProvider.getNodePacketExtensions()); } else { // Return error since specified node was not found - response.setType(IQ.Type.error); - response.setError(StanzaError.getBuilder(StanzaError.Condition.item_not_found)); + responseBuilder.ofType(IQ.Type.error); + responseBuilder.setError(StanzaError.getBuilder(StanzaError.Condition.item_not_found).build()); } } + + DiscoverInfo response = responseBuilder.build(); return response; } }); @@ -299,7 +299,7 @@ public final class ServiceDiscoveryManager extends Manager { * * @param response the discover info response packet */ - public synchronized void addDiscoverInfoTo(DiscoverInfo response) { + public synchronized void addDiscoverInfoTo(DiscoverInfoBuilder response) { // First add the identities of the connection response.addIdentities(getIdentities()); @@ -307,7 +307,9 @@ public final class ServiceDiscoveryManager extends Manager { for (String feature : getFeatures()) { response.addFeature(feature); } - response.addExtension(extendedInfo); + if (extendedInfo != null) { + response.addExtension(extendedInfo); + } } /** @@ -522,13 +524,15 @@ public final class ServiceDiscoveryManager extends Manager { * @throws InterruptedException if the calling thread was interrupted. */ public DiscoverInfo discoverInfo(Jid entityID, String node) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - // Discover the entity's info - DiscoverInfo disco = new DiscoverInfo(); - disco.setType(IQ.Type.get); - disco.setTo(entityID); - disco.setNode(node); + XMPPConnection connection = connection(); - Stanza result = connection().createStanzaCollectorAndSend(disco).nextResultOrThrow(); + // Discover the entity's info + DiscoverInfo discoInfoRequest = DiscoverInfo.builder(connection) + .to(entityID) + .setNode(node) + .build(); + + Stanza result = connection.createStanzaCollectorAndSend(discoInfoRequest).nextResultOrThrow(); return (DiscoverInfo) result; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java index 62e9cef67..796e51857 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java @@ -24,7 +24,9 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; +import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqData; import org.jivesoftware.smack.util.EqualsUtil; import org.jivesoftware.smack.util.HashCode; import org.jivesoftware.smack.util.StringUtils; @@ -42,18 +44,53 @@ import org.jxmpp.util.XmppStringUtils; * * @author Gaston Dombiak */ -public class DiscoverInfo extends IQ implements TypedCloneable { +public class DiscoverInfo extends IQ implements DiscoverInfoView, TypedCloneable { public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = "http://jabber.org/protocol/disco#info"; - private final List features = new LinkedList<>(); + private final List features = new ArrayList<>(); private final Set featuresSet = new HashSet<>(); - private final List identities = new LinkedList<>(); + private final List identities = new ArrayList<>(); private final Set identitiesSet = new HashSet<>(); private String node; private boolean containsDuplicateFeatures; + DiscoverInfo(DiscoverInfoBuilder builder, boolean validate) { + super(builder, ELEMENT, NAMESPACE); + + features.addAll(builder.getFeatures()); + identities.addAll(builder.getIdentities()); + node = builder.getNode(); + + + for (Feature feature : features) { + boolean featureIsNew = featuresSet.add(feature); + if (!featureIsNew) { + containsDuplicateFeatures = true; + } + } + + for (Identity identity : identities) { + identitiesSet.add(identity.getKey()); + } + + if (!validate) { + return; + } + + if (containsDuplicateFeatures) { + throw new IllegalArgumentException("The disco#info request contains duplicate features."); + } + } + + /** + * Deprecated. + * + * @deprecated use {@link DiscoverInfoBuilder} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. public DiscoverInfo() { super(ELEMENT, NAMESPACE); } @@ -67,17 +104,15 @@ public class DiscoverInfo extends IQ implements TypedCloneable { super(d); // Set node - setNode(d.getNode()); + node = d.getNode(); // Copy features - for (Feature f : d.features) { - addFeature(f.clone()); - } + features.addAll(d.features); + featuresSet.addAll(d.featuresSet); // Copy identities - for (Identity i : d.identities) { - addIdentity(i.clone()); - } + identities.addAll(d.identities); + identitiesSet.addAll(d.identitiesSet); } /** @@ -85,7 +120,10 @@ public class DiscoverInfo extends IQ implements TypedCloneable { * * @param feature the discovered feature * @return true if the feature did not already exist. + * @deprecated use {@link DiscoverInfoBuilder#addFeature(String)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public boolean addFeature(String feature) { return addFeature(new Feature(feature)); } @@ -94,7 +132,10 @@ public class DiscoverInfo extends IQ implements TypedCloneable { * Adds a collection of features to the packet. Does noting if featuresToAdd is null. * * @param featuresToAdd TODO javadoc me please + * @deprecated use {@link DiscoverInfoBuilder#addFeatures(Collection)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void addFeatures(Collection featuresToAdd) { if (featuresToAdd == null) return; for (String feature : featuresToAdd) { @@ -102,6 +143,15 @@ public class DiscoverInfo extends IQ implements TypedCloneable { } } + /** + * Deprecated. + * + * @param feature the future. + * @return true if the feature is new. + * @deprecated use {@link DiscoverInfoBuilder#addFeature(DiscoverInfo.Feature)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. public boolean addFeature(Feature feature) { features.add(feature); boolean featureIsNew = featuresSet.add(feature); @@ -111,11 +161,7 @@ public class DiscoverInfo extends IQ implements TypedCloneable { return featureIsNew; } - /** - * Returns the discovered features of an XMPP entity. - * - * @return an unmodifiable list of the discovered features of an XMPP entity - */ + @Override public List getFeatures() { return Collections.unmodifiableList(features); } @@ -124,7 +170,10 @@ public class DiscoverInfo extends IQ implements TypedCloneable { * Adds a new identity of the requested entity to the discovered information. * * @param identity the discovered entity's identity + * @deprecated use {@link DiscoverInfoBuilder#addIdentity(DiscoverInfo.Identity)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void addIdentity(Identity identity) { identities.add(identity); identitiesSet.add(identity.getKey()); @@ -134,7 +183,10 @@ public class DiscoverInfo extends IQ implements TypedCloneable { * Adds identities to the DiscoverInfo stanza. * * @param identitiesToAdd TODO javadoc me please + * @deprecated use {@link DiscoverInfoBuilder#addIdentities(Collection)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void addIdentities(Collection identitiesToAdd) { if (identitiesToAdd == null) return; for (Identity identity : identitiesToAdd) { @@ -142,11 +194,7 @@ public class DiscoverInfo extends IQ implements TypedCloneable { } } - /** - * Returns the discovered identities of an XMPP entity. - * - * @return an unmodifiable list of the discovered identities - */ + @Override public List getIdentities() { return Collections.unmodifiableList(identities); } @@ -180,15 +228,7 @@ public class DiscoverInfo extends IQ implements TypedCloneable { return res; } - /** - * Returns the node attribute that supplements the 'jid' attribute. A node is merely - * something that is associated with a JID and for which the JID can provide information.

- * - * Node attributes SHOULD be used only when trying to provide or query information which - * is not directly addressable. - * - * @return the node attribute that supplements the 'jid' attribute - */ + @Override public String getNode() { return node; } @@ -201,7 +241,10 @@ public class DiscoverInfo extends IQ implements TypedCloneable { * is not directly addressable. * * @param node the node attribute that supplements the 'jid' attribute + * @deprecated use {@link DiscoverInfoBuilder#setNode(String)} instead. */ + @Deprecated + // TODO: Remove in Smack 4.5. public void setNode(String node) { this.node = StringUtils.requireNullOrNotEmpty(node, "The node can not be the empty string"); } @@ -256,11 +299,28 @@ public class DiscoverInfo extends IQ implements TypedCloneable { return containsDuplicateFeatures; } + public DiscoverInfoBuilder asBuilder() { + return new DiscoverInfoBuilder(this); + } + + // TODO: Deprecate in favor of asBuilder(). @Override public DiscoverInfo clone() { return new DiscoverInfo(this); } + public static DiscoverInfoBuilder builder(XMPPConnection connection) { + return new DiscoverInfoBuilder(connection); + } + + public static DiscoverInfoBuilder builder(IqData iqData) { + return new DiscoverInfoBuilder(iqData); + } + + public static DiscoverInfoBuilder builder(String stanzaId) { + return new DiscoverInfoBuilder(stanzaId); + } + /** * Represents the identity of a given XMPP entity. An entity may have many identities but all * the identities SHOULD have the same name.

@@ -270,7 +330,7 @@ public class DiscoverInfo extends IQ implements TypedCloneable { * attributes. * */ - public static final class Identity implements Comparable, TypedCloneable { + public static final class Identity implements Comparable { private final String category; private final String type; @@ -278,14 +338,6 @@ public class DiscoverInfo extends IQ implements TypedCloneable { private final String name; private final String lang; // 'xml:lang; - public Identity(Identity identity) { - this.category = identity.category; - this.type = identity.type; - this.key = identity.type; - this.name = identity.name; - this.lang = identity.lang; - } - /** * Creates a new identity for an XMPP entity. * @@ -452,11 +504,6 @@ public class DiscoverInfo extends IQ implements TypedCloneable { } } - @Override - public Identity clone() { - return new Identity(this); - } - @Override public String toString() { return toXML().toString(); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfoBuilder.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfoBuilder.java new file mode 100644 index 000000000..66f965de4 --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfoBuilder.java @@ -0,0 +1,123 @@ +/** + * + * 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.smackx.disco.packet; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IqBuilder; +import org.jivesoftware.smack.packet.IqData; + +import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature; +import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity; + +public class DiscoverInfoBuilder extends IqBuilder + implements DiscoverInfoView { + + private final List features = new ArrayList<>(); + private final List identities = new ArrayList<>(); + + private String node; + + DiscoverInfoBuilder(IqData iqCommon) { + super(iqCommon); + } + + DiscoverInfoBuilder(XMPPConnection connection) { + super(connection); + } + + DiscoverInfoBuilder(String stanzaId) { + super(stanzaId); + } + + public DiscoverInfoBuilder(DiscoverInfo discoverInfo) { + super(discoverInfo.getStanzaId()); + features.addAll(discoverInfo.getFeatures()); + identities.addAll(discoverInfo.getIdentities()); + node = discoverInfo.getNode(); + } + + @Override + public DiscoverInfoBuilder getThis() { + return this; + } + + public DiscoverInfoBuilder addFeatures(Collection features) { + for (String feature : features) { + addFeature(feature); + } + return getThis(); + } + + public DiscoverInfoBuilder addFeature(String feature) { + return addFeature(new Feature(feature)); + } + + public DiscoverInfoBuilder addFeature(Feature feature) { + features.add(feature); + return getThis(); + } + + public DiscoverInfoBuilder addIdentities(Collection identities) { + this.identities.addAll(identities); + return getThis(); + } + + public DiscoverInfoBuilder addIdentity(Identity identity) { + identities.add(identity); + return getThis(); + } + + public DiscoverInfoBuilder setNode(String node) { + this.node = node; + return getThis(); + } + + @Override + public DiscoverInfo build() { + return new DiscoverInfo(this, true); + } + + public DiscoverInfo buildWithoutValidiation() { + return new DiscoverInfo(this, false); + } + + @Override + public List getFeatures() { + return features; + } + + @Override + public List getIdentities() { + return identities; + } + + @Override + public String getNode() { + return node; + } + + public static DiscoverInfoBuilder buildResponseFor(DiscoverInfo request, IQ.ResponseType responseType) { + DiscoverInfoBuilder builder = new DiscoverInfoBuilder(createResponse(request, responseType)); + builder.setNode(request.getNode()); + return builder; + } +} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfoView.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfoView.java new file mode 100644 index 000000000..8252f21f7 --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfoView.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.smackx.disco.packet; + +import java.util.List; + +import org.jivesoftware.smack.packet.IqView; + +public interface DiscoverInfoView extends IqView { + + /** + * Returns the discovered features of an XMPP entity. + * + * @return an unmodifiable list of the discovered features of an XMPP entity + */ + List getFeatures(); + + /** + * Returns the discovered identities of an XMPP entity. + * + * @return an unmodifiable list of the discovered identities + */ + List getIdentities(); + + /** + * Returns the node attribute that supplements the 'jid' attribute. A node is merely + * something that is associated with a JID and for which the JID can provide information.

+ * + * Node attributes SHOULD be used only when trying to provide or query information which + * is not directly addressable. + * + * @return the node attribute that supplements the 'jid' attribute + */ + String getNode(); +} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/provider/DiscoverInfoProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/provider/DiscoverInfoProvider.java index 415c4eb15..28e5d3682 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/provider/DiscoverInfoProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/provider/DiscoverInfoProvider.java @@ -19,34 +19,34 @@ package org.jivesoftware.smackx.disco.provider; import java.io.IOException; +import org.jivesoftware.smack.packet.IqData; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.parsing.SmackParsingException; -import org.jivesoftware.smack.provider.IQProvider; +import org.jivesoftware.smack.provider.IqProvider; import org.jivesoftware.smack.util.PacketParserUtils; +import org.jivesoftware.smack.util.ParserUtils; import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; +import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder; /** * The DiscoverInfoProvider parses Service Discovery information packets. * * @author Gaston Dombiak */ -public class DiscoverInfoProvider extends IQProvider { +public class DiscoverInfoProvider extends IqProvider { @Override - public DiscoverInfo parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { - DiscoverInfo discoverInfo = new DiscoverInfo(); - boolean done = false; - DiscoverInfo.Identity identity; - String category = ""; - String identityName = ""; - String type = ""; - String variable = ""; - String lang = ""; - discoverInfo.setNode(parser.getAttributeValue("", "node")); - while (!done) { + public DiscoverInfo parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment) + throws XmlPullParserException, IOException, SmackParsingException { + DiscoverInfoBuilder discoverInfoBuilder = DiscoverInfo.builder(iqData); + + String node = parser.getAttributeValue("node"); + discoverInfoBuilder.setNode(node); + + outerloop: while (true) { XmlPullParser.Event eventType = parser.next(); if (eventType == XmlPullParser.Event.START_ELEMENT) { final String name = parser.getName(); @@ -54,39 +54,31 @@ public class DiscoverInfoProvider extends IQProvider { if (namespace.equals(DiscoverInfo.NAMESPACE)) { switch (name) { case "identity": - // Initialize the variables from the parsed XML - category = parser.getAttributeValue("", "category"); - identityName = parser.getAttributeValue("", "name"); - type = parser.getAttributeValue("", "type"); - lang = parser.getAttributeValue(parser.getNamespace("xml"), "lang"); + String category = parser.getAttributeValue("category"); + String identityName = parser.getAttributeValue("name"); + String type = parser.getAttributeValue("type"); + String lang = ParserUtils.getXmlLang(parser); + DiscoverInfo.Identity identity = new DiscoverInfo.Identity(category, type, identityName, lang); + discoverInfoBuilder.addIdentity(identity); break; case "feature": - // Initialize the variables from the parsed XML - variable = parser.getAttributeValue("", "var"); + String feature = parser.getAttributeValue("var"); + discoverInfoBuilder.addFeature(feature); break; } } // Otherwise, it must be a packet extension. else { - PacketParserUtils.addExtensionElement(discoverInfo, parser, xmlEnvironment); + PacketParserUtils.addExtensionElement(discoverInfoBuilder, parser, xmlEnvironment); } } else if (eventType == XmlPullParser.Event.END_ELEMENT) { - if (parser.getName().equals("identity")) { - // Create a new identity and add it to the discovered info. - identity = new DiscoverInfo.Identity(category, type, identityName, lang); - discoverInfo.addIdentity(identity); - } - if (parser.getName().equals("feature")) { - // Create a new feature and add it to the discovered info. - boolean notADuplicateFeature = discoverInfo.addFeature(variable); - assert notADuplicateFeature; - } - if (parser.getName().equals("query")) { - done = true; + if (parser.getDepth() == initialDepth) { + break outerloop; } } } + DiscoverInfo discoverInfo = discoverInfoBuilder.buildWithoutValidiation(); return discoverInfo; } } 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/filetransfer/IncomingFileTransfer.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/IncomingFileTransfer.java index 0e972b26d..5c66d4e04 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/IncomingFileTransfer.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/IncomingFileTransfer.java @@ -110,7 +110,7 @@ public class IncomingFileTransfer extends FileTransfer { * * @param file The location to save the file. * @throws SmackException when the file transfer fails - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws IllegalArgumentException This exception is thrown when the the provided file is * either null, or cannot be written to. */ 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/iqlast/LastActivityManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/LastActivityManager.java index 3b3ea38a7..f01839f57 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/LastActivityManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/LastActivityManager.java @@ -229,7 +229,7 @@ public final class LastActivityManager extends Manager { * the JID of the user. * @return the LastActivity stanza of the jid. * @throws XMPPErrorException if there was an XMPP error returned. - * thrown if a server error has occured. + * thrown if a server error has occurred. * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/provider/PrivateDataProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/provider/PrivateDataProvider.java index 4f21a318c..60bd1e900 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/provider/PrivateDataProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/provider/PrivateDataProvider.java @@ -41,8 +41,8 @@ public interface PrivateDataProvider { * * @param parser an XML parser. * @return a new PrivateData instance. - * @throws XmlPullParserException if an error in the XML parser occured. - * @throws IOException if an I/O error occured. + * @throws XmlPullParserException if an error in the XML parser occurred. + * @throws IOException if an I/O error occurred. */ PrivateData parsePrivateData(XmlPullParser parser) throws XmlPullParserException, IOException; } 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/jiveproperties/provider/JivePropertiesExtensionProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/provider/JivePropertiesExtensionProvider.java index d88b30708..5d0efbb24 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/provider/JivePropertiesExtensionProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/provider/JivePropertiesExtensionProvider.java @@ -48,8 +48,8 @@ public class JivePropertiesExtensionProvider extends ExtensionElementProvider + * 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..747b1469f 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 @@ -27,7 +27,6 @@ import java.util.concurrent.CopyOnWriteArraySet; import java.util.logging.Level; import java.util.logging.Logger; -import org.jivesoftware.smack.AsyncButOrdered; import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.PresenceListener; import org.jivesoftware.smack.SmackException; @@ -56,6 +55,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; @@ -143,8 +143,6 @@ public class MultiUserChat { private final StanzaListener presenceListener; private final StanzaListener subjectListener; - private static final AsyncButOrdered asyncButOrdered = new AsyncButOrdered<>(); - private static final StanzaFilter DECLINE_FILTER = new AndFilter(MessageTypeFilter.NORMAL, new StanzaExtensionFilter(MUCUser.ELEMENT, MUCUser.NAMESPACE)); private final StanzaListener declinesListener; @@ -167,14 +165,9 @@ public class MultiUserChat { public void processStanza(Stanza packet) throws NotConnectedException { final Message message = (Message) packet; - asyncButOrdered.performAsyncButOrdered(MultiUserChat.this, new Runnable() { - @Override - public void run() { - for (MessageListener listener : messageListeners) { + for (MessageListener listener : messageListeners) { listener.processMessage(message); - } - } - }); + } } }; @@ -187,15 +180,10 @@ public class MultiUserChat { // Update the room subject subject = msg.getSubject(); - asyncButOrdered.performAsyncButOrdered(MultiUserChat.this, new Runnable() { - @Override - public void run() { - // Fire event for subject updated listeners - for (SubjectUpdatedListener listener : subjectUpdatedListeners) { - listener.subjectUpdated(msg.getSubject(), from); - } - } - }); + // Fire event for subject updated listeners + for (SubjectUpdatedListener listener : subjectUpdatedListeners) { + listener.subjectUpdated(msg.getSubject(), from); + } } }; @@ -211,66 +199,61 @@ public class MultiUserChat { final EntityFullJid myRoomJID = myRoomJid; final boolean isUserStatusModification = presence.getFrom().equals(myRoomJID); - asyncButOrdered.performAsyncButOrdered(MultiUserChat.this, new Runnable() { - @Override - public void run() { - switch (presence.getType()) { - case available: - Presence oldPresence = occupantsMap.put(from, presence); - if (oldPresence != null) { - // Get the previous occupant's affiliation & role - MUCUser mucExtension = MUCUser.from(oldPresence); - MUCAffiliation oldAffiliation = mucExtension.getItem().getAffiliation(); - MUCRole oldRole = mucExtension.getItem().getRole(); - // Get the new occupant's affiliation & role - mucExtension = MUCUser.from(packet); - MUCAffiliation newAffiliation = mucExtension.getItem().getAffiliation(); - MUCRole newRole = mucExtension.getItem().getRole(); - // Fire role modification events - checkRoleModifications(oldRole, newRole, isUserStatusModification, from); - // Fire affiliation modification events - checkAffiliationModifications( - oldAffiliation, - newAffiliation, - isUserStatusModification, - from); + switch (presence.getType()) { + case available: + Presence oldPresence = occupantsMap.put(from, presence); + if (oldPresence != null) { + // Get the previous occupant's affiliation & role + MUCUser mucExtension = MUCUser.from(oldPresence); + MUCAffiliation oldAffiliation = mucExtension.getItem().getAffiliation(); + MUCRole oldRole = mucExtension.getItem().getRole(); + // Get the new occupant's affiliation & role + mucExtension = MUCUser.from(packet); + MUCAffiliation newAffiliation = mucExtension.getItem().getAffiliation(); + MUCRole newRole = mucExtension.getItem().getRole(); + // Fire role modification events + checkRoleModifications(oldRole, newRole, isUserStatusModification, from); + // Fire affiliation modification events + checkAffiliationModifications( + oldAffiliation, + newAffiliation, + isUserStatusModification, + from); + } + else { + // A new occupant has joined the room + if (!isUserStatusModification) { + for (ParticipantStatusListener listener : participantStatusListeners) { + listener.joined(from); } - else { - // A new occupant has joined the room - if (!isUserStatusModification) { - for (ParticipantStatusListener listener : participantStatusListeners) { - listener.joined(from); - } - } - } - break; - case unavailable: - occupantsMap.remove(from); - MUCUser mucUser = MUCUser.from(packet); - if (mucUser != null && mucUser.hasStatus()) { - // Fire events according to the received presence code - checkPresenceCode( - mucUser.getStatus(), - presence.getFrom().equals(myRoomJID), - mucUser, - from); - } else { - // An occupant has left the room - if (!isUserStatusModification) { - for (ParticipantStatusListener listener : participantStatusListeners) { - listener.left(from); - } - } - } - break; - default: - break; - } - for (PresenceListener listener : presenceListeners) { - listener.processPresence(presence); } } - }); + break; + case unavailable: + occupantsMap.remove(from); + MUCUser mucUser = MUCUser.from(packet); + if (mucUser != null && mucUser.hasStatus()) { + // Fire events according to the received presence code + checkPresenceCode( + mucUser.getStatus(), + presence.getFrom().equals(myRoomJID), + mucUser, + from); + } else { + // An occupant has left the room + if (!isUserStatusModification) { + for (ParticipantStatusListener listener : participantStatusListeners) { + listener.left(from); + } + } + } + break; + default: + break; + } + for (PresenceListener listener : presenceListeners) { + listener.processPresence(presence); + } } }; @@ -340,13 +323,13 @@ public class MultiUserChat { Presence joinPresence = conf.getJoinPresence(this); // Setup the messageListeners and presenceListeners *before* the join presence is send. - connection.addSyncStanzaListener(messageListener, fromRoomGroupchatFilter); + connection.addStanzaListener(messageListener, fromRoomGroupchatFilter); StanzaFilter presenceFromRoomFilter = new AndFilter(fromRoomFilter, StanzaTypeFilter.PRESENCE, PossibleFromTypeFilter.ENTITY_FULL_JID); - connection.addSyncStanzaListener(presenceListener, presenceFromRoomFilter); + connection.addStanzaListener(presenceListener, presenceFromRoomFilter); // @formatter:off - connection.addSyncStanzaListener(subjectListener, + connection.addStanzaListener(subjectListener, new AndFilter(fromRoomFilter, MessageWithSubjectFilter.INSTANCE, new NotFilter(MessageTypeFilter.ERROR), @@ -356,8 +339,8 @@ public class MultiUserChat { new NotFilter(MessageWithThreadFilter.INSTANCE)) ); // @formatter:on - connection.addSyncStanzaListener(declinesListener, new AndFilter(fromRoomFilter, DECLINE_FILTER)); - connection.addStanzaInterceptor(presenceInterceptor, new AndFilter(ToMatchesFilter.create(room), + connection.addStanzaListener(declinesListener, new AndFilter(fromRoomFilter, DECLINE_FILTER)); + connection.addStanzaSendingListener(presenceInterceptor, new AndFilter(ToMatchesFilter.create(room), StanzaTypeFilter.PRESENCE)); messageCollector = connection.createStanzaCollector(fromRoomGroupchatFilter); @@ -419,7 +402,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 +727,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 +912,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 +927,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 +945,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 +1142,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 +1185,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 +1240,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); } @@ -1856,7 +1879,7 @@ public class MultiUserChat { * * @param role the role of the occupant in the room. * @return a list of Occupant that have the specified room role. - * @throws XMPPErrorException if an error occured while performing the request to the server or you + * @throws XMPPErrorException if an error occurred while performing the request to the server or you * don't have enough privileges to get this information. * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException if the XMPP connection is not connected. @@ -1887,8 +1910,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 +1938,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 +1968,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 +2080,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 +2090,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(); } @@ -2044,11 +2100,11 @@ public class MultiUserChat { * connection. */ private void removeConnectionCallbacks() { - connection.removeSyncStanzaListener(messageListener); - connection.removeSyncStanzaListener(presenceListener); - connection.removeSyncStanzaListener(subjectListener); - connection.removeSyncStanzaListener(declinesListener); - connection.removeStanzaInterceptor(presenceInterceptor); + connection.removeStanzaListener(messageListener); + connection.removeStanzaListener(presenceListener); + connection.removeStanzaListener(subjectListener); + connection.removeStanzaListener(declinesListener); + connection.removeStanzaSendingListener(presenceInterceptor); if (messageCollector != null) { messageCollector.cancel(); messageCollector = null; 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/muc/provider/MUCUserProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/provider/MUCUserProvider.java index 4eed95435..879319c9e 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/provider/MUCUserProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/provider/MUCUserProvider.java @@ -43,8 +43,8 @@ public class MUCUserProvider extends ExtensionElementProvider { * * @param parser the XML parser, positioned at the starting element of the extension. * @return a PacketExtension. - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. */ @Override public MUCUser parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/packet/OfflineMessageInfo.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/packet/OfflineMessageInfo.java index ee80d5a9b..8ce910ca1 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/packet/OfflineMessageInfo.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/packet/OfflineMessageInfo.java @@ -99,8 +99,8 @@ public class OfflineMessageInfo implements ExtensionElement { * * @param parser the XML parser, positioned at the starting element of the extension. * @return a PacketExtension. - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. */ @Override public OfflineMessageInfo parse(XmlPullParser parser, 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..ac46a76c4 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.IqData; 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().buildIqData(), to); + } + + public Ping(IqData iqBuilder, Jid to) { + super(iqBuilder.to(to).ofType(IQ.Type.get), ELEMENT, NAMESPACE); + } + + public Ping(IqData iqBuilder) { + super(iqBuilder, ELEMENT, NAMESPACE); + } + /** * Create an XMPP Pong for this Ping. * diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ConfigureForm.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ConfigureForm.java index 4c99a8867..91921eee7 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ConfigureForm.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ConfigureForm.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.List; import org.jivesoftware.smack.util.ParserUtils; + import org.jivesoftware.smackx.xdata.Form; import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.packet.DataForm; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java index 2af5c3b19..815a05bd2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java @@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.StanzaListener; +import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.filter.FlexibleStanzaTypeFilter; import org.jivesoftware.smack.filter.OrFilter; @@ -120,10 +121,12 @@ public abstract class Node { * @throws InterruptedException if the calling thread was interrupted. */ public DiscoverInfo discoverInfo() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - DiscoverInfo info = new DiscoverInfo(); - info.setTo(pubSubManager.getServiceJid()); - info.setNode(getId()); - return pubSubManager.getConnection().createStanzaCollectorAndSend(info).nextResultOrThrow(); + XMPPConnection connection = pubSubManager.getConnection(); + DiscoverInfo discoverInfoRequest = DiscoverInfo.builder(connection) + .to(pubSubManager.getServiceJid()) + .setNode(getId()) + .build(); + return connection.createStanzaCollectorAndSend(discoverInfoRequest).nextResultOrThrow(); } /** diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java index be92f373b..89dd1c761 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java @@ -289,11 +289,13 @@ public final class PubSubManager extends Manager { Node node = nodeMap.get(id); if (node == null) { - DiscoverInfo info = new DiscoverInfo(); - info.setTo(pubSubService); - info.setNode(id); + XMPPConnection connection = connection(); + DiscoverInfo info = DiscoverInfo.builder(connection) + .to(pubSubService) + .setNode(id) + .build(); - DiscoverInfo infoReply = connection().createStanzaCollectorAndSend(info).nextResultOrThrow(); + DiscoverInfo infoReply = connection.createStanzaCollectorAndSend(info).nextResultOrThrow(); if (infoReply.hasIdentity(PubSub.ELEMENT, "leaf")) { node = new LeafNode(this, id); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/SubscribeForm.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/SubscribeForm.java index 857c61054..cdcaffaf5 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/SubscribeForm.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/SubscribeForm.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.UnknownFormatConversionException; import org.jivesoftware.smack.util.ParserUtils; + import org.jivesoftware.smackx.xdata.Form; import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.packet.DataForm; 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..b069709e1 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/receipts/DeliveryReceiptManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/receipts/DeliveryReceiptManager.java @@ -38,8 +38,11 @@ import org.jivesoftware.smack.filter.StanzaExtensionFilter; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaBuilder; import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.util.Consumer; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; @@ -270,13 +273,7 @@ public final class DeliveryReceiptManager extends Manager { ); // @formatter:on - private static final StanzaListener AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER = new StanzaListener() { - @Override - public void processStanza(Stanza packet) throws NotConnectedException { - Message message = (Message) packet; - DeliveryReceiptRequest.addTo(message); - } - }; + private static final Consumer AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER = mb -> DeliveryReceiptRequest.addTo(mb); /** * Enables automatic requests of delivery receipts for outgoing messages of @@ -287,8 +284,9 @@ public final class DeliveryReceiptManager extends Manager { * @see #dontAutoAddDeliveryReceiptRequests() */ public void autoAddDeliveryReceiptRequests() { - connection().addStanzaInterceptor(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER, - MESSAGES_TO_REQUEST_RECEIPTS_FOR); + connection().addMessageInterceptor(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER, m -> { + return MESSAGES_TO_REQUEST_RECEIPTS_FOR.accept(m); + }); } /** @@ -298,7 +296,7 @@ public final class DeliveryReceiptManager extends Manager { * @see #autoAddDeliveryReceiptRequests() */ public void dontAutoAddDeliveryReceiptRequests() { - connection().removeStanzaInterceptor(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER); + connection().removeMessageInterceptor(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER); } /** @@ -342,8 +340,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/usertune/UserTuneListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneListener.java index c513579fc..e020e4ec2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneListener.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneListener.java @@ -17,6 +17,7 @@ package org.jivesoftware.smackx.usertune; import org.jivesoftware.smack.packet.Message; + import org.jivesoftware.smackx.usertune.element.UserTuneElement; import org.jxmpp.jid.BareJid; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneManager.java index 70dd900b1..415c53dcc 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneManager.java @@ -31,6 +31,7 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Message; + import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.pep.PepListener; import org.jivesoftware.smackx.pep.PepManager; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/provider/UserTuneProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/provider/UserTuneProvider.java index 5b1c423ef..3679c993d 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/provider/UserTuneProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/provider/UserTuneProvider.java @@ -25,6 +25,7 @@ import org.jivesoftware.smack.provider.ExtensionElementProvider; import org.jivesoftware.smack.util.ParserUtils; import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; + import org.jivesoftware.smackx.usertune.element.UserTuneElement; /** 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/main/java/org/jivesoftware/smackx/xdata/packet/DataForm.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/packet/DataForm.java index 79360a471..12d3bcab8 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/packet/DataForm.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/packet/DataForm.java @@ -25,9 +25,11 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.packet.Element; import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaView; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.util.XmlStringBuilder; @@ -44,6 +46,8 @@ public class DataForm implements ExtensionElement { public static final String NAMESPACE = "jabber:x:data"; public static final String ELEMENT = "x"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); + public enum Type { /** * This stanza contains a form to fill out. Display it to the user (if your program can). @@ -351,12 +355,13 @@ public class DataForm implements ExtensionElement { } /** - * Get data form from stanza. - * @param packet TODO javadoc me please + * Get data form from a stanza. + * + * @param stanzaView the stanza to get data form from. * @return the DataForm or null */ - public static DataForm from(Stanza packet) { - return (DataForm) packet.getExtension(ELEMENT, NAMESPACE); + public static DataForm from(StanzaView stanzaView) { + return (DataForm) stanzaView.getExtension(QNAME); } /** diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java index a87124fa5..39713f951 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java @@ -21,8 +21,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageView; import org.jivesoftware.smack.util.XmlStringBuilder; /** @@ -40,6 +42,8 @@ public class XHTMLExtension implements ExtensionElement { public static final String ELEMENT = "html"; public static final String NAMESPACE = "http://jabber.org/protocol/xhtml-im"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); + private final List bodies = new ArrayList<>(); /** @@ -125,7 +129,7 @@ public class XHTMLExtension implements ExtensionElement { } } - public static XHTMLExtension from(Message message) { - return message.getExtension(ELEMENT, NAMESPACE); + public static XHTMLExtension from(MessageView message) { + return message.getExtension(QNAME); } } diff --git a/smack-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..6c9b2f9f7 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 @@ -49,6 +49,7 @@ import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity; +import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder; import org.jivesoftware.smackx.disco.packet.DiscoverItems; import org.jivesoftware.smackx.disco.packet.DiscoverItems.Item; @@ -134,7 +135,7 @@ public class Socks5ByteStreamManagerTest { * @throws XMPPException if an XMPP protocol error was received. * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException if Smack detected an exceptional situation. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ @Test public void shouldFailIfTargetDoesNotSupportSocks5() @@ -145,7 +146,7 @@ public class Socks5ByteStreamManagerTest { FeatureNotSupportedException e = assertThrows(FeatureNotSupportedException.class, () -> { // build empty discover info as reply if targets features are queried - DiscoverInfo discoverInfo = new DiscoverInfo(); + DiscoverInfo discoverInfo = DiscoverInfo.builder("disco-1").build(); protocol.addResponse(discoverInfo); // start SOCKS5 Bytestream @@ -162,7 +163,7 @@ public class Socks5ByteStreamManagerTest { * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException if Smack detected an exceptional situation. * @throws XMPPException if an XMPP protocol error was received. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ @Test public void shouldFailIfNoSocks5ProxyFound1() @@ -181,11 +182,11 @@ public class Socks5ByteStreamManagerTest { */ // build discover info that supports the SOCKS5 feature - DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); + DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); discoverInfo.addFeature(Bytestream.NAMESPACE); // return that SOCKS5 is supported if target is queried - protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build discover items with no proxy items @@ -214,7 +215,7 @@ public class Socks5ByteStreamManagerTest { * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException if Smack detected an exceptional situation. * @throws XMPPException if an XMPP protocol error was received. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ @Test public void shouldFailIfNoSocks5ProxyFound2() @@ -233,11 +234,11 @@ public class Socks5ByteStreamManagerTest { */ // build discover info that supports the SOCKS5 feature - DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); + DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); discoverInfo.addFeature(Bytestream.NAMESPACE); // return that SOCKS5 is supported if target is queried - protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build discover items containing a proxy item @@ -252,12 +253,12 @@ public class Socks5ByteStreamManagerTest { // build discover info for proxy containing information about NOT being a Socks5 // proxy - DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); + DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); Identity identity = new Identity("noproxy", proxyJID.toString(), "bytestreams"); proxyInfo.addIdentity(identity); // return the proxy identity if proxy is queried - protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); SmackException e = assertThrows(SmackException.class, () -> { @@ -276,7 +277,7 @@ public class Socks5ByteStreamManagerTest { * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException if Smack detected an exceptional situation. * @throws XMPPException if an XMPP protocol error was received. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ @Test public void shouldBlacklistNonSocks5Proxies() throws SmackException, InterruptedException, IOException, XMPPException { @@ -294,9 +295,10 @@ public class Socks5ByteStreamManagerTest { */ // build discover info that supports the SOCKS5 feature - DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); - discoverInfo.addFeature(Bytestream.NAMESPACE); + DiscoverInfoBuilder discoverInfoBuilder = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); + discoverInfoBuilder.addFeature(Bytestream.NAMESPACE); + DiscoverInfo discoverInfo = discoverInfoBuilder.build(); // return that SOCKS5 is supported if target is queried protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver, Verification.requestTypeGET); @@ -313,12 +315,12 @@ public class Socks5ByteStreamManagerTest { // build discover info for proxy containing information about NOT being a Socks5 // proxy - DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); + DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); Identity identity = new Identity("noproxy", proxyJID.toString(), "bytestreams"); proxyInfo.addIdentity(identity); // return the proxy identity if proxy is queried - protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); SmackException e = assertThrows(SmackException.class, () -> { @@ -358,7 +360,7 @@ public class Socks5ByteStreamManagerTest { * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException if Smack detected an exceptional situation. * @throws XMPPException if an XMPP protocol error was received. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ @Test public void shouldFailIfTargetDoesNotAcceptSocks5Bytestream() throws SmackException, InterruptedException, IOException, XMPPException { @@ -376,11 +378,11 @@ public class Socks5ByteStreamManagerTest { */ // build discover info that supports the SOCKS5 feature - DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); + DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); discoverInfo.addFeature(Bytestream.NAMESPACE); // return that SOCKS5 is supported if target is queried - protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build discover items containing a proxy item @@ -394,12 +396,12 @@ public class Socks5ByteStreamManagerTest { Verification.requestTypeGET); // build discover info for proxy containing information about being a SOCKS5 proxy - DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); + DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams"); proxyInfo.addIdentity(identity); // return the socks5 bytestream proxy identity if proxy is queried - protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build a socks5 stream host info containing the address and the port of the @@ -413,8 +415,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); @@ -438,7 +440,7 @@ public class Socks5ByteStreamManagerTest { * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException if Smack detected an exceptional situation. * @throws XMPPException if an XMPP protocol error was received. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ @Test public void shouldFailIfTargetUsesInvalidSocks5Proxy() @@ -458,11 +460,11 @@ public class Socks5ByteStreamManagerTest { */ // build discover info that supports the SOCKS5 feature - DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); + DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); discoverInfo.addFeature(Bytestream.NAMESPACE); // return that SOCKS5 is supported if target is queried - protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build discover items containing a proxy item @@ -476,12 +478,12 @@ public class Socks5ByteStreamManagerTest { Verification.requestTypeGET); // build discover info for proxy containing information about being a SOCKS5 proxy - DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); + DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams"); proxyInfo.addIdentity(identity); // return the socks5 bytestream proxy identity if proxy is queried - protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build a socks5 stream host info containing the address and the port of the @@ -545,11 +547,11 @@ public class Socks5ByteStreamManagerTest { */ // build discover info that supports the SOCKS5 feature - DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); - discoverInfo.addFeature(Bytestream.NAMESPACE); + DiscoverInfoBuilder discoverInfoBuilder = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); + discoverInfoBuilder.addFeature(Bytestream.NAMESPACE); // return that SOCKS5 is supported if target is queried - protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(discoverInfoBuilder.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build discover items containing a proxy item @@ -563,12 +565,12 @@ public class Socks5ByteStreamManagerTest { Verification.requestTypeGET); // build discover info for proxy containing information about being a SOCKS5 proxy - DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); + DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams"); proxyInfo.addIdentity(identity); // return the socks5 bytestream proxy identity if proxy is queried - protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build a socks5 stream host info containing the address and the port of the @@ -620,7 +622,7 @@ public class Socks5ByteStreamManagerTest { * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException if Smack detected an exceptional situation. * @throws XMPPException if an XMPP protocol error was received. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ @Test public void shouldNegotiateSocks5BytestreamAndTransferData() @@ -639,11 +641,11 @@ public class Socks5ByteStreamManagerTest { */ // build discover info that supports the SOCKS5 feature - DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); + DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); discoverInfo.addFeature(Bytestream.NAMESPACE); // return that SOCKS5 is supported if target is queried - protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build discover items containing a proxy item @@ -657,12 +659,12 @@ public class Socks5ByteStreamManagerTest { Verification.requestTypeGET); // build discover info for proxy containing information about being a SOCKS5 proxy - DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); + DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams"); proxyInfo.addIdentity(identity); // return the socks5 bytestream proxy identity if proxy is queried - protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build a socks5 stream host info containing the address and the port of the @@ -739,7 +741,7 @@ public class Socks5ByteStreamManagerTest { * * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException if Smack detected an exceptional situation. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws XMPPException if an XMPP protocol error was received. * @throws TimeoutException if there was a timeout. */ @@ -765,11 +767,11 @@ public class Socks5ByteStreamManagerTest { */ // build discover info that supports the SOCKS5 feature - DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); + DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); discoverInfo.addFeature(Bytestream.NAMESPACE); // return that SOCKS5 is supported if target is queried - protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build discover items containing no proxy item @@ -846,7 +848,7 @@ public class Socks5ByteStreamManagerTest { * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException if Smack detected an exceptional situation. * @throws XMPPException if an XMPP protocol error was received. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * */ @Test @@ -932,7 +934,7 @@ public class Socks5ByteStreamManagerTest { * should successfully negotiate a SOCKS5 Bytestream via the second SOCKS5 proxy. The second * negotiation should run in the same manner if prioritization is disabled. * - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException if Smack detected an exceptional situation. * @throws XMPPException if an XMPP protocol error was received. @@ -1009,11 +1011,11 @@ public class Socks5ByteStreamManagerTest { Verification streamHostUsedVerification, Socks5TestProxy socks5TestProxy) throws XmppStringprepException { // build discover info that supports the SOCKS5 feature - DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); + DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID); discoverInfo.addFeature(Bytestream.NAMESPACE); // return that SOCKS5 is supported if target is queried - protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver, + protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build discover items containing a proxy item @@ -1030,22 +1032,22 @@ public class Socks5ByteStreamManagerTest { * build discover info for proxy "proxy2.xmpp-server" containing information about being a * SOCKS5 proxy */ - DiscoverInfo proxyInfo1 = Socks5PacketUtils.createDiscoverInfo(JidCreate.from("proxy2.xmpp-server"), + DiscoverInfoBuilder proxyInfo1 = Socks5PacketUtils.createDiscoverInfo(JidCreate.from("proxy2.xmpp-server"), initiatorJID); Identity identity1 = new Identity("proxy", "proxy2.xmpp-server", "bytestreams"); proxyInfo1.addIdentity(identity1); // return the SOCKS5 bytestream proxy identity if proxy is queried - protocol.addResponse(proxyInfo1, Verification.correspondingSenderReceiver, + protocol.addResponse(proxyInfo1.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); // build discover info for proxy containing information about being a SOCKS5 proxy - DiscoverInfo proxyInfo2 = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); + DiscoverInfoBuilder proxyInfo2 = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID); Identity identity2 = new Identity("proxy", proxyJID.toString(), "bytestreams"); proxyInfo2.addIdentity(identity2); // return the SOCKS5 bytestream proxy identity if proxy is queried - protocol.addResponse(proxyInfo2, Verification.correspondingSenderReceiver, + protocol.addResponse(proxyInfo2.build(), Verification.correspondingSenderReceiver, Verification.requestTypeGET); /* 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/bytestreams/socks5/Socks5PacketUtils.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5PacketUtils.java index d6e9ca3b1..b5cee4cc7 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5PacketUtils.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5PacketUtils.java @@ -21,6 +21,7 @@ import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; +import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder; import org.jivesoftware.smackx.disco.packet.DiscoverItems; import org.jxmpp.jid.Jid; @@ -88,11 +89,12 @@ public class Socks5PacketUtils { * @param to the initiator * @return response to an info discovery request */ - public static DiscoverInfo createDiscoverInfo(Jid from, Jid to) { - DiscoverInfo discoverInfo = new DiscoverInfo(); - discoverInfo.setFrom(from); - discoverInfo.setTo(to); - discoverInfo.setType(IQ.Type.result); + public static DiscoverInfoBuilder createDiscoverInfo(Jid from, Jid to) { + DiscoverInfoBuilder discoverInfo = DiscoverInfo.builder("disco-1") + .from(from) + .to(to) + .ofType(IQ.Type.result) + ; return discoverInfo; } diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/caps/EntityCapsManagerTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/caps/EntityCapsManagerTest.java index 518d0142e..739cae26e 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/caps/EntityCapsManagerTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/caps/EntityCapsManagerTest.java @@ -34,6 +34,7 @@ import org.jivesoftware.smackx.InitExtensions; import org.jivesoftware.smackx.caps.cache.EntityCapsPersistentCache; import org.jivesoftware.smackx.caps.cache.SimpleDirectoryPersistentCache; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; +import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder; import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.packet.DataForm; @@ -97,11 +98,10 @@ public class EntityCapsManagerTest extends InitExtensions { } private static DiscoverInfo createComplexSamplePacket() throws XmppStringprepException { - DiscoverInfo di = new DiscoverInfo(); - di.setFrom(JidCreate.from("benvolio@capulet.lit/230193")); - di.setStanzaId("disco1"); - di.setTo(JidCreate.from("juliet@capulet.lit/chamber")); - di.setType(IQ.Type.result); + DiscoverInfoBuilder di = DiscoverInfo.builder("disco1"); + di.from(JidCreate.from("benvolio@capulet.lit/230193")); + di.to(JidCreate.from("juliet@capulet.lit/chamber")); + di.ofType(IQ.Type.result); Collection identities = new LinkedList(); DiscoverInfo.Identity i = new DiscoverInfo.Identity("client", "pc", "Psi 0.11", "en"); @@ -144,15 +144,14 @@ public class EntityCapsManagerTest extends InitExtensions { df.addField(ff.build()); di.addExtension(df); - return di; + return di.build(); } private static DiscoverInfo createMalformedDiscoverInfo() throws XmppStringprepException { - DiscoverInfo di = new DiscoverInfo(); - di.setFrom(JidCreate.from("benvolio@capulet.lit/230193")); - di.setStanzaId("disco1"); - di.setTo(JidCreate.from(")juliet@capulet.lit/chamber")); - di.setType(IQ.Type.result); + DiscoverInfoBuilder di = DiscoverInfo.builder("disco1"); + di.from("benvolio@capulet.lit/230193"); + di.to(")juliet@capulet.lit/chamber"); + di.ofType(IQ.Type.result); Collection identities = new LinkedList(); DiscoverInfo.Identity i = new DiscoverInfo.Identity("client", "pc", "Psi 0.11", "en"); @@ -217,7 +216,8 @@ public class EntityCapsManagerTest extends InitExtensions { di.addExtension(df); - return di; + DiscoverInfo discoverInfo = di.buildWithoutValidiation(); + return discoverInfo; } public static File createTempDirectory() throws IOException { 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/muc/RoomInfoTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/muc/RoomInfoTest.java index ddf453218..f809ca094 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/muc/RoomInfoTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/muc/RoomInfoTest.java @@ -30,8 +30,9 @@ public class RoomInfoTest { public void validateRoomWithEmptyForm() { DataForm dataForm = new DataForm(DataForm.Type.result); - DiscoverInfo discoInfo = new DiscoverInfo(); - discoInfo.addExtension(dataForm); + DiscoverInfo discoInfo = DiscoverInfo.builder("disco1") + .addExtension(dataForm) + .build(); RoomInfo roomInfo = new RoomInfo(discoInfo); assertTrue(roomInfo.getDescription().isEmpty()); assertTrue(roomInfo.getSubject().isEmpty()); @@ -54,8 +55,9 @@ public class RoomInfoTest { occupants.addValue("3"); dataForm.addField(occupants.build()); - DiscoverInfo discoInfo = new DiscoverInfo(); - discoInfo.addExtension(dataForm); + DiscoverInfo discoInfo = DiscoverInfo.builder("disco1") + .addExtension(dataForm) + .build(); RoomInfo roomInfo = new RoomInfo(discoInfo); assertEquals("The place for all good witches!", roomInfo.getDescription()); assertEquals("Spells", roomInfo.getSubject()); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/ping/PingTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/ping/PingTest.java index 3eef31b83..37082a358 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/ping/PingTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/ping/PingTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2012-2014 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. @@ -36,7 +36,6 @@ import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smackx.InitExtensions; -import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.ping.packet.Ping; import org.junit.Test; @@ -100,7 +99,7 @@ public class PingTest extends InitExtensions { * DummyConnection will not reply so it will timeout. * @throws SmackException if Smack detected an exceptional situation. * @throws XMPPException if an XMPP protocol error was received. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws InterruptedException if the calling thread was interrupted. */ @Test @@ -191,8 +190,6 @@ public class PingTest extends InitExtensions { @Test public void checkSuccessfulDiscoRequest() throws Exception { ThreadedDummyConnection con = getAuthenticatedDummyConnection(); - DiscoverInfo info = new DiscoverInfo(); - info.addFeature(Ping.NAMESPACE); // @formatter:off String reply = @@ -213,8 +210,6 @@ public class PingTest extends InitExtensions { @Test public void checkUnsuccessfulDiscoRequest() throws Exception { ThreadedDummyConnection con = getAuthenticatedDummyConnection(); - DiscoverInfo info = new DiscoverInfo(); - info.addFeature(Ping.NAMESPACE); // @formatter:off String reply = @@ -244,7 +239,7 @@ public class PingTest extends InitExtensions { * * @return * @throws XMPPException if an XMPP protocol error was received. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws SmackException if Smack detected an exceptional situation. * @throws InterruptedException if the calling thread was interrupted. */ 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..d9fff1e03 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 @@ -26,6 +26,7 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.ThreadedDummyConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException.XMPPErrorException; +import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ.Type; import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smack.packet.StanzaError.Condition; @@ -33,6 +34,7 @@ import org.jivesoftware.smack.packet.StanzaError.Condition; import org.jivesoftware.smackx.InitExtensions; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity; +import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder; import org.jivesoftware.smackx.pubsub.packet.PubSub; import org.jivesoftware.smackx.xdata.packet.DataForm; @@ -55,19 +57,21 @@ public class ConfigureFormTest extends InitExtensions { public void getConfigFormWithInsufficientPrivileges() throws XMPPException, SmackException, IOException, InterruptedException { ThreadedDummyConnection con = ThreadedDummyConnection.newInstance(); PubSubManager mgr = new PubSubManager(con, PubSubManagerTest.DUMMY_PUBSUB_SERVICE); - DiscoverInfo info = new DiscoverInfo(); - info.setType(Type.result); - info.setFrom(PubSubManagerTest.DUMMY_PUBSUB_SERVICE); + DiscoverInfoBuilder info = DiscoverInfo.builder("disco-result") + .ofType(IQ.Type.result) + .from(PubSubManagerTest.DUMMY_PUBSUB_SERVICE); Identity ident = new Identity("pubsub", null, "leaf"); info.addIdentity(ident); - con.addIQReply(info); + + DiscoverInfo discoverInfo = info.build(); + con.addIQReply(discoverInfo); Node node = mgr.getNode("princely_musings"); 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); @@ -84,10 +88,12 @@ public class ConfigureFormTest extends InitExtensions { public void getConfigFormWithTimeout() throws XMPPException, SmackException, InterruptedException { ThreadedDummyConnection con = new ThreadedDummyConnection(); PubSubManager mgr = new PubSubManager(con, PubSubManagerTest.DUMMY_PUBSUB_SERVICE); - DiscoverInfo info = new DiscoverInfo(); + DiscoverInfoBuilder info = DiscoverInfo.builder("disco-result"); Identity ident = new Identity("pubsub", null, "leaf"); info.addIdentity(ident); - con.addIQReply(info); + + DiscoverInfo discoverInfo = info.build(); + con.addIQReply(discoverInfo); Node node = mgr.getNode("princely_musings"); 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/UserTuneElementTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/usertune/UserTuneElementTest.java index 9aea03774..56fb1af4e 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/usertune/UserTuneElementTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/usertune/UserTuneElementTest.java @@ -28,6 +28,7 @@ import org.jivesoftware.smack.test.util.SmackTestUtil; import org.jivesoftware.smack.test.util.SmackTestUtil.XmlPullParserKind; import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; + import org.jivesoftware.smackx.usertune.element.UserTuneElement; import org.jivesoftware.smackx.usertune.provider.UserTuneProvider; 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..64928de56 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,7 +24,9 @@ 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; import org.junit.Test; @@ -45,8 +47,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-extensions/src/test/java/org/jivesoftware/util/ConnectionUtils.java b/smack-extensions/src/test/java/org/jivesoftware/util/ConnectionUtils.java index cc90c29ca..910d73ee7 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/util/ConnectionUtils.java +++ b/smack-extensions/src/test/java/org/jivesoftware/util/ConnectionUtils.java @@ -30,6 +30,8 @@ import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.packet.StanzaFactory; +import org.jivesoftware.smack.packet.id.StandardStanzaIdSource; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; @@ -78,6 +80,9 @@ public class ConnectionUtils { when(connection.getUser()).thenReturn(initiatorJID); when(connection.getXMPPServiceDomain()).thenReturn(xmppServer); + final StanzaFactory stanzaFactory = new StanzaFactory(new StandardStanzaIdSource()); + when(connection.getStanzaFactory()).thenReturn(stanzaFactory); + // mock packet collector final StanzaCollector collector = mock(StanzaCollector.class); when(connection.createStanzaCollector(isA(StanzaFilter.class))).thenReturn( 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/RosterGroup.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterGroup.java index e67f3e6fc..19e7cacab 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterGroup.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterGroup.java @@ -165,7 +165,7 @@ public class RosterGroup extends Manager { * to receive the updated roster. * * @param entry a roster entry. - * @throws XMPPErrorException if an error occured while trying to add the entry to the group. + * @throws XMPPErrorException if an error occurred while trying to add the entry to the group. * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. 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/LoginIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/LoginIntegrationTest.java index 541de5163..07a239b00 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/LoginIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/LoginIntegrationTest.java @@ -43,7 +43,7 @@ public class LoginIntegrationTest extends AbstractSmackLowLevelIntegrationTest { * * @throws InterruptedException if the calling thread was interrupted. * @throws XMPPException if an XMPP protocol error was received. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws SmackException if Smack detected an exceptional situation. * @throws NoSuchAlgorithmException if no such algorithm is available. * @throws KeyManagementException if there was a key mangement error. 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/smack/chat2/OutgoingMessageListenerIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/chat2/OutgoingMessageListenerIntegrationTest.java index 6ea68d7f4..c284495fa 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/chat2/OutgoingMessageListenerIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/chat2/OutgoingMessageListenerIntegrationTest.java @@ -17,6 +17,7 @@ package org.jivesoftware.smack.chat2; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.util.StringUtils; import org.igniterealtime.smack.inttest.SmackIntegrationTest; @@ -36,7 +37,8 @@ public class OutgoingMessageListenerIntegrationTest extends AbstractChatIntegrat final SimpleResultSyncPoint syncPoint = new SimpleResultSyncPoint(); final OutgoingChatMessageListener listener = new OutgoingChatMessageListener() { @Override - public void newOutgoingMessage(EntityBareJid to, Message message, Chat chat) { + public void newOutgoingMessage(EntityBareJid to, MessageBuilder messageBuilder, Chat chat) { + Message message = messageBuilder.build(); if (message.getBody().equals(body)) { syncPoint.signal(); } 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/integration-test/java/org/jivesoftware/smackx/jingle/JingleManagerTest.java b/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/JingleManagerTest.java index 49c89c355..13cdd8e0e 100644 --- a/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/JingleManagerTest.java +++ b/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/JingleManagerTest.java @@ -234,7 +234,7 @@ public class JingleManagerTest extends SmackTestCase { } catch (Exception e) { LOGGER.log(Level.WARNING, "exception", e); - fail("An error occured with Jingle"); + fail("An error occurred with Jingle"); } } @@ -294,7 +294,7 @@ public class JingleManagerTest extends SmackTestCase { } catch (Exception e) { LOGGER.log(Level.WARNING, "exception", e); - fail("An error occured with Jingle"); + fail("An error occurred with Jingle"); } } @@ -385,7 +385,7 @@ public class JingleManagerTest extends SmackTestCase { } catch (Exception e) { LOGGER.log(Level.WARNING, "exception", e); - fail("An error occured with Jingle"); + fail("An error occurred with Jingle"); } } @@ -499,7 +499,7 @@ public class JingleManagerTest extends SmackTestCase { } catch (Exception e) { LOGGER.log(Level.WARNING, "exception", e); - fail("An error occured with Jingle"); + fail("An error occurred with Jingle"); } } @@ -589,7 +589,7 @@ public class JingleManagerTest extends SmackTestCase { } catch (Exception e) { LOGGER.log(Level.WARNING, "exception", e); - fail("An error occured with Jingle"); + fail("An error occurred with Jingle"); } } @@ -985,7 +985,7 @@ public class JingleManagerTest extends SmackTestCase { // // } catch (Exception e) { // LOGGER.log(Level.WARNING, "exception", e); -// fail("An error occured with Jingle"); +// fail("An error occurred with Jingle"); // } // } diff --git a/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/STUNResolverTest.java b/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/STUNResolverTest.java index 2f1ee9b92..5d9425a92 100644 --- a/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/STUNResolverTest.java +++ b/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/STUNResolverTest.java @@ -396,7 +396,7 @@ public class STUNResolverTest extends SmackTestCase { } catch (Exception e) { LOGGER.log(Level.WARNING, "exception", e); - fail("An error occured with Jingle"); + fail("An error occurred with Jingle"); } } 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-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jspeex/AudioMediaSession.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jspeex/AudioMediaSession.java index 229a1521f..555836732 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jspeex/AudioMediaSession.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jspeex/AudioMediaSession.java @@ -70,7 +70,7 @@ public class AudioMediaSession extends JingleMediaSession implements MediaSessio * @return MediaSession TODO javadoc me please * @throws NoProcessorException if there is no media processor. * @throws UnsupportedFormatException if the format is not supported. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws GeneralSecurityException if there was a geneeral security exception. */ public static MediaSession createSession(String localhost, int localPort, String remoteHost, int remotePort, MediaSessionListener eventHandler, int quality, boolean secure, boolean micOn) throws NoProcessorException, UnsupportedFormatException, IOException, GeneralSecurityException { diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleContentDescriptionProvider.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleContentDescriptionProvider.java index 5d2f90bc3..afba58713 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleContentDescriptionProvider.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleContentDescriptionProvider.java @@ -65,8 +65,8 @@ public abstract class JingleContentDescriptionProvider extends ExtensionElementP * * @param parser the input to parse * @return a description element - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. */ @Override public JingleContentDescription parse(XmlPullParser parser, diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleDescriptionProvider.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleDescriptionProvider.java index 124258680..c446a3958 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleDescriptionProvider.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleDescriptionProvider.java @@ -66,8 +66,8 @@ public abstract class JingleDescriptionProvider extends ExtensionElementProvider * @param parser TODO javadoc me please * the input to parse * @return a description element - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. */ @Override public JingleDescription parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException { diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleProvider.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleProvider.java index f717d7303..0d6003351 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleProvider.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleProvider.java @@ -45,8 +45,8 @@ public class JingleProvider extends IQProvider { /** * Parse a iq/jingle element. - * @throws XmlPullParserException if an error in the XML parser occured. - * @throws IOException if an I/O error occured. + * @throws XmlPullParserException if an error in the XML parser occurred. + * @throws IOException if an I/O error occurred. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input. */ @Override diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleTransportProvider.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleTransportProvider.java index 87d39360b..12d98e8a1 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleTransportProvider.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleTransportProvider.java @@ -49,8 +49,8 @@ public abstract class JingleTransportProvider extends ExtensionElementProvider 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 +239,7 @@ public class AgentRoster { } } if (presence == null) { - presence = new Presence(Presence.Type.unavailable); - presence.setFrom(user); + presence = synthesizeUnvailablePresence(user); return presence; } else { @@ -289,6 +291,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..a141b50c0 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,6 +45,7 @@ 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; @@ -335,8 +336,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 +357,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 +433,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 +484,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/packet/MetaDataProvider.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/MetaDataProvider.java index 297ce40d9..7bc257d0e 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/MetaDataProvider.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/MetaDataProvider.java @@ -38,8 +38,8 @@ public class MetaDataProvider extends ExtensionElementProvider { /** * PacketExtensionProvider implementation. - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. */ @Override public MetaData parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException { diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/WorkgroupInformation.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/WorkgroupInformation.java index 9880f5eac..6df4ad29e 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/WorkgroupInformation.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/WorkgroupInformation.java @@ -79,8 +79,8 @@ public class WorkgroupInformation implements ExtensionElement { /** * PacketExtensionProvider implementation. - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. */ @Override public WorkgroupInformation parse(XmlPullParser parser, 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/xevent/provider/MessageEventProvider.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/xevent/provider/MessageEventProvider.java index da31a5f5f..dff03a746 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/xevent/provider/MessageEventProvider.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/xevent/provider/MessageEventProvider.java @@ -39,8 +39,8 @@ public class MessageEventProvider extends ExtensionElementProvider * * @param parser the XML parser, positioned at the starting element of the extension. * @return a PacketExtension. - * @throws IOException if an I/O error occured. - * @throws XmlPullParserException if an error in the XML parser occured. + * @throws IOException if an I/O error occurred. + * @throws XmlPullParserException if an error in the XML parser occurred. */ @Override public MessageEvent parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) 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-legacy/src/main/java/org/jivesoftware/smackx/xroster/provider/RosterExchangeProvider.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/provider/RosterExchangeProvider.java index 3013b92a8..c0248c99b 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/provider/RosterExchangeProvider.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/provider/RosterExchangeProvider.java @@ -44,8 +44,8 @@ public class RosterExchangeProvider extends ExtensionElementProvider getParameters() throws IOException { 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..a3d2ff48d 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; @@ -234,7 +235,7 @@ public final class OmemoManager extends Manager { * @throws XMPPException.XMPPErrorException if there was an XMPP error returned. * @throws SmackException.NotLoggedInException if the XMPP connection is not authenticated. * @throws PubSubException.NotALeafNodeException if a PubSub leaf node operation was attempted on a non-leaf node. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public synchronized void initialize() throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, InterruptedException, @@ -278,7 +279,7 @@ public final class OmemoManager extends Manager { * @see #requestDeviceListUpdateFor(BareJid) * @param contact contact we want to get a set of device of. * @return set of known devices of that contact. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public Set getDevicesOf(BareJid contact) throws IOException { OmemoCachedDeviceList list = getOmemoService().getOmemoStoreBackend().loadCachedDeviceList(getOwnDevice(), contact); @@ -304,7 +305,7 @@ public final class OmemoManager extends Manager { * @throws SmackException.NotConnectedException if the XMPP connection is not connected. * @throws SmackException.NoResponseException if there was no response from the remote entity. * @throws SmackException.NotLoggedInException if the XMPP connection is not authenticated. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public OmemoMessage.Sent encrypt(BareJid recipient, String message) throws CryptoFailedException, UndecidedOmemoIdentityException, @@ -327,7 +328,7 @@ public final class OmemoManager extends Manager { * @throws SmackException.NotConnectedException if the XMPP connection is not connected. * @throws SmackException.NoResponseException if there was no response from the remote entity. * @throws SmackException.NotLoggedInException if the XMPP connection is not authenticated. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public synchronized OmemoMessage.Sent encrypt(Set recipients, String message) throws CryptoFailedException, UndecidedOmemoIdentityException, @@ -355,7 +356,7 @@ public final class OmemoManager extends Manager { * @throws SmackException.NoResponseException if there was no response from the remote entity. * @throws NoOmemoSupportException When the muc doesn't support OMEMO. * @throws SmackException.NotLoggedInException if the XMPP connection is not authenticated. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public synchronized OmemoMessage.Sent encrypt(MultiUserChat muc, String message) throws UndecidedOmemoIdentityException, CryptoFailedException, @@ -387,7 +388,7 @@ public final class OmemoManager extends Manager { * @throws CorruptedOmemoKeyException if our or their key is corrupted * @throws NoRawSessionException if the message was not a preKeyMessage, but we had no session with the contact * @throws CryptoFailedException if decryption fails - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public OmemoMessage.Received decrypt(BareJid sender, OmemoElement omemoElement) throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, NoRawSessionException, @@ -402,7 +403,7 @@ public final class OmemoManager extends Manager { * @param mamQuery The MAM query * @return list of decrypted OmemoMessages * @throws SmackException.NotLoggedInException if the Manager is not authenticated. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public List decryptMamQueryResult(MamManager.MamQuery mamQuery) throws SmackException.NotLoggedInException, IOException { @@ -485,22 +486,23 @@ public final class OmemoManager extends Manager { * @throws SmackException.NoResponseException if there was no response from the remote entity. * @throws NoSuchAlgorithmException if no such algorithm is available. * @throws SmackException.NotConnectedException if the XMPP connection is not connected. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public synchronized void sendRatchetUpdateMessage(OmemoDevice recipient) 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()); } /** @@ -513,7 +515,7 @@ public final class OmemoManager extends Manager { * @throws SmackException.NoResponseException if there was no response from the remote entity. * @throws PubSubException.NotALeafNodeException if a PubSub leaf node operation was attempted on a non-leaf node. * @throws XMPPException.XMPPErrorException if there was an XMPP error returned. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public synchronized boolean contactSupportsOmemo(BareJid contact) throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, @@ -565,7 +567,7 @@ public final class OmemoManager extends Manager { * @return fingerprint TODO javadoc me please * @throws SmackException.NotLoggedInException if we don't know our bareJid yet. * @throws CorruptedOmemoKeyException if our identityKey is corrupted. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public synchronized OmemoFingerprint getOwnFingerprint() throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, IOException { @@ -586,7 +588,7 @@ public final class OmemoManager extends Manager { * @throws SmackException.NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException.NoResponseException if there was no response from the remote entity. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public synchronized OmemoFingerprint getFingerprint(OmemoDevice device) throws CannotEstablishOmemoSessionException, SmackException.NotLoggedInException, @@ -616,7 +618,7 @@ public final class OmemoManager extends Manager { * @throws SmackException.NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. * @throws SmackException.NoResponseException if there was no response from the remote entity. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public synchronized HashMap getActiveFingerprints(BareJid contact) throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, @@ -686,7 +688,7 @@ public final class OmemoManager extends Manager { * @throws XMPPException.XMPPErrorException if there was an XMPP error returned. * @throws SmackException.NotConnectedException if the XMPP connection is not connected. * @throws SmackException.NoResponseException if there was no response from the remote entity. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. */ public synchronized void requestDeviceListUpdateFor(BareJid contact) throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, @@ -702,7 +704,7 @@ public final class OmemoManager extends Manager { * @throws XMPPException.XMPPErrorException if there was an XMPP error returned. * @throws SmackException.NotConnectedException if the XMPP connection is not connected. * @throws SmackException.NoResponseException if there was no response from the remote entity. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws PubSubException.NotALeafNodeException if a PubSub leaf node operation was attempted on a non-leaf node. */ public void purgeDeviceList() @@ -722,7 +724,7 @@ public final class OmemoManager extends Manager { * @throws SmackException.NotConnectedException XMPP error * @throws SmackException.NoResponseException XMPP error * @throws SmackException.NotLoggedInException if the XMPP connection is not authenticated. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws PubSubException.NotALeafNodeException if a PubSub leaf node operation was attempted on a non-leaf node. */ public synchronized void rotateSignedPreKey() 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/OmemoRatchet.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoRatchet.java index 988c2b197..e00815283 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoRatchet.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoRatchet.java @@ -66,7 +66,7 @@ public abstract class OmemoRatchet contactsDevices, @@ -441,7 +442,7 @@ public abstract class OmemoService contactsDevices, @@ -519,7 +520,7 @@ public abstract class OmemoService contactsDevices, @@ -652,7 +653,7 @@ public abstract class OmemoService buildMissingSessionsWithDevices(XMPPConnection connection, OmemoDevice userDevice, @@ -841,7 +842,7 @@ public abstract class OmemoService getUndecidedDevices(OmemoDevice userDevice, OmemoTrustCallback callback, Set devices) throws IOException { Set undecidedDevices = new HashSet<>(); @@ -872,7 +873,7 @@ public abstract class OmemoService decryptMamQueryResult(OmemoManager.LoggedInOmemoManager managerGuard, MamManager.MamQuery mamQuery) throws IOException { @@ -1220,7 +1221,7 @@ public abstract class OmemoService preKeyHashMap) throws IOException { for (Map.Entry entry : preKeyHashMap.entrySet()) { @@ -444,7 +444,7 @@ public abstract class OmemoStore loadOmemoPreKeys(OmemoDevice userDevice) throws IOException; @@ -454,7 +454,7 @@ public abstract class OmemoStore loadOmemoSignedPreKeys(OmemoDevice userDevice) throws IOException; @@ -490,7 +490,7 @@ public abstract class OmemoStore loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) throws IOException; @@ -528,7 +528,7 @@ public abstract class OmemoStoresingletonList(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/DoX.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/DoX.java index aa0525eb2..093a5aea9 100644 --- a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/DoX.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/DoX.java @@ -28,6 +28,7 @@ import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.debugger.ConsoleDebugger; import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; + import org.jivesoftware.smackx.dox.DnsOverXmppManager; import org.jivesoftware.smackx.dox.resolver.minidns.DnsOverXmppMiniDnsResolver; diff --git a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/IoT.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/IoT.java index a77f5f1ac..66a968c31 100644 --- a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/IoT.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/IoT.java @@ -33,6 +33,7 @@ import org.jivesoftware.smack.roster.RosterUtil; import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; import org.jivesoftware.smack.util.StringUtils; + import org.jivesoftware.smackx.iot.IoTDiscoveryIntegrationTest; import org.jivesoftware.smackx.iot.Thing; import org.jivesoftware.smackx.iot.data.IoTDataManager; 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/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java index a81d39fef..df6a83156 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java @@ -629,7 +629,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { * * @throws XMPPException if establishing a connection to the server fails. * @throws SmackException if the server fails to respond back or if there is anther error. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws InterruptedException if the calling thread was interrupted. */ private void initConnection() throws IOException, InterruptedException { @@ -673,7 +673,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { * The server has indicated that TLS negotiation can start. We now need to secure the * existing plain connection and perform a handshake. This method won't return until the * connection has finished the handshake or an error occurred while securing the connection. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws CertificateException * @throws NoSuchAlgorithmException if no such algorithm is available. * @throws NoSuchProviderException @@ -809,7 +809,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { * * @throws XMPPException if an error occurs while trying to establish the connection. * @throws SmackException if Smack detected an exceptional situation. - * @throws IOException if an I/O error occured. + * @throws IOException if an I/O error occurred. * @throws InterruptedException if the calling thread was interrupted. */ @Override 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;