1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-02-18 14:49:23 +01:00

Compare commits

..

No commits in common. "9d626bf787dc3e0e0a4399cef429285b22744d73" and "926c5892ad985b9fe5ef11104effa7400226304e" have entirely different histories.

234 changed files with 1397 additions and 4042 deletions

View file

@ -15,11 +15,7 @@ Smack Key Advantages
AbstractXMPPConnection connection = new XMPPTCPConnection("mtucker", "password", "jabber.org"); AbstractXMPPConnection connection = new XMPPTCPConnection("mtucker", "password", "jabber.org");
connection.connect().login(); connection.connect().login();
Message message = connection.getStanzaFactory() Message message = new Message("jsmith@jivesoftware.com", "Howdy! How are you?");
.buildMessageStanza()
.to("jsmith@jivesoftware.com")
.setBody("Howdy! How are you?")
.build();
connection.sendStanza(message); connection.sendStanza(message);
``` ```

View file

@ -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[XMPPErrorException]="if there was an XMPP error returned."
SMACK_EXCEPTIONS[NoResponseException]="if there was no response from the remote entity." SMACK_EXCEPTIONS[NoResponseException]="if there was no response from the remote entity."
SMACK_EXCEPTIONS[NotLoggedInException]="if the XMPP connection is not authenticated." SMACK_EXCEPTIONS[NotLoggedInException]="if the XMPP connection is not authenticated."
SMACK_EXCEPTIONS[BOSHException]="if an BOSH related error occurred." SMACK_EXCEPTIONS[BOSHException]="if an BOSH related error occured."
SMACK_EXCEPTIONS[IOException]="if an I/O error occurred." SMACK_EXCEPTIONS[IOException]="if an I/O error occured."
SMACK_EXCEPTIONS[SmackException]="if Smack detected an exceptional situation." SMACK_EXCEPTIONS[SmackException]="if Smack detected an exceptional situation."
SMACK_EXCEPTIONS[XMPPException]="if an XMPP protocol error was received." SMACK_EXCEPTIONS[XMPPException]="if an XMPP protocol error was received."
SMACK_EXCEPTIONS[SmackSaslException]="if a SASL specific error occurred." SMACK_EXCEPTIONS[SmackSaslException]="if a SASL specific error occured."
SMACK_EXCEPTIONS[SASLErrorException]="if a SASL protocol error was returned." SMACK_EXCEPTIONS[SASLErrorException]="if a SASL protocol error was returned."
SMACK_EXCEPTIONS[NotAMucServiceException]="if the entity is not a MUC serivce." SMACK_EXCEPTIONS[NotAMucServiceException]="if the entity is not a MUC serivce."
SMACK_EXCEPTIONS[NoSuchAlgorithmException]="if no such algorithm is available." SMACK_EXCEPTIONS[NoSuchAlgorithmException]="if no such algorithm is available."
SMACK_EXCEPTIONS[KeyManagementException]="if there was a key mangement error." SMACK_EXCEPTIONS[KeyManagementException]="if there was a key mangement error."
SMACK_EXCEPTIONS[XmppStringprepException]="if the provided string is invalid." SMACK_EXCEPTIONS[XmppStringprepException]="if the provided string is invalid."
SMACK_EXCEPTIONS[XmlPullParserException]="if an error in the XML parser occurred." SMACK_EXCEPTIONS[XmlPullParserException]="if an error in the XML parser occured."
SMACK_EXCEPTIONS[SmackParsingException]="if the Smack parser (provider) encountered invalid input." SMACK_EXCEPTIONS[SmackParsingException]="if the Smack parser (provider) encountered invalid input."
SMACK_EXCEPTIONS[MucNotJoinedException]="if not joined to the Multi-User Chat." SMACK_EXCEPTIONS[MucNotJoinedException]="if not joined to the Multi-User Chat."
SMACK_EXCEPTIONS[MucAlreadyJoinedException]="if already joined the Multi-User Chat."7y 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[NotAPubSubNodeException]="if a involved node is not a PubSub node."
SMACK_EXCEPTIONS[NoAcceptableTransferMechanisms]="if no acceptable transfer mechanisms are available" SMACK_EXCEPTIONS[NoAcceptableTransferMechanisms]="if no acceptable transfer mechanisms are available"
SMACK_EXCEPTIONS[NoSuchMethodException]="if no such method is declared" SMACK_EXCEPTIONS[NoSuchMethodException]="if no such method is declared"
SMACK_EXCEPTIONS[Exception]="if an exception occurred." SMACK_EXCEPTIONS[Exception]="if an exception occured."
SMACK_EXCEPTIONS[TestNotPossibleException]="if the test is not possible." SMACK_EXCEPTIONS[TestNotPossibleException]="if the test is not possible."
SMACK_EXCEPTIONS[TimeoutException]="if there was a timeout." SMACK_EXCEPTIONS[TimeoutException]="if there was a timeout."
SMACK_EXCEPTIONS[IllegalStateException]="if an illegal state was encountered" SMACK_EXCEPTIONS[IllegalStateException]="if an illegal state was encountered"

View file

@ -517,8 +517,8 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
if ("urn:ietf:params:xml:ns:xmpp-streams".equals(parser.getNamespace(null))) { if ("urn:ietf:params:xml:ns:xmpp-streams".equals(parser.getNamespace(null))) {
throw new StreamErrorException(PacketParserUtils.parseStreamError(parser)); throw new StreamErrorException(PacketParserUtils.parseStreamError(parser));
} else { } else {
StanzaError stanzaError = PacketParserUtils.parseError(parser); StanzaError.Builder builder = PacketParserUtils.parseError(parser);
throw new XMPPException.XMPPErrorException(null, stanzaError); throw new XMPPException.XMPPErrorException(null, builder.build());
} }
default: default:
parseAndProcessNonza(parser); parseAndProcessNonza(parser);

View file

@ -100,22 +100,16 @@ import org.jivesoftware.smack.packet.FullyQualifiedElement;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Mechanisms; import org.jivesoftware.smack.packet.Mechanisms;
import org.jivesoftware.smack.packet.Message; 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.Nonza;
import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.PresenceBuilder;
import org.jivesoftware.smack.packet.Session; import org.jivesoftware.smack.packet.Session;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smack.packet.StanzaError;
import org.jivesoftware.smack.packet.StanzaFactory;
import org.jivesoftware.smack.packet.StartTls; import org.jivesoftware.smack.packet.StartTls;
import org.jivesoftware.smack.packet.StreamError; import org.jivesoftware.smack.packet.StreamError;
import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.packet.StreamOpen;
import org.jivesoftware.smack.packet.TopLevelStreamElement; import org.jivesoftware.smack.packet.TopLevelStreamElement;
import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.packet.id.StanzaIdSource;
import org.jivesoftware.smack.parsing.ParsingExceptionCallback; import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.provider.ExtensionElementProvider; import org.jivesoftware.smack.provider.ExtensionElementProvider;
@ -127,13 +121,11 @@ import org.jivesoftware.smack.sasl.core.SASLAnonymous;
import org.jivesoftware.smack.sasl.packet.SaslNonza; import org.jivesoftware.smack.sasl.packet.SaslNonza;
import org.jivesoftware.smack.util.Async; import org.jivesoftware.smack.util.Async;
import org.jivesoftware.smack.util.CollectionUtil; import org.jivesoftware.smack.util.CollectionUtil;
import org.jivesoftware.smack.util.Consumer;
import org.jivesoftware.smack.util.DNSUtil; import org.jivesoftware.smack.util.DNSUtil;
import org.jivesoftware.smack.util.MultiMap; import org.jivesoftware.smack.util.MultiMap;
import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.util.ParserUtils; import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.util.Predicate;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.dns.HostAddress; import org.jivesoftware.smack.util.dns.HostAddress;
import org.jivesoftware.smack.util.dns.SmackDaneProvider; import org.jivesoftware.smack.util.dns.SmackDaneProvider;
@ -249,10 +241,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
private final Map<StanzaListener, InterceptorWrapper> interceptors = private final Map<StanzaListener, InterceptorWrapper> interceptors =
new HashMap<>(); new HashMap<>();
private final Map<Consumer<MessageBuilder>, GenericInterceptorWrapper<MessageBuilder, Message>> messageInterceptors = new HashMap<>();
private final Map<Consumer<PresenceBuilder>, GenericInterceptorWrapper<PresenceBuilder, Presence>> presenceInterceptors = new HashMap<>();
private XmlEnvironment incomingStreamXmlEnvironment; private XmlEnvironment incomingStreamXmlEnvironment;
protected XmlEnvironment outgoingStreamXmlEnvironment; protected XmlEnvironment outgoingStreamXmlEnvironment;
@ -414,8 +402,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
private final Map<QName, IQRequestHandler> setIqRequestHandler = new HashMap<>(); private final Map<QName, IQRequestHandler> setIqRequestHandler = new HashMap<>();
private final Map<QName, IQRequestHandler> getIqRequestHandler = new HashMap<>(); private final Map<QName, IQRequestHandler> getIqRequestHandler = new HashMap<>();
private final StanzaFactory stanzaFactory;
/** /**
* Create a new XMPPConnection to an XMPP server. * Create a new XMPPConnection to an XMPP server.
* *
@ -454,9 +440,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
for (ConnectionCreationListener listener : XMPPConnectionRegistry.getConnectionCreationListeners()) { for (ConnectionCreationListener listener : XMPPConnectionRegistry.getConnectionCreationListeners()) {
listener.connectionCreated(this); listener.connectionCreated(this);
} }
StanzaIdSource stanzaIdSource = configuration.constructStanzaIdSource();
stanzaFactory = new StanzaFactory(stanzaIdSource);
} }
/** /**
@ -535,7 +518,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
* *
* @throws XMPPException if an error occurs on the XMPP protocol level. * @throws XMPPException if an error occurs on the XMPP protocol level.
* @throws SmackException if an error occurs somewhere else besides XMPP protocol level. * @throws SmackException if an error occurs somewhere else besides XMPP protocol level.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @return a reference to this object, to chain <code>connect()</code> with <code>login()</code>. * @return a reference to this object, to chain <code>connect()</code> with <code>login()</code>.
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
*/ */
@ -575,7 +558,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
* login if the previous connection state was logged (authenticated). * login if the previous connection state was logged (authenticated).
* *
* @throws SmackException if Smack detected an exceptional situation. * @throws SmackException if Smack detected an exceptional situation.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws XMPPException if an XMPP protocol error was received. * @throws XMPPException if an XMPP protocol error was received.
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
*/ */
@ -628,7 +611,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
* @param password TODO javadoc me please * @param password TODO javadoc me please
* @throws XMPPException if an XMPP protocol error was received. * @throws XMPPException if an XMPP protocol error was received.
* @throws SmackException if Smack detected an exceptional situation. * @throws SmackException if Smack detected an exceptional situation.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
* @see #login * @see #login
*/ */
@ -646,7 +629,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
* @param resource TODO javadoc me please * @param resource TODO javadoc me please
* @throws XMPPException if an XMPP protocol error was received. * @throws XMPPException if an XMPP protocol error was received.
* @throws SmackException if Smack detected an exceptional situation. * @throws SmackException if Smack detected an exceptional situation.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
* @see #login * @see #login
*/ */
@ -750,11 +733,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
// eventually load the roster. And we should load the roster before we // eventually load the roster. And we should load the roster before we
// send the initial presence. // send the initial presence.
if (config.isSendPresence() && !resumed) { if (config.isSendPresence() && !resumed) {
Presence availablePresence = getStanzaFactory() sendStanza(new Presence(Presence.Type.available));
.buildPresenceStanza()
.ofType(Presence.Type.available)
.build();
sendStanza(availablePresence);
} }
} }
@ -835,11 +814,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
} }
@Override
public final StanzaFactory getStanzaFactory() {
return stanzaFactory;
}
@Override @Override
public final void sendStanza(Stanza stanza) throws NotConnectedException, InterruptedException { public final void sendStanza(Stanza stanza) throws NotConnectedException, InterruptedException {
Objects.requireNonNull(stanza, "Stanza must not be null"); Objects.requireNonNull(stanza, "Stanza must not be null");
@ -859,8 +833,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
// Invoke interceptors for the new stanza that is about to be sent. Interceptors may modify // Invoke interceptors for the new stanza that is about to be sent. Interceptors may modify
// the content of the stanza. // the content of the stanza.
Stanza stanzaAfterInterceptors = firePacketInterceptors(stanza); firePacketInterceptors(stanza);
sendStanzaInternal(stanzaAfterInterceptors); sendStanzaInternal(stanza);
} }
/** /**
@ -873,9 +847,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
* @return the used SASLMechanism. * @return the used SASLMechanism.
* @throws XMPPErrorException if there was an XMPP error returned. * @throws XMPPErrorException if there was an XMPP error returned.
* @throws SASLErrorException if a SASL protocol error was returned. * @throws SASLErrorException if a SASL protocol error was returned.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
* @throws SmackSaslException if a SASL specific error occurred. * @throws SmackSaslException if a SASL specific error occured.
* @throws NotConnectedException if the XMPP connection is not connected. * @throws NotConnectedException if the XMPP connection is not connected.
* @throws NoResponseException if there was no response from the remote entity. * @throws NoResponseException if there was no response from the remote entity.
* @throws SmackWrappedException in case of an exception. * @throws SmackWrappedException in case of an exception.
@ -919,9 +893,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
public void disconnect() { public void disconnect() {
Presence unavailablePresence = null; Presence unavailablePresence = null;
if (isAuthenticated()) { if (isAuthenticated()) {
unavailablePresence = getStanzaFactory().buildPresenceStanza() unavailablePresence = new Presence(Presence.Type.unavailable);
.ofType(Presence.Type.unavailable)
.build();
} }
try { try {
disconnect(unavailablePresence); disconnect(unavailablePresence);
@ -1214,7 +1186,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
}); });
} }
@Deprecated
@Override @Override
public void addStanzaInterceptor(StanzaListener packetInterceptor, public void addStanzaInterceptor(StanzaListener packetInterceptor,
StanzaFilter packetFilter) { StanzaFilter packetFilter) {
@ -1227,7 +1198,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
} }
@Deprecated
@Override @Override
public void removeStanzaInterceptor(StanzaListener packetInterceptor) { public void removeStanzaInterceptor(StanzaListener packetInterceptor) {
synchronized (interceptors) { synchronized (interceptors) {
@ -1235,83 +1205,15 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
} }
private static <MPB extends MessageOrPresenceBuilder<MP, MPB>, MP extends MessageOrPresence<MPB>> void addInterceptor(
Map<Consumer<MPB>, GenericInterceptorWrapper<MPB, MP>> interceptors, Consumer<MPB> interceptor,
Predicate<MP> filter) {
Objects.requireNonNull(interceptor, "Interceptor must not be null");
GenericInterceptorWrapper<MPB, MP> interceptorWrapper = new GenericInterceptorWrapper<>(interceptor, filter);
synchronized (interceptors) {
interceptors.put(interceptor, interceptorWrapper);
}
}
private static <MPB extends MessageOrPresenceBuilder<MP, MPB>, MP extends MessageOrPresence<MPB>> void removeInterceptor(
Map<Consumer<MPB>, GenericInterceptorWrapper<MPB, MP>> interceptors, Consumer<MPB> interceptor) {
synchronized (interceptors) {
interceptors.remove(interceptor);
}
}
@Override
public void addMessageInterceptor(Consumer<MessageBuilder> messageInterceptor, Predicate<Message> messageFilter) {
addInterceptor(messageInterceptors, messageInterceptor, messageFilter);
}
@Override
public void removeMessageInterceptor(Consumer<MessageBuilder> messageInterceptor) {
removeInterceptor(messageInterceptors, messageInterceptor);
}
@Override
public void addPresenceInterceptor(Consumer<PresenceBuilder> presenceInterceptor,
Predicate<Presence> presenceFilter) {
addInterceptor(presenceInterceptors, presenceInterceptor, presenceFilter);
}
@Override
public void removePresenceInterceptor(Consumer<PresenceBuilder> presenceInterceptor) {
removeInterceptor(presenceInterceptors, presenceInterceptor);
}
private static <MPB extends MessageOrPresenceBuilder<MP, MPB>, MP extends MessageOrPresence<MPB>> MP fireMessageOrPresenceInterceptors(
MP messageOrPresence, Map<Consumer<MPB>, GenericInterceptorWrapper<MPB, MP>> interceptors) {
List<Consumer<MPB>> interceptorsToInvoke = new LinkedList<>();
synchronized (interceptors) {
for (GenericInterceptorWrapper<MPB, MP> interceptorWrapper : interceptors.values()) {
if (interceptorWrapper.filterMatches(messageOrPresence)) {
Consumer<MPB> 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<MPB> 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. * 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 * 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 * is important that interceptors perform their work as soon as possible so that the
* thread does not remain blocked for a long period. * 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 Stanza firePacketInterceptors(Stanza packet) { private void firePacketInterceptors(Stanza packet) {
List<StanzaListener> interceptorsToInvoke = new LinkedList<>(); List<StanzaListener> interceptorsToInvoke = new LinkedList<>();
synchronized (interceptors) { synchronized (interceptors) {
for (InterceptorWrapper interceptorWrapper : interceptors.values()) { for (InterceptorWrapper interceptorWrapper : interceptors.values()) {
@ -1327,22 +1229,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
LOGGER.log(Level.SEVERE, "Packet interceptor threw exception", e); 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;
} }
/** /**
@ -1530,7 +1416,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 // 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'. // IQ of type 'error' with condition 'service-unavailable'.
final ErrorIQ errorIQ = IQ.createErrorResponse(iq, StanzaError.getBuilder( final ErrorIQ errorIQ = IQ.createErrorResponse(iq, StanzaError.getBuilder(
replyCondition).build()); replyCondition));
// Use async sendStanza() here, since if sendStanza() would block, then some connections, e.g. // 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 // XmppNioTcpConnection, would deadlock, as this operation is performed in the same thread that is
asyncGo(() -> { asyncGo(() -> {
@ -1770,8 +1656,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
/** /**
* A wrapper class to associate a stanza filter with an interceptor. * A wrapper class to associate a stanza filter with an interceptor.
*/ */
@Deprecated
// TODO: Remove once addStanzaInterceptor is gone.
protected static class InterceptorWrapper { protected static class InterceptorWrapper {
private final StanzaListener packetInterceptor; private final StanzaListener packetInterceptor;
@ -1797,24 +1681,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
} }
private static final class GenericInterceptorWrapper<MPB extends MessageOrPresenceBuilder<MP, MPB>, MP extends MessageOrPresence<MPB>> {
private final Consumer<MPB> stanzaInterceptor;
private final Predicate<MP> stanzaFilter;
private GenericInterceptorWrapper(Consumer<MPB> stanzaInterceptor, Predicate<MP> stanzaFilter) {
this.stanzaInterceptor = stanzaInterceptor;
this.stanzaFilter = stanzaFilter;
}
private boolean filterMatches(MP stanza) {
return stanzaFilter == null || stanzaFilter.test(stanza);
}
public Consumer<MPB> getInterceptor() {
return stanzaInterceptor;
}
}
@Override @Override
public int getConnectionCounter() { public int getConnectionCounter() {
return connectionCounterValue; return connectionCounterValue;

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2018-2019 Florian Schmaus * Copyright 2018 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,6 @@
*/ */
package org.jivesoftware.smack; package org.jivesoftware.smack;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.WeakHashMap; import java.util.WeakHashMap;
@ -52,17 +51,9 @@ import java.util.concurrent.Executor;
*/ */
public class AsyncButOrdered<K> { public class AsyncButOrdered<K> {
/**
* 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<K, Queue<Runnable>> pendingRunnables = new WeakHashMap<>(); private final Map<K, Queue<Runnable>> pendingRunnables = new WeakHashMap<>();
/** private final Map<K, Boolean> 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<K, Handler> threadActiveMap = new HashMap<>();
private final Executor executor; private final Executor executor;
@ -74,14 +65,6 @@ public class AsyncButOrdered<K> {
this.executor = executor; 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. * Invoke the given {@link Runnable} asynchronous but ordered in respect to the given key.
* *
@ -90,7 +73,6 @@ public class AsyncButOrdered<K> {
* @return true if a new thread was created * @return true if a new thread was created
*/ */
public boolean performAsyncButOrdered(K key, Runnable runnable) { public boolean performAsyncButOrdered(K key, Runnable runnable) {
// First check if a key queue already exists, create one if not.
Queue<Runnable> keyQueue; Queue<Runnable> keyQueue;
synchronized (pendingRunnables) { synchronized (pendingRunnables) {
keyQueue = pendingRunnables.get(key); keyQueue = pendingRunnables.get(key);
@ -100,27 +82,29 @@ public class AsyncButOrdered<K> {
} }
} }
// Then add the task to the queue.
keyQueue.add(runnable); keyQueue.add(runnable);
// Finally check if there is already a handler working on that queue, create one if not. boolean newHandler;
Handler newlyCreatedHandler = null;
synchronized (threadActiveMap) { synchronized (threadActiveMap) {
if (!threadActiveMap.containsKey(key)) { Boolean threadActive = threadActiveMap.get(key);
newlyCreatedHandler = new Handler(keyQueue, key); if (threadActive == null) {
threadActive = false;
threadActiveMap.put(key, threadActive);
}
// Mark that there is thread active for the given key. Note that this has to be done before scheduling newHandler = !threadActive;
// the handler thread. if (newHandler) {
threadActiveMap.put(key, newlyCreatedHandler); Handler handler = new Handler(keyQueue, key);
threadActiveMap.put(key, true);
if (executor == null) {
AbstractXMPPConnection.asyncGo(handler);
} else {
executor.execute(handler);
}
} }
} }
if (newlyCreatedHandler != null) { return newHandler;
scheduleHandler(newlyCreatedHandler);
return true;
}
return false;
} }
public Executor asExecutorFor(final K key) { public Executor asExecutorFor(final K key) {
@ -150,14 +134,11 @@ public class AsyncButOrdered<K> {
try { try {
runnable.run(); runnable.run();
} catch (Throwable t) { } catch (Throwable t) {
// The run() method threw, this handler thread is going to terminate because of that. We create // The run() method threw, this handler thread is going to terminate because of that. Ensure we note
// a new handler to continue working on the queue while throwing the throwable so that the // that in the map.
// executor can handle it.
Handler newlyCreatedHandler = new Handler(keyQueue, key);
synchronized (threadActiveMap) { synchronized (threadActiveMap) {
threadActiveMap.put(key, newlyCreatedHandler); threadActiveMap.put(key, false);
} }
scheduleHandler(newlyCreatedHandler);
throw t; throw t;
} }
} }
@ -165,7 +146,7 @@ public class AsyncButOrdered<K> {
synchronized (threadActiveMap) { synchronized (threadActiveMap) {
// If the queue is empty, stop this handler, otherwise continue looping. // If the queue is empty, stop this handler, otherwise continue looping.
if (keyQueue.isEmpty()) { if (keyQueue.isEmpty()) {
threadActiveMap.remove(key); threadActiveMap.put(key, false);
break mainloop; break mainloop;
} }
} }

View file

@ -36,9 +36,6 @@ import javax.net.ssl.X509TrustManager;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import org.jivesoftware.smack.debugger.SmackDebuggerFactory; 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.proxy.ProxyInfo;
import org.jivesoftware.smack.sasl.SASLMechanism; import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.sasl.core.SASLAnonymous; import org.jivesoftware.smack.sasl.core.SASLAnonymous;
@ -162,8 +159,6 @@ public abstract class ConnectionConfiguration {
private final boolean compressionEnabled; private final boolean compressionEnabled;
private final StanzaIdSourceFactory stanzaIdSourceFactory;
protected ConnectionConfiguration(Builder<?, ?> builder) { protected ConnectionConfiguration(Builder<?, ?> builder) {
authzid = builder.authzid; authzid = builder.authzid;
username = builder.username; username = builder.username;
@ -218,8 +213,6 @@ public abstract class ConnectionConfiguration {
compressionEnabled = builder.compressionEnabled; compressionEnabled = builder.compressionEnabled;
stanzaIdSourceFactory = builder.stanzaIdSourceFactory;
// If the enabledSaslmechanisms are set, then they must not be empty // If the enabledSaslmechanisms are set, then they must not be empty
assert enabledSaslMechanisms == null || !enabledSaslMechanisms.isEmpty(); assert enabledSaslMechanisms == null || !enabledSaslMechanisms.isEmpty();
@ -575,10 +568,6 @@ public abstract class ConnectionConfiguration {
return Collections.unmodifiableSet(enabledSaslMechanisms); return Collections.unmodifiableSet(enabledSaslMechanisms);
} }
StanzaIdSource constructStanzaIdSource() {
return stanzaIdSourceFactory.constructStanzaIdSource();
}
/** /**
* A builder for XMPP connection configurations. * A builder for XMPP connection configurations.
* <p> * <p>
@ -623,7 +612,6 @@ public abstract class ConnectionConfiguration {
private Set<String> enabledSaslMechanisms; private Set<String> enabledSaslMechanisms;
private X509TrustManager customX509TrustManager; private X509TrustManager customX509TrustManager;
private boolean compressionEnabled = false; private boolean compressionEnabled = false;
private StanzaIdSourceFactory stanzaIdSourceFactory = new StandardStanzaIdSource.Factory();
protected Builder() { protected Builder() {
if (SmackConfiguration.DEBUG) { if (SmackConfiguration.DEBUG) {
@ -1146,17 +1134,6 @@ public abstract class ConnectionConfiguration {
return getThis(); 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(); public abstract C build();

View file

@ -175,9 +175,9 @@ public final class SASLAuthentication {
* @return the used SASLMechanism. * @return the used SASLMechanism.
* @throws XMPPErrorException if there was an XMPP error returned. * @throws XMPPErrorException if there was an XMPP error returned.
* @throws SASLErrorException if a SASL protocol error was returned. * @throws SASLErrorException if a SASL protocol error was returned.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
* @throws SmackSaslException if a SASL specific error occurred. * @throws SmackSaslException if a SASL specific error occured.
* @throws NotConnectedException if the XMPP connection is not connected. * @throws NotConnectedException if the XMPP connection is not connected.
* @throws NoResponseException if there was no response from the remote entity. * @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 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 * @param finalChallenge true if this is the last challenge send by the server within the success stanza
* @throws SmackSaslException if a SASL specific error occurred. * @throws SmackSaslException if a SASL specific error occured.
* @throws NotConnectedException if the XMPP connection is not connected. * @throws NotConnectedException if the XMPP connection is not connected.
* @throws InterruptedException if the calling thread was interrupted. * @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 SmackException if Smack detected an exceptional situation.
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
* @throws NotConnectedException if the XMPP connection is not connected. * @throws NotConnectedException if the XMPP connection is not connected.
* @throws SmackSaslException if a SASL specific error occurred. * @throws SmackSaslException if a SASL specific error occured.
*/ */
void authenticated(Success success) throws InterruptedException, SmackSaslException, NotConnectedException { void authenticated(Success success) throws InterruptedException, SmackSaslException, NotConnectedException {
// RFC6120 6.3.10 "At the end of the authentication exchange, the SASL server (the XMPP // RFC6120 6.3.10 "At the end of the authentication exchange, the SASL server (the XMPP

View file

@ -49,6 +49,7 @@ import org.jivesoftware.smack.sasl.core.ScramSha1PlusMechanism;
import org.jivesoftware.smack.util.CloseableUtil; import org.jivesoftware.smack.util.CloseableUtil;
import org.jivesoftware.smack.util.FileUtils; import org.jivesoftware.smack.util.FileUtils;
import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;

View file

@ -27,15 +27,8 @@ import org.jivesoftware.smack.iqrequest.IQRequestHandler;
import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.FullyQualifiedElement; import org.jivesoftware.smack.packet.FullyQualifiedElement;
import org.jivesoftware.smack.packet.IQ; 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.Nonza;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.PresenceBuilder;
import org.jivesoftware.smack.packet.Stanza; 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.DomainBareJid;
import org.jxmpp.jid.EntityFullJid; import org.jxmpp.jid.EntityFullJid;
@ -185,8 +178,6 @@ public interface XMPPConnection {
*/ */
boolean isUsingCompression(); boolean isUsingCompression();
StanzaFactory getStanzaFactory();
/** /**
* Sends the specified stanza to the server. * Sends the specified stanza to the server.
* *
@ -367,7 +358,7 @@ public interface XMPPConnection {
boolean removeStanzaListener(StanzaListener stanzaListener); boolean removeStanzaListener(StanzaListener stanzaListener);
/** /**
* Registers a <b>synchronous</b> stanza listener with this connection. A stanza listener will be invoked only when * Registers a <b>synchronous</b> 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 * 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. * the same stanza listener is added again with a different filter, only the new filter will be used.
* <p> * <p>
@ -452,65 +443,16 @@ public interface XMPPConnection {
* *
* @param stanzaInterceptor the stanza interceptor to notify of stanzas about to be sent. * @param stanzaInterceptor the stanza interceptor to notify of stanzas about to be sent.
* @param stanzaFilter the stanza filter to use. * @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); void addStanzaInterceptor(StanzaListener stanzaInterceptor, StanzaFilter stanzaFilter);
/** /**
* Removes a stanza interceptor. * Removes a stanza interceptor.
* *
* @param stanzaInterceptor the stanza interceptor to remove. * @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); 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.
*
* <p>
* NOTE: For a similar functionality on incoming stanzas, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}.
* </p>
*
* @param messageInterceptor the stanza interceptor to notify of stanzas about to be sent.
* @param messageFilter the stanza filter to use.
*/
void addMessageInterceptor(Consumer<MessageBuilder> messageInterceptor, Predicate<Message> messageFilter);
/**
* Removes a message interceptor.
*
* @param messageInterceptor the message interceptor to remove.
*/
void removeMessageInterceptor(Consumer<MessageBuilder> 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.
*
* <p>
* NOTE: For a similar functionality on incoming stanzas, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}.
* </p>
*
* @param presenceInterceptor the stanza interceptor to notify of stanzas about to be sent.
* @param presenceFilter the stanza filter to use.
*/
void addPresenceInterceptor(Consumer<PresenceBuilder> presenceInterceptor, Predicate<Presence> presenceFilter);
/**
* Removes a presence interceptor.
*
* @param presenceInterceptor the stanza interceptor to remove.
*/
void removePresenceInterceptor(Consumer<PresenceBuilder> presenceInterceptor);
/** /**
* Returns the current value of the reply timeout in milliseconds for request for this * Returns the current value of the reply timeout in milliseconds for request for this
* XMPPConnection instance. * XMPPConnection instance.

View file

@ -19,6 +19,7 @@ package org.jivesoftware.smack.compress.provider;
import org.jivesoftware.smack.compress.packet.Compressed; import org.jivesoftware.smack.compress.packet.Compressed;
import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.provider.NonzaProvider; import org.jivesoftware.smack.provider.NonzaProvider;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
public final class CompressedProvider extends NonzaProvider<Compressed> { public final class CompressedProvider extends NonzaProvider<Compressed> {

View file

@ -26,6 +26,7 @@ import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.provider.NonzaProvider; import org.jivesoftware.smack.provider.NonzaProvider;
import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smack.xml.XmlPullParserException;
@ -61,7 +62,8 @@ public final class FailureProvider extends NonzaProvider<Failure> {
case StreamOpen.SERVER_NAMESPACE: case StreamOpen.SERVER_NAMESPACE:
switch (name) { switch (name) {
case StanzaError.ERROR: case StanzaError.ERROR:
stanzaError = PacketParserUtils.parseError(parser, failureXmlEnvironment); StanzaError.Builder stanzaErrorBuilder = PacketParserUtils.parseError(parser, failureXmlEnvironment);
stanzaError = stanzaErrorBuilder.build();
break; break;
default: default:
LOGGER.warning("Unknown element in " + namespace + ": " + name); LOGGER.warning("Unknown element in " + namespace + ": " + name);

View file

@ -76,7 +76,7 @@ public class Java7ZlibInputOutputStream extends XMPPInputOutputStream {
* byte without blocking, 0 means that the system is known to block for more input. * byte without blocking, 0 means that the system is known to block for more input.
* *
* @return 0 if no data is available, 1 otherwise * @return 0 if no data is available, 1 otherwise
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
*/ */
@Override @Override
public int available() throws IOException { public int available() throws IOException {

View file

@ -18,7 +18,6 @@
package org.jivesoftware.smack.filter; package org.jivesoftware.smack.filter;
import org.jivesoftware.smack.packet.Stanza; 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 * Defines a way to filter stanzas for particular attributes. Stanza filters are used when
@ -52,7 +51,7 @@ import org.jivesoftware.smack.util.Predicate;
* @see org.jivesoftware.smack.StanzaListener * @see org.jivesoftware.smack.StanzaListener
* @author Matt Tucker * @author Matt Tucker
*/ */
public interface StanzaFilter extends Predicate<Stanza> { public interface StanzaFilter {
/** /**
* Tests whether or not the specified stanza should pass the filter. * Tests whether or not the specified stanza should pass the filter.
@ -61,9 +60,4 @@ public interface StanzaFilter extends Predicate<Stanza> {
* @return true if and only if <code>stanza</code> passes the filter. * @return true if and only if <code>stanza</code> passes the filter.
*/ */
boolean accept(Stanza stanza); boolean accept(Stanza stanza);
@Override
default boolean test(Stanza stanza) {
return accept(stanza);
}
} }

View file

@ -1,69 +0,0 @@
/**
*
* 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<IB extends AbstractIqBuilder<IB>> extends StanzaBuilder<IB> 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;
}
}

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2014-2019 Florian Schmaus * Copyright © 2014 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,18 +18,14 @@ package org.jivesoftware.smack.packet;
public class EmptyResultIQ extends IQ { public class EmptyResultIQ extends IQ {
EmptyResultIQ(IqData iqBuilder) {
super(iqBuilder, null, null);
}
// TODO: Deprecate when stanza builder and parsing logic is ready.
public EmptyResultIQ() { public EmptyResultIQ() {
super(null, null); super(null, null);
setType(IQ.Type.result); setType(IQ.Type.result);
} }
public EmptyResultIQ(IQ request) { public EmptyResultIQ(IQ request) {
this(AbstractIqBuilder.createResponse(request)); this();
initializeAsResultFor(request);
} }
@Override @Override

View file

@ -27,13 +27,13 @@ public class ErrorIQ extends SimpleIQ {
* <p> * <p>
* According to RFC 6120 § 8.3.1 "4. An error stanza MUST contain an &lt;error/&gt; child element.", so the xmppError argument is mandatory. * According to RFC 6120 § 8.3.1 "4. An error stanza MUST contain an &lt;error/&gt; child element.", so the xmppError argument is mandatory.
* </p> * </p>
* @param stanzaError the stanzaError (required). * @param xmppErrorBuilder the XMPPError builder (required).
*/ */
public ErrorIQ(StanzaError stanzaError) { public ErrorIQ(StanzaError.Builder xmppErrorBuilder) {
super(ELEMENT, null); super(ELEMENT, null);
Objects.requireNonNull(stanzaError, "stanzaError must not be null"); Objects.requireNonNull(xmppErrorBuilder, "xmppErrorBuilder must not be null");
setType(IQ.Type.error); setType(IQ.Type.error);
setError(stanzaError); setError(xmppErrorBuilder);
} }
} }

View file

@ -18,7 +18,7 @@ package org.jivesoftware.smack.packet;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
public interface FullyQualifiedElement extends NamedElement, XmlLangElement { public interface FullyQualifiedElement extends NamedElement {
/** /**
* Returns the root element XML namespace. * Returns the root element XML namespace.
@ -33,7 +33,11 @@ public interface FullyQualifiedElement extends NamedElement, XmlLangElement {
return new QName(namespaceURI, localPart); return new QName(namespaceURI, localPart);
} }
@Override /**
* 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.
*/
default String getLanguage() { default String getLanguage() {
return null; return null;
} }

View file

@ -42,7 +42,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
* *
* @author Matt Tucker * @author Matt Tucker
*/ */
public abstract class IQ extends Stanza implements IqView { public abstract class IQ extends Stanza {
// Don't name this field 'ELEMENT'. When it comes to IQ, ELEMENT is the child element! // Don't name this field 'ELEMENT'. When it comes to IQ, ELEMENT is the child element!
public static final String IQ_ELEMENT = "iq"; public static final String IQ_ELEMENT = "iq";
@ -54,7 +54,7 @@ public abstract class IQ extends Stanza implements IqView {
private Type type = Type.get; private Type type = Type.get;
protected IQ(IQ iq) { public IQ(IQ iq) {
super(iq); super(iq);
type = iq.getType(); type = iq.getType();
this.childElementName = iq.childElementName; this.childElementName = iq.childElementName;
@ -62,16 +62,7 @@ public abstract class IQ extends Stanza implements IqView {
this.childElementQName = iq.childElementQName; this.childElementQName = iq.childElementQName;
} }
// TODO: Deprecate when stanza builder is ready.
protected IQ(String childElementName, String childElementNamespace) { 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.childElementName = childElementName;
this.childElementNamespace = childElementNamespace; this.childElementNamespace = childElementNamespace;
if (childElementName == null) { if (childElementName == null) {
@ -81,7 +72,11 @@ public abstract class IQ extends Stanza implements IqView {
} }
} }
@Override /**
* Returns the type of the IQ packet.
*
* @return the type of the IQ packet.
*/
public Type getType() { public Type getType() {
return type; return type;
} }
@ -95,7 +90,6 @@ public abstract class IQ extends Stanza implements IqView {
* *
* @param type the type of the IQ packet. * @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) { public void setType(Type type) {
this.type = Objects.requireNonNull(type, "type must not be null"); this.type = Objects.requireNonNull(type, "type must not be null");
} }
@ -266,6 +260,19 @@ public abstract class IQ extends Stanza implements IqView {
*/ */
protected abstract IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml); 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} * 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} * IQ based on a {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set}
@ -304,7 +311,7 @@ public abstract class IQ extends Stanza implements IqView {
* {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set}. * {@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. * @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) { public static ErrorIQ createErrorResponse(final IQ request, final StanzaError.Builder error) {
if (!request.isRequestIQ()) { if (!request.isRequestIQ()) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"IQ must be of type 'set' or 'get'. Original IQ: " + request.toXML()); "IQ must be of type 'set' or 'get'. Original IQ: " + request.toXML());
@ -314,25 +321,35 @@ public abstract class IQ extends Stanza implements IqView {
result.setFrom(request.getTo()); result.setFrom(request.getTo());
result.setTo(request.getFrom()); result.setTo(request.getFrom());
error.setStanza(result);
return result; return result;
} }
/** public static ErrorIQ createErrorResponse(final IQ request, final StanzaError.Condition condition) {
* Deprecated. return createErrorResponse(request, StanzaError.getBuilder(condition));
*
* @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());
} }
public static ErrorIQ createErrorResponse(final IQ request, final StanzaError.Condition condition) { /**
return createErrorResponse(request, StanzaError.getBuilder(condition).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:<ul>
* <li>The sender set to the recipient of the originating IQ.
* <li>The recipient set to the sender of the originating IQ.
* <li>The type set to {@link Type#error IQ.Type.error}.
* <li>The id set to the id of the originating IQ.
* <li>The child element contained in the associated originating IQ.
* <li>The provided {@link StanzaError XMPPError}.
* </ul>
*
* @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));
} }
/** /**
@ -375,25 +392,6 @@ public abstract class IQ extends Stanza implements IqView {
} }
} }
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 { public static class IQChildElementXmlStringBuilder extends XmlStringBuilder {
private final String element; private final String element;

View file

@ -1,44 +0,0 @@
/**
*
* 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<IB extends IqBuilder<IB, I>, I extends IQ>
extends AbstractIqBuilder<IB> {
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();
}

View file

@ -1,44 +0,0 @@
/**
*
* 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<IqData> {
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;
}
}

View file

@ -1,28 +0,0 @@
/**
*
* 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();
}

View file

@ -24,8 +24,6 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.util.EqualsUtil; import org.jivesoftware.smack.util.EqualsUtil;
import org.jivesoftware.smack.util.HashCode; import org.jivesoftware.smack.util.HashCode;
import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.Objects;
@ -60,8 +58,7 @@ import org.jxmpp.stringprep.XmppStringprepException;
* *
* @author Matt Tucker * @author Matt Tucker
*/ */
public final class Message extends MessageOrPresence<MessageBuilder> public final class Message extends Stanza implements TypedCloneable<Message> {
implements MessageView, TypedCloneable<Message> {
public static final String ELEMENT = "message"; public static final String ELEMENT = "message";
public static final String BODY = "body"; public static final String BODY = "body";
@ -69,12 +66,11 @@ public final class Message extends MessageOrPresence<MessageBuilder>
private Type type; private Type type;
private String thread = null; private String thread = null;
private final Set<Subject> subjects = new HashSet<Subject>();
/** /**
* Creates a new, "normal" message. * Creates a new, "normal" message.
* @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead.
*/ */
@Deprecated
// TODO: Remove in Smack 4.5.
public Message() { public Message() {
} }
@ -82,10 +78,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* Creates a new "normal" message to the specified recipient. * Creates a new "normal" message to the specified recipient.
* *
* @param to the recipient of the message. * @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) { public Message(Jid to) {
setTo(to); setTo(to);
} }
@ -95,10 +88,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* *
* @param to the user to send the message to. * @param to the user to send the message to.
* @param type the message type. * @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) { public Message(Jid to, Type type) {
this(to); this(to);
setType(type); setType(type);
@ -109,10 +99,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* *
* @param to the user to send the message to. * @param to the user to send the message to.
* @param body the body of the message. * @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) { public Message(Jid to, String body) {
this(to); this(to);
setBody(body); setBody(body);
@ -124,10 +111,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* @param to the user to send the message to. * @param to the user to send the message to.
* @param body the body of the message. * @param body the body of the message.
* @throws XmppStringprepException if 'to' is not a valid XMPP address. * @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 { public Message(String to, String body) throws XmppStringprepException {
this(JidCreate.from(to), body); this(JidCreate.from(to), body);
} }
@ -138,21 +122,12 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* @param to TODO javadoc me please * @param to TODO javadoc me please
* @param extensionElement TODO javadoc me please * @param extensionElement TODO javadoc me please
* @since 4.2 * @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) { public Message(Jid to, ExtensionElement extensionElement) {
this(to); this(to);
addExtension(extensionElement); addExtension(extensionElement);
} }
Message(MessageBuilder messageBuilder) {
super(messageBuilder);
type = messageBuilder.type;
thread = messageBuilder.thread;
}
/** /**
* Copy constructor. * Copy constructor.
* <p> * <p>
@ -166,9 +141,15 @@ public final class Message extends MessageOrPresence<MessageBuilder>
super(other); super(other);
this.type = other.type; this.type = other.type;
this.thread = other.thread; this.thread = other.thread;
this.subjects.addAll(other.subjects);
} }
@Override /**
* 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.
*/
public Type getType() { public Type getType() {
if (type == null) { if (type == null) {
return Type.normal; return Type.normal;
@ -180,10 +161,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* Sets the type of the message. * Sets the type of the message.
* *
* @param type 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) { public void setType(Type type) {
this.type = type; this.type = type;
} }
@ -217,9 +195,8 @@ public final class Message extends MessageOrPresence<MessageBuilder>
private Subject getMessageSubject(String language) { private Subject getMessageSubject(String language) {
language = determineLanguage(language); language = determineLanguage(language);
for (Subject subject : getSubjects()) { for (Subject subject : subjects) {
if (Objects.equals(language, subject.language) if (Objects.equals(language, subject.language)) {
|| (subject.language == null && Objects.equals(this.language, language))) {
return subject; return subject;
} }
} }
@ -233,12 +210,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* @return a collection of all subjects in this message. * @return a collection of all subjects in this message.
*/ */
public Set<Subject> getSubjects() { public Set<Subject> getSubjects() {
List<Subject> subjectList = getExtensions(Subject.class); return Collections.unmodifiableSet(subjects);
Set<Subject> subjects = new HashSet<>(subjectList.size());
subjects.addAll(subjectList);
return subjects;
} }
/** /**
@ -246,10 +218,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* message contents. * message contents.
* *
* @param subject the subject of the message. * @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) { public void setSubject(String subject) {
if (subject == null) { if (subject == null) {
removeSubject(""); // use empty string because #removeSubject(null) is ambiguous removeSubject(""); // use empty string because #removeSubject(null) is ambiguous
@ -266,20 +235,10 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* @return the new {@link org.jivesoftware.smack.packet.Message.Subject} * @return the new {@link org.jivesoftware.smack.packet.Message.Subject}
* @throws NullPointerException if the subject is null, a null pointer exception is thrown * @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) { public Subject addSubject(String language, String subject) {
language = determineLanguage(language); language = determineLanguage(language);
List<Subject> 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); Subject messageSubject = new Subject(language, subject);
addExtension(messageSubject); subjects.add(messageSubject);
return messageSubject; return messageSubject;
} }
@ -289,13 +248,11 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* @param language the language of the subject which is to be removed * @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. * @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) { public boolean removeSubject(String language) {
language = determineLanguage(language); language = determineLanguage(language);
for (Subject subject : getExtensions(Subject.class)) { for (Subject subject : subjects) {
if (language.equals(subject.language)) { if (language.equals(subject.language)) {
return removeSubject(subject); return subjects.remove(subject);
} }
} }
return false; return false;
@ -307,10 +264,8 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* @param subject the subject being removed from the message. * @param subject the subject being removed from the message.
* @return true if the subject was successfully removed and false if it was not. * @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) { public boolean removeSubject(Subject subject) {
return removeExtension(subject) != null; return subjects.remove(subject);
} }
/** /**
@ -321,7 +276,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
public List<String> getSubjectLanguages() { public List<String> getSubjectLanguages() {
Subject defaultSubject = getMessageSubject(null); Subject defaultSubject = getMessageSubject(null);
List<String> languages = new ArrayList<String>(); List<String> languages = new ArrayList<String>();
for (Subject subject : getExtensions(Subject.class)) { for (Subject subject : subjects) {
if (!subject.equals(defaultSubject)) { if (!subject.equals(defaultSubject)) {
languages.add(subject.language); languages.add(subject.language);
} }
@ -390,10 +345,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* @param body the body of the message. * @param body the body of the message.
* @see #setBody(String) * @see #setBody(String)
* @since 4.2 * @since 4.2
* @deprecated use {@link StanzaBuilder} instead.
*/ */
@Deprecated
// TODO: Remove when stanza builder is ready.
public void setBody(CharSequence body) { public void setBody(CharSequence body) {
String bodyString; String bodyString;
if (body != null) { if (body != null) {
@ -408,10 +360,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* Sets the body of the message. The body is the main message contents. * Sets the body of the message. The body is the main message contents.
* *
* @param body the body of the message. * @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) { public void setBody(String body) {
if (body == null) { if (body == null) {
removeBody(""); // use empty string because #removeBody(null) is ambiguous removeBody(""); // use empty string because #removeBody(null) is ambiguous
@ -428,10 +377,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* @return the new {@link org.jivesoftware.smack.packet.Message.Body} * @return the new {@link org.jivesoftware.smack.packet.Message.Body}
* @throws NullPointerException if the body is null, a null pointer exception is thrown * @throws NullPointerException if the body is null, a null pointer exception is thrown
* @since 3.0.2 * @since 3.0.2
* @deprecated use {@link StanzaBuilder} instead.
*/ */
@Deprecated
// TODO: Remove when stanza builder is ready.
public Body addBody(String language, String body) { public Body addBody(String language, String body) {
language = determineLanguage(language); language = determineLanguage(language);
@ -447,10 +393,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* *
* @param language the language of the body which is to be removed * @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. * @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) { public boolean removeBody(String language) {
language = determineLanguage(language); language = determineLanguage(language);
for (Body body : getBodies()) { for (Body body : getBodies()) {
@ -469,10 +412,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* @param body the body being removed from the message. * @param body the body being removed from the message.
* @return true if the body was successfully removed and false if it was not. * @return true if the body was successfully removed and false if it was not.
* @since 3.0.2 * @since 3.0.2
* @deprecated use {@link StanzaBuilder} instead.
*/ */
@Deprecated
// TODO: Remove when stanza builder is ready.
public boolean removeBody(Body body) { public boolean removeBody(Body body) {
ExtensionElement removedElement = removeExtension(body); ExtensionElement removedElement = removeExtension(body);
return removedElement != null; return removedElement != null;
@ -510,10 +450,7 @@ public final class Message extends MessageOrPresence<MessageBuilder>
* of "chat" messages. * of "chat" messages.
* *
* @param thread the thread id of the message. * @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) { public void setThread(String thread) {
this.thread = thread; this.thread = thread;
} }
@ -535,11 +472,6 @@ public final class Message extends MessageOrPresence<MessageBuilder>
return ELEMENT; return ELEMENT;
} }
@Override
public MessageBuilder asBuilder() {
return StanzaBuilder.buildMessageFrom(this, getStanzaId());
}
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@ -559,6 +491,18 @@ public final class Message extends MessageOrPresence<MessageBuilder>
buf.optAttribute("type", type); buf.optAttribute("type", type);
buf.rightAngleBracket(); 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); buf.optElement("thread", thread);
// Append the error subpacket if the message type is an error. // Append the error subpacket if the message type is an error.
if (type == Type.error) { if (type == Type.error) {
@ -593,12 +537,10 @@ public final class Message extends MessageOrPresence<MessageBuilder>
public static final String ELEMENT = "subject"; public static final String ELEMENT = "subject";
public static final String NAMESPACE = StreamOpen.CLIENT_NAMESPACE; public static final String NAMESPACE = StreamOpen.CLIENT_NAMESPACE;
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
private final String subject; private final String subject;
private final String language; private final String language;
public Subject(String language, String subject) { private Subject(String language, String subject) {
if (subject == null) { if (subject == null) {
throw new NullPointerException("Subject cannot be null."); throw new NullPointerException("Subject cannot be null.");
} }
@ -666,7 +608,6 @@ public final class Message extends MessageOrPresence<MessageBuilder>
public static final String ELEMENT = "body"; public static final String ELEMENT = "body";
public static final String NAMESPACE = StreamOpen.CLIENT_NAMESPACE; public static final String NAMESPACE = StreamOpen.CLIENT_NAMESPACE;
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
enum BodyElementNamespace { enum BodyElementNamespace {
client(StreamOpen.CLIENT_NAMESPACE), client(StreamOpen.CLIENT_NAMESPACE),

View file

@ -1,165 +0,0 @@
/**
*
* 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<Message, MessageBuilder> 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;
}
}

View file

@ -1,36 +0,0 @@
/**
*
* 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<MPB extends MessageOrPresenceBuilder<?, ?>> 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();
}

View file

@ -1,42 +0,0 @@
/**
*
* 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<MP extends MessageOrPresence<? extends MessageOrPresenceBuilder<MP, SB>>, SB extends StanzaBuilder<SB>>
extends StanzaBuilder<SB> {
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();
}

View file

@ -1,29 +0,0 @@
/**
*
* 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();
}

View file

@ -19,8 +19,7 @@ package org.jivesoftware.smack.packet;
import java.util.Locale; import java.util.Locale;
import javax.net.SocketFactory; import org.jivesoftware.smack.packet.id.StanzaIdUtil;
import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.TypedCloneable; import org.jivesoftware.smack.util.TypedCloneable;
@ -61,8 +60,7 @@ import org.jxmpp.jid.Jid;
* *
* @author Matt Tucker * @author Matt Tucker
*/ */
public final class Presence extends MessageOrPresence<PresenceBuilder> public final class Presence extends Stanza implements TypedCloneable<Presence> {
implements PresenceView, TypedCloneable<Presence> {
public static final String ELEMENT = "presence"; public static final String ELEMENT = "presence";
@ -83,10 +81,7 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
* Creates a new presence update. Status, priority, and mode are left un-set. * Creates a new presence update. Status, priority, and mode are left un-set.
* *
* @param type the type. * @param type the type.
* @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
*/ */
@Deprecated
// TODO: Remove in Smack 4.5.
public Presence(Type type) { public Presence(Type type) {
// Ensure that the stanza ID is set by calling super(). // Ensure that the stanza ID is set by calling super().
super(); super();
@ -99,10 +94,7 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
* @param to the recipient. * @param to the recipient.
* @param type the type. * @param type the type.
* @since 4.2 * @since 4.2
* @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
*/ */
@Deprecated
// TODO: Remove in Smack 4.5.
public Presence(Jid to, Type type) { public Presence(Jid to, Type type) {
this(type); this(type);
setTo(to); setTo(to);
@ -115,10 +107,7 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
* @param status a text message describing the presence update. * @param status a text message describing the presence update.
* @param priority the priority of this presence update. * @param priority the priority of this presence update.
* @param mode the mode type for 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) { public Presence(Type type, String status, int priority, Mode mode) {
// Ensure that the stanza ID is set by calling super(). // Ensure that the stanza ID is set by calling super().
super(); super();
@ -128,14 +117,6 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
setMode(mode); setMode(mode);
} }
Presence(PresenceBuilder presenceBuilder) {
super(presenceBuilder);
type = presenceBuilder.type;
status = presenceBuilder.status;
priority = presenceBuilder.priority;
mode = presenceBuilder.mode;
}
/** /**
* Copy constructor. * Copy constructor.
* <p> * <p>
@ -182,7 +163,11 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
return type == Type.available && (mode == Mode.away || mode == Mode.xa || mode == Mode.dnd); return type == Type.available && (mode == Mode.away || mode == Mode.xa || mode == Mode.dnd);
} }
@Override /**
* Returns the type of this presence packet.
*
* @return the type of the presence packet.
*/
public Type getType() { public Type getType() {
return type; return type;
} }
@ -191,15 +176,18 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
* Sets the type of the presence packet. * Sets the type of the presence packet.
* *
* @param type 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) { public void setType(Type type) {
this.type = Objects.requireNonNull(type, "Type cannot be null"); this.type = Objects.requireNonNull(type, "Type cannot be null");
} }
@Override /**
* Returns the status message of the presence update, or <code>null</code> 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.
*/
public String getStatus() { public String getStatus() {
return status; return status;
} }
@ -209,21 +197,18 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
* describing a user's presence (i.e., "gone to lunch"). * describing a user's presence (i.e., "gone to lunch").
* *
* @param status the status message. * @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) { public void setStatus(String status) {
this.status = status; this.status = status;
} }
@Override /**
* Returns the priority of the presence.
*
* @return the priority.
* @see <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3. Priority Element</a>
*/
public int getPriority() { public int getPriority() {
return getPriorityByte();
}
@Override
public byte getPriorityByte() {
if (priority == null) { if (priority == null) {
return 0; return 0;
} }
@ -236,10 +221,7 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
* @param priority the priority of the presence. * @param priority the priority of the presence.
* @throws IllegalArgumentException if the priority is outside the valid range. * @throws IllegalArgumentException if the priority is outside the valid range.
* @see <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3. Priority Element</a> * @see <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3. Priority Element</a>
* @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
*/ */
@Deprecated
// TODO: Remove in Smack 4.5.
public void setPriority(int priority) { public void setPriority(int priority) {
if (priority < -128 || priority > 127) { if (priority < -128 || priority > 127) {
throw new IllegalArgumentException("Priority value " + priority + throw new IllegalArgumentException("Priority value " + priority +
@ -252,7 +234,11 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
this.priority = priority; this.priority = priority;
} }
@Override /**
* Returns the mode of the presence update.
*
* @return the mode.
*/
public Mode getMode() { public Mode getMode() {
if (mode == null) { if (mode == null) {
return Mode.available; return Mode.available;
@ -265,10 +251,7 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
* to be the same thing as {@link Presence.Mode#available}. * to be the same thing as {@link Presence.Mode#available}.
* *
* @param mode the mode. * @param mode the mode.
* @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
*/ */
@Deprecated
// TODO: Remove in Smack 4.5.
public void setMode(Mode mode) { public void setMode(Mode mode) {
this.mode = mode; this.mode = mode;
} }
@ -278,11 +261,6 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
return ELEMENT; return ELEMENT;
} }
@Override
public PresenceBuilder asBuilder() {
return StanzaBuilder.buildPresenceFrom(this, getStanzaId());
}
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@ -348,7 +326,7 @@ public final class Presence extends MessageOrPresence<PresenceBuilder>
*/ */
public Presence cloneWithNewId() { public Presence cloneWithNewId() {
Presence clone = clone(); Presence clone = clone();
clone.setNewStanzaId(); clone.setStanzaId(StanzaIdUtil.newStanzaId());
return clone; return clone;
} }

View file

@ -1,141 +0,0 @@
/**
*
* 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<Presence, PresenceBuilder> 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;
}
}

View file

@ -1,59 +0,0 @@
/**
*
* 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 <code>null</code> 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 <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3. Priority Element</a>
*/
int getPriority();
/**
* Returns the priority of the presence.
*
* @return the priority.
* @see <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3. Priority Element</a>
*/
byte getPriorityByte();
/**
* Returns the mode of the presence update.
*
* @return the mode.
*/
Presence.Mode getMode();
}

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2014-2019 Florian Schmaus * Copyright © 2014 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,10 +29,6 @@ public abstract class SimpleIQ extends IQ {
super(childElementName, childElementNamespace); super(childElementName, childElementNamespace);
} }
protected SimpleIQ(IqData iqBuilder, String childElementName, String childElementNamespace) {
super(iqBuilder, childElementName, childElementNamespace);
}
@Override @Override
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
xml.setEmptyElement(); xml.setEmptyElement();

View file

@ -20,19 +20,15 @@ package org.jivesoftware.smack.packet;
import static org.jivesoftware.smack.util.StringUtils.requireNotNullNorEmpty; import static org.jivesoftware.smack.util.StringUtils.requireNotNullNorEmpty;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.id.StandardStanzaIdSource; import org.jivesoftware.smack.packet.id.StanzaIdUtil;
import org.jivesoftware.smack.packet.id.StanzaIdSource;
import org.jivesoftware.smack.util.MultiMap; import org.jivesoftware.smack.util.MultiMap;
import org.jivesoftware.smack.util.PacketUtil; import org.jivesoftware.smack.util.PacketUtil;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smack.util.XmppElementUtil;
import org.jxmpp.jid.Jid; import org.jxmpp.jid.Jid;
@ -47,16 +43,12 @@ import org.jxmpp.jid.Jid;
* XMPP Stanzas are {@link Message}, {@link IQ} and {@link Presence}. Which therefore subclass this * XMPP Stanzas are {@link Message}, {@link IQ} and {@link Presence}. Which therefore subclass this
* class. <b>If you think you need to subclass this class, then you are doing something wrong.</b> * class. <b>If you think you need to subclass this class, then you are doing something wrong.</b>
* </p> * </p>
* <p>
* 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.
* </p>
* *
* @author Matt Tucker * @author Matt Tucker
* @author Florian Schmaus * @author Florian Schmaus
* @see <a href="http://xmpp.org/rfcs/rfc6120.html#stanzas">RFC 6120 § 8. XML Stanzas</a> * @see <a href="http://xmpp.org/rfcs/rfc6120.html#stanzas">RFC 6120 § 8. XML Stanzas</a>
*/ */
public abstract class Stanza implements StanzaView, TopLevelStreamElement { public abstract class Stanza implements TopLevelStreamElement {
public static final String TEXT = "text"; public static final String TEXT = "text";
public static final String ITEM = "item"; public static final String ITEM = "item";
@ -64,14 +56,12 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
protected static final String DEFAULT_LANGUAGE = protected static final String DEFAULT_LANGUAGE =
java.util.Locale.getDefault().getLanguage().toLowerCase(Locale.US); java.util.Locale.getDefault().getLanguage().toLowerCase(Locale.US);
private final MultiMap<QName, ExtensionElement> extensionElements; private final MultiMap<QName, ExtensionElement> extensionElements = new MultiMap<>();
// Assume that all stanzas Smack handles are in the client namespace, since Smack is an XMPP client library. We can // 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. // change this behavior later if it is required.
private final String namespace = StreamOpen.CLIENT_NAMESPACE; private final String namespace = StreamOpen.CLIENT_NAMESPACE;
private final StanzaIdSource usedStanzaIdSource;
private String id = null; private String id = null;
private Jid to; private Jid to;
private Jid from; private Jid from;
@ -90,47 +80,31 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
protected String language; protected String language;
protected Stanza() { protected Stanza() {
extensionElements = new MultiMap<>(); this(StanzaIdUtil.newStanzaId());
usedStanzaIdSource = null;
id = StandardStanzaIdSource.DEFAULT.getNewStanzaId();
} }
protected Stanza(StanzaBuilder<?> stanzaBuilder) { protected Stanza(String stanzaId) {
if (stanzaBuilder.stanzaIdSource != null) { setStanzaId(stanzaId);
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) { protected Stanza(Stanza p) {
usedStanzaIdSource = p.usedStanzaIdSource;
id = p.getStanzaId(); id = p.getStanzaId();
to = p.getTo(); to = p.getTo();
from = p.getFrom(); from = p.getFrom();
error = p.error; error = p.error;
extensionElements = p.extensionElements.clone(); // Copy extensions
for (ExtensionElement pe : p.getExtensions()) {
addExtension(pe);
}
} }
@Override /**
public final String getStanzaId() { * Returns the unique ID of the stanza. The returned value could be <code>null</code>.
*
* @return the packet's unique ID or <code>null</code> if the id is not available.
*/
public String getStanzaId() {
return id; return id;
} }
@ -153,7 +127,7 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* @return true if the stanza ID is set, false otherwise. * @return true if the stanza ID is set, false otherwise.
* @since 4.1 * @since 4.1
*/ */
public final boolean hasStanzaIdSet() { public boolean hasStanzaIdSet() {
// setStanzaId ensures that the id is either null or not empty, // setStanzaId ensures that the id is either null or not empty,
// so we can assume that it is set if it's not null. // so we can assume that it is set if it's not null.
return id != null; return id != null;
@ -164,51 +138,57 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* *
* @return the stanza id. * @return the stanza id.
* @since 4.2 * @since 4.2
* @deprecated use {@link StanzaBuilder} instead. * @deprecated use {@link #setNewStanzaId()} instead.
*/ */
@Deprecated @Deprecated
// TODO: Remove in Smack 4.5. // TODO: Remove in Smack 4.5.
public String setStanzaId() { public String setStanzaId() {
if (!hasStanzaIdSet()) { return ensureStanzaIdSet();
setNewStanzaId();
}
return getStanzaId();
} }
/** /**
* Throws an {@link IllegalArgumentException} if this stanza has no stanza ID set. * Set a new stanza ID even if there is already one set.
* *
* @throws IllegalArgumentException if this stanza has no stanza ID set. * @return the stanza id.
* @since 4.4. * @since 4.4
*/ */
public final void throwIfNoStanzaId() { public String setNewStanzaId() {
if (hasStanzaIdSet()) { return ensureStanzaIdSet(true);
return; }
}
throw new IllegalArgumentException("The stanza has no RFC stanza ID set, although one is required"); /**
* 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. * Ensure that a stanza ID is set.
* *
* @param forceNew force a new ID even if there is already one set.
* @return the stanza ID. * @return the stanza ID.
* @since 4.4 * @since 4.4
*/ */
// TODO: Remove this method once StanzaBuilder is ready. private String ensureStanzaIdSet(boolean forceNew) {
protected String setNewStanzaId() { if (forceNew || !hasStanzaIdSet()) {
if (usedStanzaIdSource != null) { setStanzaId(StanzaIdUtil.newStanzaId());
id = usedStanzaIdSource.getNewStanzaId();
} }
else {
id = StandardStanzaIdSource.DEFAULT.getNewStanzaId();
}
return getStanzaId(); return getStanzaId();
} }
@Override /**
public final Jid getTo() { * Returns who the stanza is being sent "to", or <code>null</code> if
* the value is not set. The XMPP protocol often makes the "to"
* attribute optional, so it does not always need to be set.<p>
*
* @return who the stanza is being sent to, or <code>null</code> if the
* value has not been set.
*/
public Jid getTo() {
return to; return to;
} }
@ -218,13 +198,19 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* *
* @param to who the packet is being sent to. * @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) { public void setTo(Jid to) {
this.to = to; this.to = to;
} }
@Override /**
public final Jid getFrom() { * Returns who the stanza is being sent "from" or <code>null</code> if
* the value is not set. The XMPP protocol often makes the "from"
* attribute optional, so it does not always need to be set.<p>
*
* @return who the stanza is being sent from, or <code>null</code> if the
* value has not been set.
*/
public Jid getFrom() {
return from; return from;
} }
@ -235,39 +221,35 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* *
* @param from who the packet is being sent to. * @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) { public void setFrom(Jid from) {
this.from = from; this.from = from;
} }
@Override /**
public final StanzaError getError() { * Returns the error associated with this packet, or <code>null</code> if there are
* no errors.
*
* @return the error sub-packet or <code>null</code> if there isn't an error.
*/
public StanzaError getError() {
return error; return error;
} }
/** /**
* Sets the error for this stanza. * Sets the error for this stanza.
* *
* @param stanzaError the error that this stanza carries and hence signals. * @param xmppErrorBuilder the error to associate with this stanza.
*/ */
// TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public void setError(StanzaError.Builder xmppErrorBuilder) {
public void setError(StanzaError stanzaError) { if (xmppErrorBuilder == null) {
error = stanzaError; return;
} }
xmppErrorBuilder.setStanza(this);
/** error = xmppErrorBuilder.build();
* 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 @Override
public final String getLanguage() { public String getLanguage() {
return language; return language;
} }
@ -275,32 +257,23 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* Sets the xml:lang of this Stanza. * Sets the xml:lang of this Stanza.
* *
* @param language 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) { public void setLanguage(String language) {
this.language = language; this.language = language;
} }
@Override /**
public final List<ExtensionElement> getExtensions() { * Returns a list of all extension elements of this stanza.
*
* @return a list of all extension elements of this stanza.
*/
public List<ExtensionElement> getExtensions() {
synchronized (extensionElements) { synchronized (extensionElements) {
// No need to create a new list, values() will already create a new one for us // No need to create a new list, values() will already create a new one for us
return extensionElements.values(); return extensionElements.values();
} }
} }
public final MultiMap<QName, ExtensionElement> getExtensionsMap() {
return cloneExtensionsMap();
}
final MultiMap<QName, ExtensionElement> cloneExtensionsMap() {
synchronized (extensionElements) {
return extensionElements.clone();
}
}
/** /**
* Return a list of all extensions with the given element name <em>and</em> namespace. * Return a list of all extensions with the given element name <em>and</em> namespace.
* <p> * <p>
@ -312,27 +285,11 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* @return a set of all matching extensions. * @return a set of all matching extensions.
* @since 4.1 * @since 4.1
*/ */
public final List<ExtensionElement> getExtensions(String elementName, String namespace) { public List<ExtensionElement> getExtensions(String elementName, String namespace) {
requireNotNullNorEmpty(elementName, "elementName must not be null nor empty"); requireNotNullNorEmpty(elementName, "elementName must not be null nor empty");
requireNotNullNorEmpty(namespace, "namespace must not be null nor empty"); requireNotNullNorEmpty(namespace, "namespace must not be null nor empty");
QName key = new QName(namespace, elementName); QName key = new QName(namespace, elementName);
return getExtensions(key); return extensionElements.getAll(key);
}
@Override
public final List<ExtensionElement> getExtensions(QName qname) {
List<ExtensionElement> res;
synchronized (extensionElements) {
res = extensionElements.getAll(qname);
}
return Collections.unmodifiableList(res);
}
@Override
public final <E extends ExtensionElement> List<E> getExtensions(Class<E> extensionElementClass) {
synchronized (extensionElements) {
return XmppElementUtil.getElementsFrom(extensionElements, extensionElementClass);
}
} }
/** /**
@ -344,7 +301,7 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* @param namespace the namespace of the extension that is desired. * @param namespace the namespace of the extension that is desired.
* @return the stanza extension with the given namespace. * @return the stanza extension with the given namespace.
*/ */
public final ExtensionElement getExtension(String namespace) { public ExtensionElement getExtension(String namespace) {
return PacketUtil.extensionElementFrom(getExtensions(), null, namespace); return PacketUtil.extensionElementFrom(getExtensions(), null, namespace);
} }
@ -360,37 +317,27 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* @return the extension, or <code>null</code> if it doesn't exist. * @return the extension, or <code>null</code> if it doesn't exist.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final <PE extends ExtensionElement> PE getExtension(String elementName, String namespace) { public <PE extends ExtensionElement> PE getExtension(String elementName, String namespace) {
if (namespace == null) { if (namespace == null) {
return null; return null;
} }
QName key = new QName(namespace, elementName); QName key = new QName(namespace, elementName);
ExtensionElement packetExtension = getExtension(key); ExtensionElement packetExtension;
synchronized (extensionElements) {
packetExtension = extensionElements.getFirst(key);
}
if (packetExtension == null) { if (packetExtension == null) {
return null; return null;
} }
return (PE) packetExtension; return (PE) packetExtension;
} }
@SuppressWarnings("unchecked")
@Override
public final <E extends ExtensionElement> E getExtension(QName qname) {
synchronized (extensionElements) {
return (E) extensionElements.getFirst(qname);
}
}
/** /**
* Adds a stanza extension to the packet. Does nothing if extension is null. * Adds a stanza extension to the packet. Does nothing if extension is null.
* <p>
* Please note that although this method is not yet marked as deprecated, it is recommended to use
* {@link StanzaBuilder#addExtension(ExtensionElement)} instead.
* </p>
* *
* @param extension a stanza extension. * @param extension a stanza extension.
*/ */
// TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public void addExtension(ExtensionElement extension) {
public final void addExtension(ExtensionElement extension) {
if (extension == null) return; if (extension == null) return;
QName key = extension.getQName(); QName key = extension.getQName();
synchronized (extensionElements) { synchronized (extensionElements) {
@ -401,17 +348,12 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
/** /**
* Add the given extension and override eventually existing extensions with the same name and * Add the given extension and override eventually existing extensions with the same name and
* namespace. * namespace.
* <p>
* Please note that although this method is not yet marked as deprecated, it is recommended to use
* {@link StanzaBuilder#overrideExtension(ExtensionElement)} instead.
* </p>
* *
* @param extension the extension element to add. * @param extension the extension element to add.
* @return one of the removed extensions or <code>null</code> if there are none. * @return one of the removed extensions or <code>null</code> if there are none.
* @since 4.1.2 * @since 4.1.2
*/ */
// TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public ExtensionElement overrideExtension(ExtensionElement extension) {
public final ExtensionElement overrideExtension(ExtensionElement extension) {
if (extension == null) return null; if (extension == null) return null;
synchronized (extensionElements) { synchronized (extensionElements) {
// Note that we need to use removeExtension(String, String) here. If would use // Note that we need to use removeExtension(String, String) here. If would use
@ -428,8 +370,7 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* *
* @param extensions a collection of stanza extensions * @param extensions a collection of stanza extensions
*/ */
// TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public void addExtensions(Collection<ExtensionElement> extensions) {
public final void addExtensions(Collection<ExtensionElement> extensions) {
if (extensions == null) return; if (extensions == null) return;
for (ExtensionElement packetExtension : extensions) { for (ExtensionElement packetExtension : extensions) {
addExtension(packetExtension); addExtension(packetExtension);
@ -446,7 +387,7 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* @param namespace TODO javadoc me please * @param namespace TODO javadoc me please
* @return true if a stanza extension exists, false otherwise. * @return true if a stanza extension exists, false otherwise.
*/ */
public final boolean hasExtension(String elementName, String namespace) { public boolean hasExtension(String elementName, String namespace) {
if (elementName == null) { if (elementName == null) {
return hasExtension(namespace); return hasExtension(namespace);
} }
@ -456,9 +397,13 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
} }
} }
// Overridden in order to avoid an extra copy. /**
@Override * Check if a stanza extension with the given namespace exists.
public final boolean hasExtension(String namespace) { *
* @param namespace TODO javadoc me please
* @return true if a stanza extension exists, false otherwise.
*/
public boolean hasExtension(String namespace) {
synchronized (extensionElements) { synchronized (extensionElements) {
for (ExtensionElement packetExtension : extensionElements.values()) { for (ExtensionElement packetExtension : extensionElements.values()) {
if (packetExtension.getNamespace().equals(namespace)) { if (packetExtension.getNamespace().equals(namespace)) {
@ -476,8 +421,7 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* @param namespace TODO javadoc me please * @param namespace TODO javadoc me please
* @return the removed stanza extension or null. * @return the removed stanza extension or null.
*/ */
// TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. public ExtensionElement removeExtension(String elementName, String namespace) {
public final ExtensionElement removeExtension(String elementName, String namespace) {
QName key = new QName(namespace, elementName); QName key = new QName(namespace, elementName);
synchronized (extensionElements) { synchronized (extensionElements) {
return extensionElements.remove(key); return extensionElements.remove(key);
@ -489,11 +433,8 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* *
* @param extension the stanza extension to remove. * @param extension the stanza extension to remove.
* @return the removed stanza extension or null. * @return the removed stanza extension or null.
* @deprecated use {@link StanzaBuilder} instead.
*/ */
@Deprecated public ExtensionElement removeExtension(ExtensionElement extension) {
// TODO: Remove in Smack 4.5.
public final ExtensionElement removeExtension(ExtensionElement extension) {
QName key = extension.getQName(); QName key = extension.getQName();
synchronized (extensionElements) { synchronized (extensionElements) {
List<ExtensionElement> list = extensionElements.getAll(key); List<ExtensionElement> list = extensionElements.getAll(key);
@ -553,7 +494,7 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement {
* *
* @param xml the XmlStringBuilder to append the error to. * @param xml the XmlStringBuilder to append the error to.
*/ */
protected final void appendErrorIfExists(XmlStringBuilder xml) { protected void appendErrorIfExists(XmlStringBuilder xml) {
StanzaError error = getError(); StanzaError error = getError();
if (error != null) { if (error != null) {
xml.append(error); xml.append(error);

View file

@ -1,306 +0,0 @@
/**
*
* 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<B extends StanzaBuilder<B>> implements StanzaView {
final StanzaIdSource stanzaIdSource;
final String stanzaId;
Jid to;
Jid from;
StanzaError stanzaError;
String language;
MultiMap<QName, ExtensionElement> 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<? extends ExtensionElement> 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 extends ExtensionElement> E getExtension(QName qname) {
return (E) extensionElements.getFirst(qname);
}
@Override
public final List<ExtensionElement> getExtensions() {
return extensionElements.values();
}
@Override
public final List<ExtensionElement> getExtensions(QName qname) {
return extensionElements.getAll(qname);
}
@Override
public final <E extends ExtensionElement> List<E> getExtensions(Class<E> 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 extends StanzaBuilder<?>> SB buildResponse(StanzaView request, Function<SB, String> builderFromStanzaId) {
SB responseBuilder = builderFromStanzaId.apply(request.getStanzaId());
responseBuilder.to(request.getFrom())
.from(request.getTo())
;
return responseBuilder;
}
}

View file

@ -106,6 +106,7 @@ public class StanzaError extends AbstractError implements ExtensionElement {
private final String conditionText; private final String conditionText;
private final String errorGenerator; private final String errorGenerator;
private final Type type; private final Type type;
private final Stanza stanza;
/** /**
* Creates a new error with the specified type, condition and message. * Creates a new error with the specified type, condition and message.
@ -119,11 +120,13 @@ public class StanzaError extends AbstractError implements ExtensionElement {
* @param errorGenerator TODO javadoc me please * @param errorGenerator TODO javadoc me please
* @param descriptiveTexts TODO javadoc me please * @param descriptiveTexts TODO javadoc me please
* @param extensions list of stanza extensions * @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<String, String> descriptiveTexts, public StanzaError(Condition condition, String conditionText, String errorGenerator, Type type, Map<String, String> descriptiveTexts,
List<ExtensionElement> extensions) { List<ExtensionElement> extensions, Stanza stanza) {
super(descriptiveTexts, ERROR_CONDITION_AND_TEXT_NAMESPACE, extensions); super(descriptiveTexts, ERROR_CONDITION_AND_TEXT_NAMESPACE, extensions);
this.condition = Objects.requireNonNull(condition, "condition must not be null"); 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 // Some implementations may send the condition as non-empty element containing the empty string, that is
// <condition xmlns='foo'></condition>, in this case the parser may calls this constructor with the empty string // <condition xmlns='foo'></condition>, 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 // as conditionText, therefore reset it to null if it's the empty string
@ -181,6 +184,16 @@ public class StanzaError extends AbstractError implements ExtensionElement {
return conditionText; 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 @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder("XMPPError: "); StringBuilder sb = new StringBuilder("XMPPError: ");
@ -258,6 +271,7 @@ public class StanzaError extends AbstractError implements ExtensionElement {
private String conditionText; private String conditionText;
private String errorGenerator; private String errorGenerator;
private Type type; private Type type;
private Stanza stanza;
private Builder() { private Builder() {
} }
@ -282,11 +296,17 @@ public class StanzaError extends AbstractError implements ExtensionElement {
return this; return this;
} }
public Builder setStanza(Stanza stanza) {
this.stanza = stanza;
return this;
}
public Builder copyFrom(StanzaError xmppError) { public Builder copyFrom(StanzaError xmppError) {
setCondition(xmppError.getCondition()); setCondition(xmppError.getCondition());
setType(xmppError.getType()); setType(xmppError.getType());
setConditionText(xmppError.getConditionText()); setConditionText(xmppError.getConditionText());
setErrorGenerator(xmppError.getErrorGenerator()); setErrorGenerator(xmppError.getErrorGenerator());
setStanza(xmppError.getStanza());
setDescriptiveTexts(xmppError.descriptiveTexts); setDescriptiveTexts(xmppError.descriptiveTexts);
setTextNamespace(xmppError.textNamespace); setTextNamespace(xmppError.textNamespace);
setExtensions(xmppError.extensions); setExtensions(xmppError.extensions);
@ -295,7 +315,7 @@ public class StanzaError extends AbstractError implements ExtensionElement {
public StanzaError build() { public StanzaError build() {
return new StanzaError(condition, conditionText, errorGenerator, type, descriptiveTexts, return new StanzaError(condition, conditionText, errorGenerator, type, descriptiveTexts,
extensions); extensions, stanza);
} }
@Override @Override

View file

@ -1,53 +0,0 @@
/**
*
* 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);
}
}

View file

@ -1,102 +0,0 @@
/**
*
* 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 <code>null</code>.
*
* @return the packet's unique ID or <code>null</code> if the id is not available.
*/
String getStanzaId();
/**
* Returns who the stanza is being sent "to", or <code>null</code> if
* the value is not set. The XMPP protocol often makes the "to"
* attribute optional, so it does not always need to be set.<p>
*
* @return who the stanza is being sent to, or <code>null</code> if the
* value has not been set.
*/
Jid getTo();
/**
* Returns who the stanza is being sent "from" or <code>null</code> if
* the value is not set. The XMPP protocol often makes the "from"
* attribute optional, so it does not always need to be set.<p>
*
* @return who the stanza is being sent from, or <code>null</code> if the
* value has not been set.
*/
Jid getFrom();
/**
* Returns the error associated with this packet, or <code>null</code> if there are
* no errors.
*
* @return the error sub-packet or <code>null</code> if there isn't an error.
*/
StanzaError getError();
<E extends ExtensionElement> 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 extends ExtensionElement> E getExtension(Class<E> 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<ExtensionElement> getExtensions();
List<ExtensionElement> getExtensions(QName qname);
<E extends ExtensionElement> List<E> getExtensions(Class<E> extensionElementClass);
}

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2014-2019 Florian Schmaus * Copyright © 2014-2018 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -52,15 +52,9 @@ public class StartTls implements Nonza {
@Override @Override
public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) { public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace); XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace);
xml.rightAngleBracket();
if (required) { xml.condEmptyElement(required, "required");
xml.rightAngleBracket(); xml.closeElement(this);
xml.emptyElement("required");
xml.closeElement(this);
} else {
xml.closeEmptyElement();
}
return xml; return xml;
} }

View file

@ -18,6 +18,7 @@ package org.jivesoftware.smack.packet;
import org.jivesoftware.smack.util.ParserUtils; import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
public class XmlEnvironment { public class XmlEnvironment {

View file

@ -1,28 +0,0 @@
/**
*
* 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();
}

View file

@ -1,54 +0,0 @@
/**
*
* 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;
}
}
}

View file

@ -1,21 +0,0 @@
/**
*
* 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();
}

View file

@ -1,21 +0,0 @@
/**
*
* 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();
}

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2019 Florian Schmaus * Copyright 2003-2007 Jive Software, 2015 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,32 +20,20 @@ import java.util.concurrent.atomic.AtomicLong;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.StringUtils;
public class StandardStanzaIdSource implements StanzaIdSource { public class StanzaIdUtil {
public static final StandardStanzaIdSource DEFAULT = new StandardStanzaIdSource();
/** /**
* A prefix helps to make sure that ID's are unique across multiple instances. * A prefix helps to make sure that ID's are unique across multiple instances.
*/ */
private final String prefix = StringUtils.randomString(5) + "-"; private static final String PREFIX = StringUtils.randomString(5) + "-";
/** /**
* Keeps track of the current increment, which is appended to the prefix to * Keeps track of the current increment, which is appended to the prefix to
* forum a unique ID. * forum a unique ID.
*/ */
private final AtomicLong id = new AtomicLong(); private static 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());
} }
} }

View file

@ -1,41 +0,0 @@
/**
*
* 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;
}
}
}

View file

@ -39,7 +39,7 @@ public interface ParsingExceptionCallback {
* Called when parsing a stanza caused an exception. * Called when parsing a stanza caused an exception.
* *
* @param stanzaData the raw stanza data that caused the exception * @param stanzaData the raw stanza data that caused the exception
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
*/ */
void handleUnparsableStanza(UnparseableStanza stanzaData) throws IOException; void handleUnparsableStanza(UnparseableStanza stanzaData) throws IOException;

View file

@ -25,6 +25,7 @@ import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.provider.ExtensionElementProvider; import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.ParserUtils; import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smack.xml.XmlPullParserException;

View file

@ -1,45 +0,0 @@
/**
*
* 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<E extends Element> {
private final Class<E> 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<E>) elementType;
}
public final Class<E> getElementClass() {
return elementClass;
}
}

View file

@ -23,6 +23,7 @@ import java.io.IOException;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.ParserUtils; import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smack.xml.XmlPullParserException;

View file

@ -26,6 +26,7 @@ import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smack.xml.XmlPullParserException;

View file

@ -17,53 +17,15 @@
package org.jivesoftware.smack.provider; package org.jivesoftware.smack.provider;
import java.io.IOException;
import org.jivesoftware.smack.packet.IQ; 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;
/** /**
* <p>
* <b>Deprecation Notice:</b> This class is deprecated, use {@link IQProvider} instead.
* </p>
* An abstract class for parsing custom IQ packets. Each IQProvider must be registered with * 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 * the ProviderManager class for it to be used. Every implementation of this
* abstract class <b>must</b> have a public, no-argument constructor. * abstract class <b>must</b> have a public, no-argument constructor.
* *
* @author Matt Tucker * @author Matt Tucker
*/ */
public abstract class IQProvider<I extends IQ> extends IqProvider<I> { public abstract class IQProvider<I extends IQ> extends Provider<I> {
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;
} }

View file

@ -34,7 +34,7 @@ public final class IQProviderInfo extends AbstractProviderInfo {
* @param namespace Namespace that provider parses. * @param namespace Namespace that provider parses.
* @param iqProvider The provider implementation. * @param iqProvider The provider implementation.
*/ */
public IQProviderInfo(String elementName, String namespace, IqProvider<IQ> iqProvider) { public IQProviderInfo(String elementName, String namespace, IQProvider<IQ> iqProvider) {
super(elementName, namespace, iqProvider); super(elementName, namespace, iqProvider);
} }
} }

View file

@ -23,6 +23,7 @@ import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.ParserUtils; import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smack.xml.XmlPullParserException;

View file

@ -1,46 +0,0 @@
/**
*
* 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<I extends IQ> extends AbstractProvider<I> {
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;
}

View file

@ -18,11 +18,14 @@
package org.jivesoftware.smack.provider; package org.jivesoftware.smack.provider;
import java.io.IOException; 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.Element;
import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.util.ParserUtils; import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smack.xml.XmlPullParserException;
@ -37,7 +40,27 @@ import org.jivesoftware.smack.xml.XmlPullParserException;
* @author Florian Schmaus * @author Florian Schmaus
* @param <E> the type of the resulting element. * @param <E> the type of the resulting element.
*/ */
public abstract class Provider<E extends Element> extends AbstractProvider<E> { public abstract class Provider<E extends Element> {
private final Class<E> 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<E>) elementType;
}
public final Class<E> getElementClass() {
return elementClass;
}
public final E parse(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException { public final E parse(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException {
return parse(parser, null); return parse(parser, null);

View file

@ -80,8 +80,8 @@ public class ProviderFileLoader implements ProviderLoader {
// an IQ class, add the class object itself, then we'll use // an IQ class, add the class object itself, then we'll use
// reflection later to create instances of the class. // reflection later to create instances of the class.
// Add the provider to the map. // Add the provider to the map.
if (IqProvider.class.isAssignableFrom(provider)) { if (IQProvider.class.isAssignableFrom(provider)) {
IqProvider<IQ> iqProvider = (IqProvider<IQ>) provider.getConstructor().newInstance(); IQProvider<IQ> iqProvider = (IQProvider<IQ>) provider.getConstructor().newInstance();
iqProviders.add(new IQProviderInfo(elementName, namespace, iqProvider)); iqProviders.add(new IQProviderInfo(elementName, namespace, iqProvider));
} }
else { else {

View file

@ -113,7 +113,7 @@ import org.jivesoftware.smack.util.XmppElementUtil;
public final class ProviderManager { public final class ProviderManager {
private static final Map<QName, ExtensionElementProvider<ExtensionElement>> extensionProviders = new ConcurrentHashMap<>(); private static final Map<QName, ExtensionElementProvider<ExtensionElement>> extensionProviders = new ConcurrentHashMap<>();
private static final Map<QName, IqProvider<IQ>> iqProviders = new ConcurrentHashMap<>(); private static final Map<QName, IQProvider<IQ>> iqProviders = new ConcurrentHashMap<>();
private static final Map<QName, ExtensionElementProvider<ExtensionElement>> streamFeatureProviders = new ConcurrentHashMap<>(); private static final Map<QName, ExtensionElementProvider<ExtensionElement>> streamFeatureProviders = new ConcurrentHashMap<>();
private static final Map<QName, NonzaProvider<? extends Nonza>> nonzaProviders = new ConcurrentHashMap<>(); private static final Map<QName, NonzaProvider<? extends Nonza>> nonzaProviders = new ConcurrentHashMap<>();
@ -167,7 +167,7 @@ public final class ProviderManager {
* @param namespace the XML namespace. * @param namespace the XML namespace.
* @return the IQ provider. * @return the IQ provider.
*/ */
public static IqProvider<IQ> getIQProvider(String elementName, String namespace) { public static IQProvider<IQ> getIQProvider(String elementName, String namespace) {
QName key = getQName(elementName, namespace); QName key = getQName(elementName, namespace);
return iqProviders.get(key); return iqProviders.get(key);
} }
@ -179,8 +179,8 @@ public final class ProviderManager {
* *
* @return all IQProvider instances. * @return all IQProvider instances.
*/ */
public static List<IqProvider<IQ>> getIQProviders() { public static List<IQProvider<IQ>> getIQProviders() {
List<IqProvider<IQ>> providers = new ArrayList<>(iqProviders.size()); List<IQProvider<IQ>> providers = new ArrayList<>(iqProviders.size());
providers.addAll(iqProviders.values()); providers.addAll(iqProviders.values());
return providers; return providers;
} }
@ -200,10 +200,10 @@ public final class ProviderManager {
validate(elementName, namespace); validate(elementName, namespace);
// First remove existing providers // First remove existing providers
QName key = removeIQProvider(elementName, namespace); QName key = removeIQProvider(elementName, namespace);
if (provider instanceof IqProvider) { if (provider instanceof IQProvider) {
iqProviders.put(key, (IqProvider<IQ>) provider); iqProviders.put(key, (IQProvider<IQ>) provider);
} else { } else {
throw new IllegalArgumentException("Provider must be an instance of IqProvider"); throw new IllegalArgumentException("Provider must be an IQProvider");
} }
} }

View file

@ -18,6 +18,7 @@ package org.jivesoftware.smack.provider;
import org.jivesoftware.smack.packet.TlsProceed; import org.jivesoftware.smack.packet.TlsProceed;
import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
public final class TlsFailureProvider extends NonzaProvider<TlsProceed> { public final class TlsFailureProvider extends NonzaProvider<TlsProceed> {

View file

@ -18,6 +18,7 @@ package org.jivesoftware.smack.provider;
import org.jivesoftware.smack.packet.TlsFailure; import org.jivesoftware.smack.packet.TlsFailure;
import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
public final class TlsProceedProvider extends NonzaProvider<TlsFailure> { public final class TlsProceedProvider extends NonzaProvider<TlsFailure> {

View file

@ -222,7 +222,7 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
* empty array here. * empty array here.
* *
* @return the initial response or null * @return the initial response or null
* @throws SmackSaslException if a SASL specific error occurred. * @throws SmackSaslException if a SASL specific error occured.
*/ */
protected abstract byte[] getAuthenticationText() throws SmackSaslException; protected abstract byte[] getAuthenticationText() throws SmackSaslException;

View file

@ -259,7 +259,7 @@ public abstract class ScramMechanism extends SASLMechanism {
/** /**
* *
* @return the Channel Binding data. * @return the Channel Binding data.
* @throws SmackSaslException if a SASL specific error occurred. * @throws SmackSaslException if a SASL specific error occured.
*/ */
protected byte[] getChannelBindingData() throws SmackSaslException { protected byte[] getChannelBindingData() throws SmackSaslException {
return null; return null;

View file

@ -110,7 +110,7 @@ public final class FileUtils {
* *
* @param file TODO javadoc me please * @param file TODO javadoc me please
* @return the content of file or null in case of an error * @return the content of file or null in case of an error
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
*/ */
@SuppressWarnings("DefaultCharset") @SuppressWarnings("DefaultCharset")
public static String readFileOrThrow(File file) throws IOException { public static String readFileOrThrow(File file) throws IOException {

View file

@ -1,23 +0,0 @@
/**
*
* 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, T> {
R apply(T t);
}

View file

@ -34,7 +34,7 @@ import java.util.Set;
* @param <K> the type of the keys the map uses. * @param <K> the type of the keys the map uses.
* @param <V> the type of the values the map uses. * @param <V> the type of the values the map uses.
*/ */
public class MultiMap<K, V> implements TypedCloneable<MultiMap<K, V>> { public class MultiMap<K, V> {
/** /**
* The constant value {@value}. * The constant value {@value}.
@ -252,19 +252,6 @@ public class MultiMap<K, V> implements TypedCloneable<MultiMap<K, V>> {
return new MultiMap<K, V>(Collections.unmodifiableMap(mapCopy)); return new MultiMap<K, V>(Collections.unmodifiableMap(mapCopy));
} }
@Override
public MultiMap<K, V> clone() {
Map<K, List<V>> clonedMap = new LinkedHashMap<>(map.size());
// TODO: Use Map.forEach() once Smack's minimum Android API is 24 or higher.
for (Entry<K, List<V>> entry : map.entrySet()) {
List<V> clonedList = CollectionUtil.newListWith(entry.getValue());
clonedMap.put(entry.getKey(), clonedList);
}
return new MultiMap<>(clonedMap);
}
private static final class SimpleMapEntry<K, V> implements Map.Entry<K, V> { private static final class SimpleMapEntry<K, V> implements Map.Entry<K, V> {
private final K key; private final K key;

View file

@ -28,7 +28,6 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.jivesoftware.smack.compress.packet.Compress; import org.jivesoftware.smack.compress.packet.Compress;
@ -36,14 +35,10 @@ import org.jivesoftware.smack.packet.EmptyResultIQ;
import org.jivesoftware.smack.packet.ErrorIQ; import org.jivesoftware.smack.packet.ErrorIQ;
import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.IqData;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.MessageBuilder;
import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.PresenceBuilder;
import org.jivesoftware.smack.packet.Session; import org.jivesoftware.smack.packet.Session;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.StanzaBuilder;
import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smack.packet.StanzaError;
import org.jivesoftware.smack.packet.StartTls; import org.jivesoftware.smack.packet.StartTls;
import org.jivesoftware.smack.packet.StreamError; import org.jivesoftware.smack.packet.StreamError;
@ -52,7 +47,7 @@ import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException; import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.parsing.StandardExtensionElementProvider; import org.jivesoftware.smack.parsing.StandardExtensionElementProvider;
import org.jivesoftware.smack.provider.ExtensionElementProvider; 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.provider.ProviderManager;
import org.jivesoftware.smack.xml.SmackXmlParser; import org.jivesoftware.smack.xml.SmackXmlParser;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
@ -106,9 +101,9 @@ public class PacketParserUtils {
* @param parser TODO javadoc me please * @param parser TODO javadoc me please
* @param outerXmlEnvironment the outer XML environment (optional). * @param outerXmlEnvironment the outer XML environment (optional).
* @return a stanza which is either a Message, IQ or Presence. * @return a stanza which is either a Message, IQ or Presence.
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws SmackParsingException if the Smack parser (provider) encountered invalid input. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
*/ */
public static Stanza parseStanza(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, SmackParsingException, IOException { public static Stanza parseStanza(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, SmackParsingException, IOException {
ParserUtils.assertAtStartTag(parser); ParserUtils.assertAtStartTag(parser);
@ -125,25 +120,18 @@ public class PacketParserUtils {
} }
} }
private interface StanzaBuilderSupplier<SB extends StanzaBuilder<?>> { private static void parseCommonStanzaAttributes(Stanza stanza, XmlPullParser parser, XmlEnvironment xmlEnvironment) throws XmppStringprepException {
SB get(String stanzaId);
}
private static <SB extends StanzaBuilder<?>> SB parseCommonStanzaAttributes(StanzaBuilderSupplier<SB> stanzaBuilderSupplier, XmlPullParser parser, XmlEnvironment xmlEnvironment) throws XmppStringprepException {
String id = parser.getAttributeValue("id"); String id = parser.getAttributeValue("id");
stanza.setStanzaId(id);
SB stanzaBuilder = stanzaBuilderSupplier.get(id);
Jid to = ParserUtils.getJidAttribute(parser, "to"); Jid to = ParserUtils.getJidAttribute(parser, "to");
stanzaBuilder.to(to); stanza.setTo(to);
Jid from = ParserUtils.getJidAttribute(parser, "from"); Jid from = ParserUtils.getJidAttribute(parser, "from");
stanzaBuilder.from(from); stanza.setFrom(from);
String language = ParserUtils.getXmlLang(parser, xmlEnvironment); String language = ParserUtils.getXmlLang(parser, xmlEnvironment);
stanzaBuilder.setLanguage(language); stanza.setLanguage(language);
return stanzaBuilder;
} }
public static Message parseMessage(XmlPullParser parser) throws XmlPullParserException, IOException, SmackParsingException { public static Message parseMessage(XmlPullParser parser) throws XmlPullParserException, IOException, SmackParsingException {
@ -156,8 +144,8 @@ public class PacketParserUtils {
* @param parser the XML parser, positioned at the start of a message packet. * @param parser the XML parser, positioned at the start of a message packet.
* @param outerXmlEnvironment the outer XML environment (optional). * @param outerXmlEnvironment the outer XML environment (optional).
* @return a Message packet. * @return a Message packet.
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws SmackParsingException if the Smack parser (provider) encountered invalid input. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input.
*/ */
public static Message parseMessage(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { public static Message parseMessage(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
@ -166,14 +154,11 @@ public class PacketParserUtils {
XmlEnvironment messageXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment); XmlEnvironment messageXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
final int initialDepth = parser.getDepth(); final int initialDepth = parser.getDepth();
Message message = new Message();
MessageBuilder message = parseCommonStanzaAttributes(id -> { parseCommonStanzaAttributes(message, parser, outerXmlEnvironment);
return StanzaBuilder.buildMessage(id);
}, parser, outerXmlEnvironment);
String typeString = parser.getAttributeValue("", "type"); String typeString = parser.getAttributeValue("", "type");
if (typeString != null) { if (typeString != null) {
message.ofType(Message.Type.fromString(typeString)); message.setType(Message.Type.fromString(typeString));
} }
// Parse sub-elements. We include extra logic to make sure the values // Parse sub-elements. We include extra logic to make sure the values
@ -191,8 +176,9 @@ public class PacketParserUtils {
String xmlLangSubject = ParserUtils.getXmlLang(parser); String xmlLangSubject = ParserUtils.getXmlLang(parser);
String subject = parseElementText(parser); String subject = parseElementText(parser);
Message.Subject subjectExtensionElement = new Message.Subject(xmlLangSubject, subject); if (message.getSubject(xmlLangSubject) == null) {
message.addExtension(subjectExtensionElement); message.addSubject(xmlLangSubject, subject);
}
break; break;
case "thread": case "thread":
if (thread == null) { if (thread == null) {
@ -203,8 +189,7 @@ public class PacketParserUtils {
message.setError(parseError(parser, messageXmlEnvironment)); message.setError(parseError(parser, messageXmlEnvironment));
break; break;
default: default:
ExtensionElement extensionElement = parseExtensionElement(elementName, namespace, parser, messageXmlEnvironment); PacketParserUtils.addExtensionElement(message, parser, elementName, namespace, messageXmlEnvironment);
message.addExtension(extensionElement);
break; break;
} }
break; break;
@ -223,7 +208,7 @@ public class PacketParserUtils {
// situations where we have a body element with an explicit xml lang set and once where the value is inherited // 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. // and both values are equal.
return message.build(); return message;
} }
/** /**
@ -238,8 +223,8 @@ public class PacketParserUtils {
* *
* @param parser TODO javadoc me please * @param parser TODO javadoc me please
* @return the textual content of the element as String * @return the textual content of the element as String
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
*/ */
public static String parseElementText(XmlPullParser parser) throws XmlPullParserException, IOException { public static String parseElementText(XmlPullParser parser) throws XmlPullParserException, IOException {
assert parser.getEventType() == XmlPullParser.Event.START_ELEMENT; assert parser.getEventType() == XmlPullParser.Event.START_ELEMENT;
@ -277,8 +262,8 @@ public class PacketParserUtils {
* *
* @param parser the XML pull parser * @param parser the XML pull parser
* @return the element as string * @return the element as string
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
*/ */
public static CharSequence parseElement(XmlPullParser parser) throws XmlPullParserException, IOException { public static CharSequence parseElement(XmlPullParser parser) throws XmlPullParserException, IOException {
return parseElement(parser, false); return parseElement(parser, false);
@ -316,8 +301,8 @@ public class PacketParserUtils {
* @param depth TODO javadoc me please * @param depth TODO javadoc me please
* @param fullNamespaces TODO javadoc me please * @param fullNamespaces TODO javadoc me please
* @return the content of the current depth * @return the content of the current depth
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
*/ */
public static CharSequence parseContentDepth(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException { public static CharSequence parseContentDepth(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException {
if (parser.supportsRoundtrip()) { if (parser.supportsRoundtrip()) {
@ -442,8 +427,8 @@ public class PacketParserUtils {
* @param parser the XML parser, positioned at the start of a presence packet. * @param parser the XML parser, positioned at the start of a presence packet.
* @param outerXmlEnvironment the outer XML environment (optional). * @param outerXmlEnvironment the outer XML environment (optional).
* @return a Presence packet. * @return a Presence packet.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws SmackParsingException if the Smack parser (provider) encountered invalid input. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input.
*/ */
public static Presence parsePresence(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { public static Presence parsePresence(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
@ -451,16 +436,13 @@ public class PacketParserUtils {
final int initialDepth = parser.getDepth(); final int initialDepth = parser.getDepth();
XmlEnvironment presenceXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment); XmlEnvironment presenceXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
PresenceBuilder presence = parseCommonStanzaAttributes(
stanzaId -> StanzaBuilder.buildPresence(stanzaId), parser, outerXmlEnvironment);
Presence.Type type = Presence.Type.available; Presence.Type type = Presence.Type.available;
String typeString = parser.getAttributeValue("", "type"); String typeString = parser.getAttributeValue("", "type");
if (typeString != null && !typeString.equals("")) { if (typeString != null && !typeString.equals("")) {
type = Presence.Type.fromString(typeString); type = Presence.Type.fromString(typeString);
} }
Presence presence = new Presence(type);
presence.ofType(type); parseCommonStanzaAttributes(presence, parser, outerXmlEnvironment);
// Parse sub-elements // Parse sub-elements
outerloop: while (true) { outerloop: while (true) {
@ -486,7 +468,9 @@ public class PacketParserUtils {
// '<show />' element, which is a invalid XMPP presence // '<show />' element, which is a invalid XMPP presence
// stanza according to RFC 6121 4.7.2.1 // stanza according to RFC 6121 4.7.2.1
LOGGER.warning("Empty or null mode text in presence show element form " LOGGER.warning("Empty or null mode text in presence show element form "
+ presence + presence.getFrom()
+ " with id '"
+ presence.getStanzaId()
+ "' which is invalid according to RFC6121 4.7.2.1"); + "' which is invalid according to RFC6121 4.7.2.1");
} }
break; break;
@ -498,10 +482,10 @@ public class PacketParserUtils {
// Be extra robust: Skip PacketExtensions that cause Exceptions, instead of // Be extra robust: Skip PacketExtensions that cause Exceptions, instead of
// failing completely here. See SMACK-390 for more information. // failing completely here. See SMACK-390 for more information.
try { try {
ExtensionElement extensionElement = parseExtensionElement(elementName, namespace, parser, presenceXmlEnvironment); PacketParserUtils.addExtensionElement(presence, parser, elementName, namespace, presenceXmlEnvironment);
presence.addExtension(extensionElement);
} catch (Exception e) { } catch (Exception e) {
LOGGER.log(Level.WARNING, "Failed to parse extension element in Presence stanza: " + presence, e); LOGGER.warning("Failed to parse extension element in Presence stanza: \"" + e + "\" from: '"
+ presence.getFrom() + " id: '" + presence.getStanzaId() + "'");
} }
break; break;
} }
@ -516,8 +500,7 @@ public class PacketParserUtils {
break; break;
} }
} }
return presence;
return presence.build();
} }
public static IQ parseIQ(XmlPullParser parser) throws Exception { public static IQ parseIQ(XmlPullParser parser) throws Exception {
@ -530,9 +513,9 @@ public class PacketParserUtils {
* @param parser the XML parser, positioned at the start of an IQ packet. * @param parser the XML parser, positioned at the start of an IQ packet.
* @param outerXmlEnvironment the outer XML environment (optional). * @param outerXmlEnvironment the outer XML environment (optional).
* @return an IQ object. * @return an IQ object.
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws XmppStringprepException if the provided string is invalid. * @throws XmppStringprepException if the provided string is invalid.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws SmackParsingException if the Smack parser (provider) encountered invalid input. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input.
*/ */
public static IQ parseIQ(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, XmppStringprepException, IOException, SmackParsingException { public static IQ parseIQ(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, XmppStringprepException, IOException, SmackParsingException {
@ -540,19 +523,12 @@ public class PacketParserUtils {
final int initialDepth = parser.getDepth(); final int initialDepth = parser.getDepth();
XmlEnvironment iqXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment); XmlEnvironment iqXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
IQ iqPacket = null; IQ iqPacket = null;
StanzaError error = null; StanzaError.Builder error = null;
final String id = parser.getAttributeValue("", "id"); final String id = parser.getAttributeValue("", "id");
IqData iqData = StanzaBuilder.buildIqData(id);
final Jid to = ParserUtils.getJidAttribute(parser, "to"); final Jid to = ParserUtils.getJidAttribute(parser, "to");
iqData.to(to);
final Jid from = ParserUtils.getJidAttribute(parser, "from"); final Jid from = ParserUtils.getJidAttribute(parser, "from");
iqData.from(from);
final IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type")); final IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type"));
iqData.ofType(type);
outerloop: while (true) { outerloop: while (true) {
XmlPullParser.Event eventType = parser.next(); XmlPullParser.Event eventType = parser.next();
@ -568,9 +544,9 @@ public class PacketParserUtils {
// Otherwise, see if there is a registered provider for // Otherwise, see if there is a registered provider for
// this element name and namespace. // this element name and namespace.
default: default:
IqProvider<IQ> provider = ProviderManager.getIQProvider(elementName, namespace); IQProvider<IQ> provider = ProviderManager.getIQProvider(elementName, namespace);
if (provider != null) { if (provider != null) {
iqPacket = provider.parse(parser, iqData, outerXmlEnvironment); iqPacket = provider.parse(parser, outerXmlEnvironment);
} }
// Note that if we reach this code, it is guranteed that the result IQ contained a child element // 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. // (RFC 6120 § 8.2.3 6) because otherwhise we would have reached the END_ELEMENT first.
@ -622,8 +598,8 @@ public class PacketParserUtils {
* *
* @param parser the XML parser, positioned at the start of the mechanisms stanza. * @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. * @return a collection of Stings with the mechanisms included in the mechanisms stanza.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
*/ */
public static Collection<String> parseMechanisms(XmlPullParser parser) public static Collection<String> parseMechanisms(XmlPullParser parser)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
@ -652,7 +628,7 @@ public class PacketParserUtils {
* *
* @param parser the XML parser, positioned at the start of the compression stanza. * @param parser the XML parser, positioned at the start of the compression stanza.
* @return The CompressionFeature stream element * @return The CompressionFeature stream element
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws XmlPullParserException if an exception occurs while parsing the stanza. * @throws XmlPullParserException if an exception occurs while parsing the stanza.
*/ */
public static Compress.Feature parseCompressionFeature(XmlPullParser parser) public static Compress.Feature parseCompressionFeature(XmlPullParser parser)
@ -719,8 +695,8 @@ public class PacketParserUtils {
* @param parser the XML parser. * @param parser the XML parser.
* @param outerXmlEnvironment the outer XML environment (optional). * @param outerXmlEnvironment the outer XML environment (optional).
* @return an stream error packet. * @return an stream error packet.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws SmackParsingException if the Smack parser (provider) encountered invalid input. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input.
*/ */
public static StreamError parseStreamError(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { public static StreamError parseStreamError(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
@ -771,7 +747,7 @@ public class PacketParserUtils {
return new StreamError(condition, conditionText, descriptiveTexts, extensions); return new StreamError(condition, conditionText, descriptiveTexts, extensions);
} }
public static StanzaError parseError(XmlPullParser parser) throws XmlPullParserException, IOException, SmackParsingException { public static StanzaError.Builder parseError(XmlPullParser parser) throws XmlPullParserException, IOException, SmackParsingException {
return parseError(parser, null); return parseError(parser, null);
} }
@ -781,11 +757,11 @@ public class PacketParserUtils {
* @param parser the XML parser. * @param parser the XML parser.
* @param outerXmlEnvironment the outer XML environment (optional). * @param outerXmlEnvironment the outer XML environment (optional).
* @return an error sub-packet. * @return an error sub-packet.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws SmackParsingException if the Smack parser (provider) encountered invalid input. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input.
*/ */
public static StanzaError parseError(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { public static StanzaError.Builder parseError(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
final int initialDepth = parser.getDepth(); final int initialDepth = parser.getDepth();
Map<String, String> descriptiveTexts = null; Map<String, String> descriptiveTexts = null;
XmlEnvironment stanzaErrorXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment); XmlEnvironment stanzaErrorXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
@ -832,8 +808,7 @@ public class PacketParserUtils {
} }
} }
builder.setExtensions(extensions).setDescriptiveTexts(descriptiveTexts); builder.setExtensions(extensions).setDescriptiveTexts(descriptiveTexts);
return builder;
return builder.build();
} }
/** /**
@ -845,8 +820,8 @@ public class PacketParserUtils {
* @param outerXmlEnvironment the outer XML environment (optional). * @param outerXmlEnvironment the outer XML environment (optional).
* *
* @return an extension element. * @return an extension element.
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws SmackParsingException if the Smack parser (provider) encountered invalid input. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input.
*/ */
public static ExtensionElement parseExtensionElement(String elementName, String namespace, public static ExtensionElement parseExtensionElement(String elementName, String namespace,
@ -923,18 +898,6 @@ public class PacketParserUtils {
return new Session.Feature(optional); 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) public static void addExtensionElement(Stanza packet, XmlPullParser parser, XmlEnvironment outerXmlEnvironment)
throws XmlPullParserException, IOException, SmackParsingException { throws XmlPullParserException, IOException, SmackParsingException {
ParserUtils.assertAtStartTag(parser); ParserUtils.assertAtStartTag(parser);

View file

@ -1,24 +0,0 @@
/**
*
* 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<T> {
boolean test(T t);
}

View file

@ -427,13 +427,6 @@ public class StringUtils {
return true; 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. * Returns true if the given CharSequence is empty.
* *
@ -463,11 +456,6 @@ public class StringUtils {
*/ */
public static StringBuilder toStringBuilder(Collection<? extends Object> collection, String delimiter) { public static StringBuilder toStringBuilder(Collection<? extends Object> collection, String delimiter) {
StringBuilder sb = new StringBuilder(collection.size() * 20); StringBuilder sb = new StringBuilder(collection.size() * 20);
appendTo(collection, delimiter, sb);
return sb;
}
public static void appendTo(Collection<? extends Object> collection, String delimiter, StringBuilder sb) {
for (Iterator<? extends Object> it = collection.iterator(); it.hasNext();) { for (Iterator<? extends Object> it = collection.iterator(); it.hasNext();) {
Object cs = it.next(); Object cs = it.next();
sb.append(cs); sb.append(cs);
@ -475,6 +463,7 @@ public class StringUtils {
sb.append(delimiter); sb.append(delimiter);
} }
} }
return sb;
} }
public static String returnIfNotEmptyTrimmed(String string) { public static String returnIfNotEmptyTrimmed(String string) {
@ -535,7 +524,7 @@ public class StringUtils {
if (cs == null) { if (cs == null) {
return null; return null;
} }
if (isEmpty(cs)) { if (cs.toString().isEmpty()) {
throw new IllegalArgumentException(message); throw new IllegalArgumentException(message);
} }
return cs; return cs;

View file

@ -1,75 +0,0 @@
/**
*
* 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 <V> Builder add(String name, Collection<? extends V> values, Function<?, V> toStringFunction) {
if (values.isEmpty()) {
return this;
}
sb.append(' ').append(name).append('[');
List<String> 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();
}
}
}

View file

@ -628,7 +628,7 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
* *
* @param writer TODO javadoc me please * @param writer TODO javadoc me please
* @param enclosingXmlEnvironment the enclosing XML environment. * @param enclosingXmlEnvironment the enclosing XML environment.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
*/ */
public void write(Writer writer, XmlEnvironment enclosingXmlEnvironment) throws IOException { public void write(Writer writer, XmlEnvironment enclosingXmlEnvironment) throws IOException {
try { try {

View file

@ -16,9 +16,6 @@
*/ */
package org.jivesoftware.smack.util; package org.jivesoftware.smack.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
@ -55,21 +52,4 @@ public class XmppElementUtil {
return new QName(namespace, element); return new QName(namespace, element);
} }
public static <E extends FullyQualifiedElement, R extends FullyQualifiedElement> List<R> getElementsFrom(
MultiMap<QName, E> elementMap, Class<R> extensionElementClass) {
QName qname = XmppElementUtil.getQNameFor(extensionElementClass);
List<E> extensionElements = elementMap.getAll(qname);
if (extensionElements.isEmpty()) {
return Collections.emptyList();
}
List<R> res = new ArrayList<>(extensionElements.size());
for (E extensionElement : extensionElements) {
R e = extensionElementClass.cast(extensionElement);
res.add(e);
}
return res;
}
} }

View file

@ -19,8 +19,8 @@ package org.jivesoftware.smack.filter;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.StanzaBuilder;
import org.junit.Test; import org.junit.Test;
import org.jxmpp.jid.EntityFullJid; import org.jxmpp.jid.EntityFullJid;
@ -47,7 +47,7 @@ public class FromMatchesFilterTest {
@Test @Test
public void autoCompareMatchingEntityFullJid() { public void autoCompareMatchingEntityFullJid() {
FromMatchesFilter filter = FromMatchesFilter.create(FULL_JID1_R1); FromMatchesFilter filter = FromMatchesFilter.create(FULL_JID1_R1);
Stanza packet = StanzaBuilder.buildMessage().build(); Stanza packet = new Message();
packet.setFrom(FULL_JID1_R1); packet.setFrom(FULL_JID1_R1);
assertTrue(filter.accept(packet)); assertTrue(filter.accept(packet));
@ -71,7 +71,7 @@ public class FromMatchesFilterTest {
@Test @Test
public void autoCompareMatchingBaseJid() { public void autoCompareMatchingBaseJid() {
FromMatchesFilter filter = FromMatchesFilter.create(BASE_JID1); FromMatchesFilter filter = FromMatchesFilter.create(BASE_JID1);
Stanza packet = StanzaBuilder.buildMessage().build(); Stanza packet = new Message();
packet.setFrom(BASE_JID1); packet.setFrom(BASE_JID1);
assertTrue(filter.accept(packet)); assertTrue(filter.accept(packet));
@ -95,7 +95,7 @@ public class FromMatchesFilterTest {
@Test @Test
public void autoCompareMatchingServiceJid() { public void autoCompareMatchingServiceJid() {
FromMatchesFilter filter = FromMatchesFilter.create(SERVICE_JID1); FromMatchesFilter filter = FromMatchesFilter.create(SERVICE_JID1);
Stanza packet = StanzaBuilder.buildMessage().build(); Stanza packet = new Message();
packet.setFrom(SERVICE_JID1); packet.setFrom(SERVICE_JID1);
assertTrue(filter.accept(packet)); assertTrue(filter.accept(packet));
@ -116,7 +116,7 @@ public class FromMatchesFilterTest {
@Test @Test
public void bareCompareMatchingEntityFullJid() { public void bareCompareMatchingEntityFullJid() {
FromMatchesFilter filter = FromMatchesFilter.createBare(FULL_JID1_R1); FromMatchesFilter filter = FromMatchesFilter.createBare(FULL_JID1_R1);
Stanza packet = StanzaBuilder.buildMessage().build(); Stanza packet = new Message();
packet.setFrom(BASE_JID1); packet.setFrom(BASE_JID1);
assertTrue(filter.accept(packet)); assertTrue(filter.accept(packet));
@ -140,7 +140,7 @@ public class FromMatchesFilterTest {
@Test @Test
public void bareCompareMatchingBaseJid() { public void bareCompareMatchingBaseJid() {
FromMatchesFilter filter = FromMatchesFilter.createBare(BASE_JID1); FromMatchesFilter filter = FromMatchesFilter.createBare(BASE_JID1);
Stanza packet = StanzaBuilder.buildMessage().build(); Stanza packet = new Message();
packet.setFrom(BASE_JID1); packet.setFrom(BASE_JID1);
assertTrue(filter.accept(packet)); assertTrue(filter.accept(packet));
@ -164,7 +164,7 @@ public class FromMatchesFilterTest {
@Test @Test
public void bareCompareMatchingServiceJid() { public void bareCompareMatchingServiceJid() {
FromMatchesFilter filter = FromMatchesFilter.createBare(SERVICE_JID1); FromMatchesFilter filter = FromMatchesFilter.createBare(SERVICE_JID1);
Stanza packet = StanzaBuilder.buildMessage().build(); Stanza packet = new Message();
packet.setFrom(SERVICE_JID1); packet.setFrom(SERVICE_JID1);
assertTrue(filter.accept(packet)); assertTrue(filter.accept(packet));
@ -185,7 +185,7 @@ public class FromMatchesFilterTest {
@Test @Test
public void fullCompareMatchingEntityFullJid() { public void fullCompareMatchingEntityFullJid() {
FromMatchesFilter filter = FromMatchesFilter.createFull(FULL_JID1_R1); FromMatchesFilter filter = FromMatchesFilter.createFull(FULL_JID1_R1);
Stanza packet = StanzaBuilder.buildMessage().build(); Stanza packet = new Message();
packet.setFrom(FULL_JID1_R1); packet.setFrom(FULL_JID1_R1);
assertTrue(filter.accept(packet)); assertTrue(filter.accept(packet));
@ -209,7 +209,7 @@ public class FromMatchesFilterTest {
@Test @Test
public void fullCompareMatchingBaseJid() { public void fullCompareMatchingBaseJid() {
FromMatchesFilter filter = FromMatchesFilter.createFull(BASE_JID1); FromMatchesFilter filter = FromMatchesFilter.createFull(BASE_JID1);
Stanza packet = StanzaBuilder.buildMessage().build(); Stanza packet = new Message();
packet.setFrom(BASE_JID1); packet.setFrom(BASE_JID1);
assertTrue(filter.accept(packet)); assertTrue(filter.accept(packet));
@ -233,7 +233,7 @@ public class FromMatchesFilterTest {
@Test @Test
public void fullCompareMatchingServiceJid() { public void fullCompareMatchingServiceJid() {
FromMatchesFilter filter = FromMatchesFilter.createFull(SERVICE_JID1); FromMatchesFilter filter = FromMatchesFilter.createFull(SERVICE_JID1);
Stanza packet = StanzaBuilder.buildMessage().build(); Stanza packet = new Message();
packet.setFrom(SERVICE_JID1); packet.setFrom(SERVICE_JID1);
assertTrue(filter.accept(packet)); assertTrue(filter.accept(packet));

View file

@ -62,7 +62,7 @@ public class IQResponseTest {
*/ */
@Test @Test
public void testGeneratingValidErrorResponse() throws XmppStringprepException { public void testGeneratingValidErrorResponse() throws XmppStringprepException {
final StanzaError error = StanzaError.getBuilder(StanzaError.Condition.bad_request).build(); final StanzaError.Builder error = StanzaError.getBuilder(StanzaError.Condition.bad_request);
final IQ request = new TestIQ(ELEMENT, NAMESPACE); final IQ request = new TestIQ(ELEMENT, NAMESPACE);
request.setType(IQ.Type.set); request.setType(IQ.Type.set);
@ -75,7 +75,7 @@ public class IQResponseTest {
assertNotNull(result.getStanzaId()); assertNotNull(result.getStanzaId());
assertEquals(request.getStanzaId(), result.getStanzaId()); assertEquals(request.getStanzaId(), result.getStanzaId());
assertEquals(request.getFrom(), result.getTo()); assertEquals(request.getFrom(), result.getTo());
assertEquals(error.toXML().toString(), result.getError().toXML().toString()); assertEquals(error.build().toXML().toString(), result.getError().toXML().toString());
// TODO this test was never valid // TODO this test was never valid
// assertEquals(CHILD_ELEMENT, result.getChildElementXML()); // assertEquals(CHILD_ELEMENT, result.getChildElementXML());
} }
@ -110,7 +110,7 @@ public class IQResponseTest {
*/ */
@Test @Test
public void testGeneratingErrorBasedOnError() throws XmppStringprepException { public void testGeneratingErrorBasedOnError() throws XmppStringprepException {
final StanzaError error = StanzaError.getBuilder(StanzaError.Condition.bad_request).build(); final StanzaError.Builder error = StanzaError.getBuilder(StanzaError.Condition.bad_request);
final IQ request = new TestIQ(ELEMENT, NAMESPACE); final IQ request = new TestIQ(ELEMENT, NAMESPACE);
request.setType(IQ.Type.error); request.setType(IQ.Type.error);

View file

@ -18,6 +18,7 @@ package org.jivesoftware.smack.packet;
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar; import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
@ -43,12 +44,10 @@ public class MessageTest {
.append("</message>"); .append("</message>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
Message messageBuildWithBuilder = StanzaBuilder.buildMessage() Message messageTypeInConstructor = new Message(null, Message.Type.chat);
.ofType(Message.Type.chat) messageTypeInConstructor.setStanzaId(null);
.build(); assertEquals(type, messageTypeInConstructor.getType());
assertXmlSimilar(control, messageTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertEquals(type, messageBuildWithBuilder.getType());
assertXmlSimilar(control, messageBuildWithBuilder.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
controlBuilder = new StringBuilder(); controlBuilder = new StringBuilder();
controlBuilder.append("<message") controlBuilder.append("<message")
@ -58,18 +57,16 @@ public class MessageTest {
.append("</message>"); .append("</message>");
control = controlBuilder.toString(); control = controlBuilder.toString();
Message messageTypeSet = StanzaBuilder.buildMessage() Message messageTypeSet = getNewMessage();
.ofType(type2) messageTypeSet.setType(type2);
.build();
assertEquals(type2, messageTypeSet.getType()); assertEquals(type2, messageTypeSet.getType());
assertXmlSimilar(control, messageTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, messageTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }
@Test(expected = NullPointerException.class) @Test(expected = NullPointerException.class)
public void setNullMessageBodyTest() { public void setNullMessageBodyTest() {
StanzaBuilder.buildMessage() Message message = getNewMessage();
.addBody(null, null) message.addBody(null, null);
.build();
} }
@Test @Test
@ -84,9 +81,9 @@ public class MessageTest {
.append("</message>"); .append("</message>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
Message message = StanzaBuilder.buildMessage() Message message = getNewMessage();
.setSubject(messageSubject) message.setSubject(messageSubject);
.build();
assertEquals(messageSubject, message.getSubject()); assertEquals(messageSubject, message.getSubject());
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }
@ -103,9 +100,9 @@ public class MessageTest {
.append("</message>"); .append("</message>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
Message message = StanzaBuilder.buildMessage() Message message = getNewMessage();
.setBody(messageBody) message.setBody(messageBody);
.build();
assertEquals(messageBody, message.getBody()); assertEquals(messageBody, message.getBody());
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }
@ -136,11 +133,10 @@ public class MessageTest {
.append("</message>"); .append("</message>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
Message message = StanzaBuilder.buildMessage() Message message = getNewMessage();
.addBody(null, messageBody1) message.addBody(null, messageBody1);
.addBody(lang2, messageBody2) message.addBody(lang2, messageBody2);
.addBody(lang3, messageBody3) message.addBody(lang3, messageBody3);
.build();
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE)); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE));
Collection<String> languages = message.getBodyLanguages(); Collection<String> languages = message.getBodyLanguages();
@ -152,20 +148,21 @@ public class MessageTest {
} }
@Test @Test
public void simpleMessageBodyTest() { public void removeMessageBodyTest() {
Message message = StanzaBuilder.buildMessage() Message message = getNewMessage();
.setBody("test") message.setBody("test");
.build();
assertTrue(message.getBodies().size() == 1); assertTrue(message.getBodies().size() == 1);
message = StanzaBuilder.buildMessage().build(); message.setBody(null);
assertTrue(message.getBodies().size() == 0); assertTrue(message.getBodies().size() == 0);
assertFalse(message.removeBody("sp"));
message = StanzaBuilder.buildMessage() Message.Body body = message.addBody("es", "test");
.addBody("es", "test")
.build();
assertTrue(message.getBodies().size() == 1); assertTrue(message.getBodies().size() == 1);
message.removeBody(body);
assertTrue(message.getBodies().size() == 0);
} }
@Test @Test
@ -180,9 +177,8 @@ public class MessageTest {
.append("</message>"); .append("</message>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
Message message = StanzaBuilder.buildMessage() Message message = getNewMessage();
.setThread(messageThread) message.setThread(messageThread);
.build();
assertEquals(messageThread, message.getThread()); assertEquals(messageThread, message.getThread());
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
@ -200,10 +196,15 @@ public class MessageTest {
.append("</message>"); .append("</message>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
Message message = StanzaBuilder.buildMessage() Message message = getNewMessage();
.setLanguage(lang) message.setLanguage(lang);
.build();
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }
private static Message getNewMessage() {
Message message = new Message();
message.setStanzaId(null);
return message;
}
} }

View file

@ -41,9 +41,8 @@ public class PresenceTest {
.append("</presence>"); .append("</presence>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
Presence presenceTypeInConstructor = StanzaBuilder.buildPresence() Presence presenceTypeInConstructor = new Presence(type);
.ofType(type) presenceTypeInConstructor.setStanzaId(null);
.build();
assertEquals(type, presenceTypeInConstructor.getType()); assertEquals(type, presenceTypeInConstructor.getType());
assertXmlSimilar(control, presenceTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, presenceTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
@ -55,27 +54,27 @@ public class PresenceTest {
.append("</presence>"); .append("</presence>");
control = controlBuilder.toString(); control = controlBuilder.toString();
PresenceBuilder presenceTypeSet = getNewPresence(); Presence presenceTypeSet = getNewPresence();
presenceTypeSet.ofType(type2); presenceTypeSet.setType(type2);
assertEquals(type2, presenceTypeSet.getType()); assertEquals(type2, presenceTypeSet.getType());
assertXmlSimilar(control, presenceTypeSet.build().toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, presenceTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }
@Test @Test
public void setNullPresenceTypeTest() { public void setNullPresenceTypeTest() {
assertThrows(IllegalArgumentException.class, () -> assertThrows(IllegalArgumentException.class, () ->
getNewPresence().ofType(null) getNewPresence().setType(null)
); );
} }
@Test @Test
public void isPresenceAvailableTest() { public void isPresenceAvailableTest() {
PresenceBuilder presence = getNewPresence(); Presence presence = getNewPresence();
presence.ofType(Presence.Type.available); presence.setType(Presence.Type.available);
assertTrue(presence.build().isAvailable()); assertTrue(presence.isAvailable());
presence.ofType(Presence.Type.unavailable); presence.setType(Presence.Type.unavailable);
assertFalse(presence.build().isAvailable()); assertFalse(presence.isAvailable());
} }
@Test @Test
@ -90,11 +89,11 @@ public class PresenceTest {
.append("</presence>"); .append("</presence>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
PresenceBuilder presence = getNewPresence(); Presence presence = getNewPresence();
presence.setStatus(status); presence.setStatus(status);
assertEquals(status, presence.getStatus()); assertEquals(status, presence.getStatus());
assertXmlSimilar(control, presence.build().toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }
@Test @Test
@ -109,11 +108,11 @@ public class PresenceTest {
.append("</presence>"); .append("</presence>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
PresenceBuilder presence = getNewPresence(); Presence presence = getNewPresence();
presence.setPriority(priority); presence.setPriority(priority);
assertEquals(priority, presence.getPriority()); assertEquals(priority, presence.getPriority());
assertXmlSimilar(control, presence.build().toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }
@Test @Test
@ -144,14 +143,11 @@ public class PresenceTest {
.append("</presence>"); .append("</presence>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
Presence presenceBuildWithBuilder = StanzaBuilder.buildPresence() Presence presenceModeInConstructor = new Presence(Presence.Type.available, status, priority,
.ofType(Presence.Type.available) mode1);
.setStatus(status) presenceModeInConstructor.setStanzaId(null);
.setPriority(priority) assertEquals(mode1, presenceModeInConstructor.getMode());
.setMode(mode1) assertXmlSimilar(control, presenceModeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
.build();
assertEquals(mode1, presenceBuildWithBuilder.getMode());
assertXmlSimilar(control, presenceBuildWithBuilder.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
controlBuilder = new StringBuilder(); controlBuilder = new StringBuilder();
controlBuilder.append("<presence>") controlBuilder.append("<presence>")
@ -161,20 +157,20 @@ public class PresenceTest {
.append("</presence>"); .append("</presence>");
control = controlBuilder.toString(); control = controlBuilder.toString();
PresenceBuilder presenceModeSet = getNewPresence(); Presence presenceModeSet = getNewPresence();
presenceModeSet.setMode(mode2); presenceModeSet.setMode(mode2);
assertEquals(mode2, presenceModeSet.getMode()); assertEquals(mode2, presenceModeSet.getMode());
assertXmlSimilar(control, presenceModeSet.build().toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, presenceModeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }
@Test @Test
public void isModeAwayTest() { public void isModeAwayTest() {
PresenceBuilder presence = getNewPresence(); Presence presence = getNewPresence();
presence.setMode(Presence.Mode.away); presence.setMode(Presence.Mode.away);
assertTrue(presence.build().isAway()); assertTrue(presence.isAway());
presence.setMode(Presence.Mode.chat); presence.setMode(Presence.Mode.chat);
assertFalse(presence.build().isAway()); assertFalse(presence.isAway());
} }
@Test @Test
@ -189,14 +185,15 @@ public class PresenceTest {
.append("</presence>"); .append("</presence>");
String control = controlBuilder.toString(); String control = controlBuilder.toString();
PresenceBuilder presence = getNewPresence(); Presence presence = getNewPresence();
presence.setLanguage(lang); presence.setLanguage(lang);
assertXmlSimilar(control, presence.build().toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }
private static PresenceBuilder getNewPresence() { private static Presence getNewPresence() {
PresenceBuilder presence = StanzaBuilder.buildPresence().ofType(Presence.Type.available); Presence presence = new Presence(Presence.Type.available);
presence.setStanzaId(null);
return presence; return presence;
} }
} }

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2016-2019 Florian Schmaus * Copyright © 2016-2017 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,8 @@ package org.jivesoftware.smack.packet;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import org.jivesoftware.smack.packet.Presence.Mode;
import org.junit.Test; import org.junit.Test;
import org.jxmpp.jid.JidTestUtil; import org.jxmpp.jid.JidTestUtil;
@ -25,21 +27,15 @@ public class ToStringTest {
@Test @Test
public void messageTest() { public void messageTest() {
Message message = StanzaBuilder.buildMessage("message-id") Message message = new Message(JidTestUtil.BARE_JID_1, Message.Type.headline);
.ofType(Message.Type.headline) message.setStanzaId("message-id");
.to(JidTestUtil.BARE_JID_1)
.build();
String string = message.toString(); String string = message.toString();
assertEquals("Message Stanza [to=one@exampleone.org,id=message-id,type=headline,]", string); assertEquals("Message Stanza [to=one@exampleone.org,id=message-id,type=headline,]", string);
} }
@Test @Test
public void presenceTest() { public void presenceTest() {
Presence presence = StanzaBuilder.buildPresence() Presence presence = new Presence(Presence.Type.subscribe, null, 0, Mode.away);
.ofType(Presence.Type.subscribe)
.setPriority(0)
.setMode(Presence.Mode.away)
.build();
presence.setStanzaId("presence-id"); presence.setStanzaId("presence-id");
String string = presence.toString(); String string = presence.toString();
assertEquals("Presence Stanza [id=presence-id,type=subscribe,mode=away,prio=0,]", string); assertEquals("Presence Stanza [id=presence-id,type=subscribe,mode=away,prio=0,]", string);

View file

@ -16,13 +16,12 @@
*/ */
package org.jivesoftware.smack.packet; 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 static org.junit.Assert.assertEquals;
import java.util.Map; import java.util.Map;
import org.jivesoftware.smack.packet.StanzaError.Condition;
import org.jivesoftware.smack.packet.StanzaError.Type;
import org.junit.Test; import org.junit.Test;
public class XMPPErrorTest { public class XMPPErrorTest {

View file

@ -45,6 +45,7 @@ import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smack.xml.XmlPullParserException;
import com.jamesmurty.utils.XMLBuilder; import com.jamesmurty.utils.XMLBuilder;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
@ -546,6 +547,30 @@ public class PacketParserUtilsTest {
assertTrue(message.getSubjectLanguages().contains(otherLanguage)); assertTrue(message.getSubjectLanguages().contains(otherLanguage));
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); 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 // message has non-default language, first subject no language, second subject default language
control = XMLBuilder.create("message") control = XMLBuilder.create("message")
.a("from", "romeo@montague.lit/orchard") .a("from", "romeo@montague.lit/orchard")
@ -842,7 +867,7 @@ public class PacketParserUtilsTest {
.element("text", StanzaError.ERROR_CONDITION_AND_TEXT_NAMESPACE).t(text).up() .element("text", StanzaError.ERROR_CONDITION_AND_TEXT_NAMESPACE).t(text).up()
.asString(); .asString();
XmlPullParser parser = TestUtils.getParser(errorXml); XmlPullParser parser = TestUtils.getParser(errorXml);
StanzaError error = PacketParserUtils.parseError(parser); StanzaError error = PacketParserUtils.parseError(parser).build();
assertEquals(text, error.getDescriptiveText()); assertEquals(text, error.getDescriptiveText());
} }
} }

View file

@ -120,10 +120,18 @@ public final class ChatMarkersManager extends Manager {
chatManager = ChatManager.getInstanceFor(connection); chatManager = ChatManager.getInstanceFor(connection);
connection.addMessageInterceptor(mb -> mb.addExtension(ChatMarkersElements.MarkableExtension.INSTANCE), connection.addStanzaInterceptor(new StanzaListener() {
m -> { @Override
return OUTGOING_MESSAGE_FILTER.accept(m); 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.addSyncStanzaListener(new StanzaListener() { connection.addSyncStanzaListener(new StanzaListener() {
@Override @Override

View file

@ -88,11 +88,10 @@ public final class DnsOverXmppManager extends Manager {
try { try {
response = resolver.resolve(query); response = resolver.resolve(query);
} catch (IOException exception) { } catch (IOException exception) {
StanzaError errorBuilder = StanzaError.getBuilder() StanzaError.Builder errorBuilder = StanzaError.getBuilder()
.setType(Type.CANCEL) .setType(Type.CANCEL)
.setCondition(Condition.internal_server_error) .setCondition(Condition.internal_server_error)
.setDescriptiveEnText("Exception while resolving your DNS query", exception) .setDescriptiveEnText("Exception while resolving your DNS query", exception)
.build()
; ;
IQ errorResponse = IQ.createErrorResponse(iqRequest, errorBuilder); IQ errorResponse = IQ.createErrorResponse(iqRequest, errorBuilder);

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2017-2019 Florian Schmaus * Copyright 2017 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,12 +20,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message; 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.StringUtils;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
@ -37,8 +33,6 @@ public class ExplicitMessageEncryptionElement implements ExtensionElement {
public static final String NAMESPACE = "urn:xmpp:eme:0"; public static final String NAMESPACE = "urn:xmpp:eme:0";
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
public enum ExplicitMessageEncryptionProtocol { public enum ExplicitMessageEncryptionProtocol {
/** /**
@ -160,12 +154,14 @@ public class ExplicitMessageEncryptionElement implements ExtensionElement {
* @param protocolNamespace namespace * @param protocolNamespace namespace
* @return true if message has EME element for that namespace, otherwise false * @return true if message has EME element for that namespace, otherwise false
*/ */
public static boolean hasProtocol(MessageView message, String protocolNamespace) { public static boolean hasProtocol(Message message, String protocolNamespace) {
List<ExplicitMessageEncryptionElement> emeElements = message List<ExtensionElement> extensionElements = message.getExtensions(
.getExtensions(ExplicitMessageEncryptionElement.class); ExplicitMessageEncryptionElement.ELEMENT,
ExplicitMessageEncryptionElement.NAMESPACE);
for (ExplicitMessageEncryptionElement emeElement : emeElements) { for (ExtensionElement extensionElement : extensionElements) {
if (emeElement.getEncryptionNamespace().equals(protocolNamespace)) { ExplicitMessageEncryptionElement e = (ExplicitMessageEncryptionElement) extensionElement;
if (e.getEncryptionNamespace().equals(protocolNamespace)) {
return true; return true;
} }
} }
@ -180,7 +176,7 @@ public class ExplicitMessageEncryptionElement implements ExtensionElement {
* @param protocol protocol * @param protocol protocol
* @return true if message has EME element for that namespace, otherwise false * @return true if message has EME element for that namespace, otherwise false
*/ */
public static boolean hasProtocol(MessageView message, ExplicitMessageEncryptionProtocol protocol) { public static boolean hasProtocol(Message message, ExplicitMessageEncryptionProtocol protocol) {
return hasProtocol(message, protocol.namespace); return hasProtocol(message, protocol.namespace);
} }
@ -188,10 +184,10 @@ public class ExplicitMessageEncryptionElement implements ExtensionElement {
* Add an EME element containing the specified {@code protocol} namespace to the message. * 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. * In case there is already an element with that protocol, we do nothing.
* *
* @param message a message builder. * @param message message
* @param protocol encryption protocol * @param protocol encryption protocol
*/ */
public static void set(MessageBuilder message, ExplicitMessageEncryptionProtocol protocol) { public static void set(Message message, ExplicitMessageEncryptionProtocol protocol) {
if (!hasProtocol(message, protocol.namespace)) { if (!hasProtocol(message, protocol.namespace)) {
message.addExtension(new ExplicitMessageEncryptionElement(protocol)); message.addExtension(new ExplicitMessageEncryptionElement(protocol));
} }

View file

@ -43,7 +43,6 @@ import java.util.WeakHashMap;
import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.util.SecurityUtil; import org.jivesoftware.smack.util.SecurityUtil;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.hashes.element.HashElement; import org.jivesoftware.smackx.hashes.element.HashElement;

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2017-2019 Florian Schmaus * Copyright 2017 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,10 +16,7 @@
*/ */
package org.jivesoftware.smackx.hints.element; package org.jivesoftware.smackx.hints.element;
import javax.xml.namespace.QName; import org.jivesoftware.smack.packet.Message;
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. * A "store" hint. Messages with this hint should be stored in permanent stores or archives.
@ -32,8 +29,6 @@ public final class StoreHint extends MessageProcessingHint {
public static final String ELEMENT = "store"; public static final String ELEMENT = "store";
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
private StoreHint() { private StoreHint() {
} }
@ -52,15 +47,15 @@ public final class StoreHint extends MessageProcessingHint {
return MessageProcessingHintType.store; return MessageProcessingHintType.store;
} }
public static StoreHint from(MessageView message) { public static StoreHint from(Message message) {
return message.getExtension(QNAME); return message.getExtension(ELEMENT, NAMESPACE);
} }
public static boolean hasHint(MessageView message) { public static boolean hasHint(Message message) {
return from(message) != null; return from(message) != null;
} }
public static void set(MessageBuilder message) { public static void set(Message message) {
message.overrideExtension(INSTANCE); message.overrideExtension(INSTANCE);
} }
} }

View file

@ -55,8 +55,8 @@ public abstract class AbstractHttpOverXmppProvider<H extends AbstractHttpOverXmp
* *
* @param parser parser * @param parser parser
* @return HeadersExtension or null if no headers * @return HeadersExtension or null if no headers
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
* @throws SmackParsingException if the Smack parser (provider) encountered invalid input. * @throws SmackParsingException if the Smack parser (provider) encountered invalid input.
*/ */
protected HeadersExtension parseHeaders(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException { protected HeadersExtension parseHeaders(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException {
@ -76,8 +76,8 @@ public abstract class AbstractHttpOverXmppProvider<H extends AbstractHttpOverXmp
* @param parser parser * @param parser parser
* @return Data or null if no data * @return Data or null if no data
* *
* @throws XmlPullParserException if an error in the XML parser occurred. * @throws XmlPullParserException if an error in the XML parser occured.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
*/ */
protected AbstractHttpOverXmpp.Data parseData(XmlPullParser parser) throws XmlPullParserException, IOException { protected AbstractHttpOverXmpp.Data parseData(XmlPullParser parser) throws XmlPullParserException, IOException {
NamedElement child = null; NamedElement child = null;

View file

@ -251,7 +251,7 @@ public final class HttpFileUploadManager extends Manager {
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
* @throws XMPPException.XMPPErrorException if there was an XMPP error returned. * @throws XMPPException.XMPPErrorException if there was an XMPP error returned.
* @throws SmackException if Smack detected an exceptional situation. * @throws SmackException if Smack detected an exceptional situation.
* @throws IOException if an I/O error occurred. * @throws IOException if an I/O error occured.
*/ */
public URL uploadFile(File file, UploadProgressListener listener) throws InterruptedException, public URL uploadFile(File file, UploadProgressListener listener) throws InterruptedException,
XMPPException.XMPPErrorException, SmackException, IOException { XMPPException.XMPPErrorException, SmackException, IOException {

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2016-2019 Florian Schmaus * Copyright © 2016 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,26 +16,20 @@
*/ */
package org.jivesoftware.smackx.iot.control.element; package org.jivesoftware.smackx.iot.control.element;
import org.jivesoftware.smack.packet.AbstractIqBuilder;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.IqData;
public class IoTSetResponse extends IQ { public class IoTSetResponse extends IQ {
public static final String ELEMENT = "setResponse"; public static final String ELEMENT = "setResponse";
public static final String NAMESPACE = Constants.IOT_CONTROL_NAMESPACE; public static final String NAMESPACE = Constants.IOT_CONTROL_NAMESPACE;
public IoTSetResponse(IqData iqBuilder) {
super(iqBuilder, ELEMENT, NAMESPACE);
}
// TODO: Deprecate when stanza build is ready.
public IoTSetResponse() { public IoTSetResponse() {
super(ELEMENT, NAMESPACE); super(ELEMENT, NAMESPACE);
} }
public IoTSetResponse(IoTSetRequest iotSetRequest) { public IoTSetResponse(IoTSetRequest iotSetRequest) {
this(AbstractIqBuilder.createResponse(iotSetRequest)); this();
initializeAsResultFor(iotSetRequest);
} }
@Override @Override

View file

@ -125,14 +125,10 @@ public final class IoTDataManager extends IoTManager {
@Override @Override
public void momentaryReadOut(List<? extends IoTDataField> results) { public void momentaryReadOut(List<? extends IoTDataField> results) {
IoTFieldsExtension iotFieldsExtension = IoTFieldsExtension.buildFor(dataRequest.getSequenceNr(), true, thing.getNodeInfo(), results); IoTFieldsExtension iotFieldsExtension = IoTFieldsExtension.buildFor(dataRequest.getSequenceNr(), true, thing.getNodeInfo(), results);
Message message = new Message(dataRequest.getFrom());
XMPPConnection connection = connection(); message.addExtension(iotFieldsExtension);
Message message = connection.getStanzaFactory().buildMessageStanza()
.to(dataRequest.getFrom())
.addExtension(iotFieldsExtension)
.build();
try { try {
connection.sendStanza(message); connection().sendStanza(message);
} }
catch (NotConnectedException | InterruptedException e) { catch (NotConnectedException | InterruptedException e) {
LOGGER.log(Level.SEVERE, "Could not send read-out response " + message, e); LOGGER.log(Level.SEVERE, "Could not send read-out response " + message, e);

View file

@ -20,7 +20,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.iot.element.NodeInfo; import org.jivesoftware.smackx.iot.element.NodeInfo;
public class NodeElement extends IoTDataExtensionElement { public class NodeElement extends IoTDataExtensionElement {

View file

@ -140,10 +140,8 @@ public final class IoTProvisioningManager extends Manager {
+ " is already not subscribed to our presence."); + " is already not subscribed to our presence.");
return; return;
} }
Presence unsubscribed = connection.getStanzaFactory().buildPresenceStanza() Presence unsubscribed = new Presence(Presence.Type.unsubscribed);
.ofType(Presence.Type.unsubscribed) unsubscribed.setTo(unfriendJid);
.to(unfriendJid)
.build();
connection.sendStanza(unsubscribed); connection.sendStanza(unsubscribed);
} }
}, UNFRIEND_MESSAGE); }, UNFRIEND_MESSAGE);
@ -164,10 +162,7 @@ public final class IoTProvisioningManager extends Manager {
// friendship requests. // friendship requests.
final XMPPConnection connection = connection(); final XMPPConnection connection = connection();
Friend friendNotification = new Friend(connection.getUser().asBareJid()); Friend friendNotification = new Friend(connection.getUser().asBareJid());
Message notificationMessage = connection.getStanzaFactory().buildMessageStanza() Message notificationMessage = new Message(friendJid, friendNotification);
.to(friendJid)
.addExtension(friendNotification)
.build();
connection.sendStanza(notificationMessage); connection.sendStanza(notificationMessage);
} else { } else {
// Check is the message was send from a thing we previously // Check is the message was send from a thing we previously
@ -364,11 +359,8 @@ public final class IoTProvisioningManager extends Manager {
} }
public void sendFriendshipRequest(BareJid bareJid) throws NotConnectedException, InterruptedException { public void sendFriendshipRequest(BareJid bareJid) throws NotConnectedException, InterruptedException {
XMPPConnection connection = connection(); Presence presence = new Presence(Presence.Type.subscribe);
Presence presence = connection.getStanzaFactory().buildPresenceStanza() presence.setTo(bareJid);
.ofType(Presence.Type.subscribe)
.to(bareJid)
.build();
friendshipRequestedCache.put(bareJid, null); friendshipRequestedCache.put(bareJid, null);
@ -387,12 +379,9 @@ public final class IoTProvisioningManager extends Manager {
public void unfriend(Jid friend) throws NotConnectedException, InterruptedException { public void unfriend(Jid friend) throws NotConnectedException, InterruptedException {
if (isMyFriend(friend)) { if (isMyFriend(friend)) {
XMPPConnection connection = connection(); Presence presence = new Presence(Presence.Type.unsubscribed);
Presence presence = connection.getStanzaFactory().buildPresenceStanza() presence.setTo(friend);
.ofType(Presence.Type.unsubscribed) connection().sendStanza(presence);
.to(friend)
.build();
connection.sendStanza(presence);
} }
} }

View file

@ -23,7 +23,6 @@ import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.provider.IQProvider; import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.jid_prep.element.JidPrepIq; import org.jivesoftware.smackx.jid_prep.element.JidPrepIq;
public class JidPrepIqProvider extends IQProvider<JidPrepIq> { public class JidPrepIqProvider extends IQProvider<JidPrepIq> {

View file

@ -35,7 +35,6 @@ import org.jivesoftware.smack.filter.MessageTypeFilter;
import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.MessageBuilder;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smackx.muclight.element.MUCLightAffiliationsIQ; import org.jivesoftware.smackx.muclight.element.MUCLightAffiliationsIQ;
@ -127,9 +126,9 @@ public class MultiUserChatLight {
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
*/ */
public void sendMessage(String text) throws NotConnectedException, InterruptedException { public void sendMessage(String text) throws NotConnectedException, InterruptedException {
MessageBuilder message = buildMessage(); Message message = createMessage();
message.setBody(text); message.setBody(text);
connection.sendStanza(message.build()); connection.sendStanza(message);
} }
/** /**
@ -158,28 +157,9 @@ public class MultiUserChatLight {
* Creates a new Message to send to the chat room. * Creates a new Message to send to the chat room.
* *
* @return a new Message addressed 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() { public Message createMessage() {
return connection.getStanzaFactory().buildMessageStanza() return new Message(room, Message.Type.groupchat);
.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)
;
} }
/** /**
@ -189,23 +169,10 @@ public class MultiUserChatLight {
* the message. * the message.
* @throws NotConnectedException if the XMPP connection is not connected. * @throws NotConnectedException if the XMPP connection is not connected.
* @throws InterruptedException if the calling thread was interrupted. * @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 { public void sendMessage(Message message) throws NotConnectedException, InterruptedException {
sendMessage(message.asBuilder()); message.setTo(room);
} message.setType(Message.Type.groupchat);
/**
* 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); connection.sendStanza(message);
} }

View file

@ -50,9 +50,7 @@ public class RemoteDisablingProvider extends ExtensionElementProvider<RemoteDisa
String affiliation = parser.getAttributeValue("", "affiliation"); String affiliation = parser.getAttributeValue("", "affiliation");
if (affiliation == null || !affiliation.equals("none")) { if (affiliation == null || !affiliation.equals("none")) {
// TODO: Is this correct? We previously returned null here, but was certainly wrong, as return null;
// providers should always return an element or throw.
throw new IOException("Invalid affiliation: " + affiliation);
} }
} }
} else if (eventType == XmlPullParser.Event.END_ELEMENT) { } else if (eventType == XmlPullParser.Event.END_ELEMENT) {

View file

@ -21,6 +21,7 @@ import java.util.WeakHashMap;
import org.jivesoftware.smack.ConnectionCreationListener; import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPConnectionRegistry; import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.filter.AndFilter;
@ -30,9 +31,7 @@ import org.jivesoftware.smack.filter.StanzaExtensionFilter;
import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.filter.ToTypeFilter; import org.jivesoftware.smack.filter.ToTypeFilter;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.util.Consumer;
import org.jivesoftware.smack.util.Predicate;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.sid.element.OriginIdElement; import org.jivesoftware.smackx.sid.element.OriginIdElement;
@ -63,12 +62,12 @@ public final class StableUniqueStanzaIdManager extends Manager {
private static final StanzaFilter ORIGIN_ID_FILTER = new StanzaExtensionFilter(OriginIdElement.ELEMENT, NAMESPACE); private static final StanzaFilter ORIGIN_ID_FILTER = new StanzaExtensionFilter(OriginIdElement.ELEMENT, NAMESPACE);
// Listener for outgoing stanzas that adds origin-ids to outgoing stanzas. // Listener for outgoing stanzas that adds origin-ids to outgoing stanzas.
private static final Consumer<MessageBuilder> ADD_ORIGIN_ID_INTERCEPTOR = mb -> OriginIdElement.addOriginId(mb); private static final StanzaListener ADD_ORIGIN_ID_INTERCEPTOR = new StanzaListener() {
@Override
// We need a filter for outgoing messages that do not carry an origin-id already. public void processStanza(Stanza stanza) {
private static final StanzaFilter ADD_ORIGIN_ID_FILTER = new AndFilter(OUTGOING_FILTER, new NotFilter(ORIGIN_ID_FILTER)); Message message = (Message) stanza;
private static final Predicate<Message> ADD_ORIGIN_ID_PREDICATE = m -> { OriginIdElement.addOriginId(message);
return ADD_ORIGIN_ID_FILTER.accept(m); }
}; };
static { static {
@ -113,8 +112,10 @@ public final class StableUniqueStanzaIdManager extends Manager {
* Start appending origin-id elements to outgoing stanzas and add the feature to disco. * Start appending origin-id elements to outgoing stanzas and add the feature to disco.
*/ */
public synchronized void enable() { public synchronized void enable() {
connection().addMessageInterceptor(ADD_ORIGIN_ID_INTERCEPTOR, ADD_ORIGIN_ID_PREDICATE);
ServiceDiscoveryManager.getInstanceFor(connection()).addFeature(NAMESPACE); 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);
} }
/** /**
@ -122,7 +123,7 @@ public final class StableUniqueStanzaIdManager extends Manager {
*/ */
public synchronized void disable() { public synchronized void disable() {
ServiceDiscoveryManager.getInstanceFor(connection()).removeFeature(NAMESPACE); ServiceDiscoveryManager.getInstanceFor(connection()).removeFeature(NAMESPACE);
connection().removeMessageInterceptor(ADD_ORIGIN_ID_INTERCEPTOR); connection().removeStanzaInterceptor(ADD_ORIGIN_ID_INTERCEPTOR);
} }
/** /**

View file

@ -17,7 +17,6 @@
package org.jivesoftware.smackx.sid.element; package org.jivesoftware.smackx.sid.element;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.MessageBuilder;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager; import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager;
@ -39,10 +38,7 @@ public class OriginIdElement extends StableAndUniqueIdElement {
* *
* @param message message. * @param message message.
* @return the added origin-id element. * @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) { public static OriginIdElement addOriginId(Message message) {
OriginIdElement originId = new OriginIdElement(); OriginIdElement originId = new OriginIdElement();
message.addExtension(originId); message.addExtension(originId);
@ -51,20 +47,6 @@ public class OriginIdElement extends StableAndUniqueIdElement {
return originId; 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. * Return true, if the message contains a origin-id element.
* *

View file

@ -21,7 +21,6 @@ import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.StandardExtensionElement; import org.jivesoftware.smack.packet.StandardExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.FormField;
import org.jivesoftware.smackx.xdata.FormFieldChildElement; import org.jivesoftware.smackx.xdata.FormFieldChildElement;

View file

@ -26,7 +26,6 @@ import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.parsing.StandardExtensionElementProvider; import org.jivesoftware.smack.parsing.StandardExtensionElementProvider;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException; import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.xdata.provider.FormFieldChildElementProvider; import org.jivesoftware.smackx.xdata.provider.FormFieldChildElementProvider;
import org.jivesoftware.smackx.xmlelement.element.DataFormsXmlElement; import org.jivesoftware.smackx.xmlelement.element.DataFormsXmlElement;

View file

@ -19,7 +19,6 @@ package org.jivesoftware.smackx.chat_markers;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.StanzaBuilder;
import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.packet.StreamOpen;
import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
@ -29,6 +28,7 @@ import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements.Acknowle
import org.jivesoftware.smackx.chat_markers.provider.AcknowledgedProvider; import org.jivesoftware.smackx.chat_markers.provider.AcknowledgedProvider;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.jxmpp.jid.impl.JidCreate;
public class AcknowledgedExtensionTest { public class AcknowledgedExtensionTest {
@ -39,10 +39,9 @@ public class AcknowledgedExtensionTest {
@Test @Test
public void checkDisplayedExtension() throws Exception { public void checkDisplayedExtension() throws Exception {
Message message = StanzaBuilder.buildMessage("message-2") Message message = new Message(JidCreate.from("northumberland@shakespeare.lit/westminster"));
.to("northumberland@shakespeare.lit/westminster") message.setStanzaId("message-2");
.addExtension(new ChatMarkersElements.AcknowledgedExtension("message-1")) message.addExtension(new ChatMarkersElements.AcknowledgedExtension("message-1"));
.build();
assertEquals(acknowledgedMessageStanza, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertEquals(acknowledgedMessageStanza, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }

View file

@ -19,7 +19,6 @@ package org.jivesoftware.smackx.chat_markers;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.StanzaBuilder;
import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.packet.StreamOpen;
import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
@ -29,6 +28,7 @@ import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements.Displaye
import org.jivesoftware.smackx.chat_markers.provider.DisplayedProvider; import org.jivesoftware.smackx.chat_markers.provider.DisplayedProvider;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.jxmpp.jid.impl.JidCreate;
public class DisplayedExtensionTest { public class DisplayedExtensionTest {
@ -39,10 +39,9 @@ public class DisplayedExtensionTest {
@Test @Test
public void checkDisplayedExtension() throws Exception { public void checkDisplayedExtension() throws Exception {
Message message = StanzaBuilder.buildMessage("message-2") Message message = new Message(JidCreate.from("northumberland@shakespeare.lit/westminster"));
.to("northumberland@shakespeare.lit/westminster") message.setStanzaId("message-2");
.addExtension(new ChatMarkersElements.DisplayedExtension("message-1")) message.addExtension(new ChatMarkersElements.DisplayedExtension("message-1"));
.build();
assertEquals(displayedMessageStanza, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertEquals(displayedMessageStanza, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }

View file

@ -19,7 +19,6 @@ package org.jivesoftware.smackx.chat_markers;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.StanzaBuilder;
import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
@ -40,12 +39,10 @@ public class MarkableExtensionTest {
@Test @Test
public void checkMarkableExtension() throws Exception { public void checkMarkableExtension() throws Exception {
Message message = StanzaBuilder.buildMessage("message-1") Message message = new Message(JidCreate.from("ingrichard@royalty.england.lit/throne"));
.to(JidCreate.from("ingrichard@royalty.england.lit/throne")) message.setStanzaId("message-1");
.setBody("My lord, dispatch; read o'er these articles.") message.setBody("My lord, dispatch; read o'er these articles.");
.addExtension(ChatMarkersElements.MarkableExtension.INSTANCE) message.addExtension(ChatMarkersElements.MarkableExtension.INSTANCE);
.build();
assertEquals(markableMessageStanza, message.toXML().toString()); assertEquals(markableMessageStanza, message.toXML().toString());
} }

View file

@ -19,7 +19,6 @@ package org.jivesoftware.smackx.chat_markers;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.StanzaBuilder;
import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.packet.StreamOpen;
import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParser;
@ -29,6 +28,7 @@ import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements.Received
import org.jivesoftware.smackx.chat_markers.provider.ReceivedProvider; import org.jivesoftware.smackx.chat_markers.provider.ReceivedProvider;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.jxmpp.jid.impl.JidCreate;
public class ReceivedExtensionTest { public class ReceivedExtensionTest {
@ -39,10 +39,9 @@ public class ReceivedExtensionTest {
@Test @Test
public void checkReceivedExtension() throws Exception { public void checkReceivedExtension() throws Exception {
Message message = StanzaBuilder.buildMessage("message-2") Message message = new Message(JidCreate.from("northumberland@shakespeare.lit/westminster"));
.to("northumberland@shakespeare.lit/westminster") message.setStanzaId("message-2");
.addExtension(new ChatMarkersElements.ReceivedExtension("message-1")) message.addExtension(new ChatMarkersElements.ReceivedExtension("message-1"));
.build();
assertEquals(receivedMessageStanza, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString()); assertEquals(receivedMessageStanza, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
} }

View file

@ -19,7 +19,6 @@ package org.jivesoftware.smackx.colors;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smackx.colors.ConsistentColor.Deficiency; import org.jivesoftware.smackx.colors.ConsistentColor.Deficiency;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View file

@ -25,8 +25,6 @@ import java.util.List;
import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message; 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.SmackTestSuite;
import org.jivesoftware.smackx.eme.element.ExplicitMessageEncryptionElement; import org.jivesoftware.smackx.eme.element.ExplicitMessageEncryptionElement;
@ -37,7 +35,7 @@ public class ExplicitMessageEncryptionElementTest extends SmackTestSuite {
@Test @Test
public void addToMessageTest() { public void addToMessageTest() {
Message message = StanzaBuilder.buildMessage().build(); Message message = new Message();
// Check inital state (no elements) // Check inital state (no elements)
assertNull(ExplicitMessageEncryptionElement.from(message)); assertNull(ExplicitMessageEncryptionElement.from(message));
@ -47,12 +45,9 @@ public class ExplicitMessageEncryptionElementTest extends SmackTestSuite {
List<ExtensionElement> extensions = message.getExtensions(); List<ExtensionElement> extensions = message.getExtensions();
assertEquals(0, extensions.size()); assertEquals(0, extensions.size());
MessageBuilder messageBuilder = StanzaBuilder.buildMessage();
// Add OMEMO // Add OMEMO
ExplicitMessageEncryptionElement.set(messageBuilder, ExplicitMessageEncryptionElement.set(message,
ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl); ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl);
message = messageBuilder.build();
extensions = message.getExtensions(); extensions = message.getExtensions();
assertEquals(1, extensions.size()); assertEquals(1, extensions.size());
assertTrue(ExplicitMessageEncryptionElement.hasProtocol(message, assertTrue(ExplicitMessageEncryptionElement.hasProtocol(message,
@ -64,10 +59,8 @@ public class ExplicitMessageEncryptionElementTest extends SmackTestSuite {
assertFalse(ExplicitMessageEncryptionElement.hasProtocol(message, assertFalse(ExplicitMessageEncryptionElement.hasProtocol(message,
ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.openpgpV0.getNamespace())); ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.openpgpV0.getNamespace()));
ExplicitMessageEncryptionElement.set(messageBuilder, ExplicitMessageEncryptionElement.set(message,
ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.openpgpV0); ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.openpgpV0);
message = messageBuilder.build();
extensions = message.getExtensions(); extensions = message.getExtensions();
assertEquals(2, extensions.size()); assertEquals(2, extensions.size());
assertTrue(ExplicitMessageEncryptionElement.hasProtocol(message, assertTrue(ExplicitMessageEncryptionElement.hasProtocol(message,
@ -76,10 +69,9 @@ public class ExplicitMessageEncryptionElementTest extends SmackTestSuite {
ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl)); ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl));
// Check, if adding additional OMEMO wont add another element // Check, if adding additional OMEMO wont add another element
ExplicitMessageEncryptionElement.set(messageBuilder, ExplicitMessageEncryptionElement.set(message,
ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl); ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl);
message = messageBuilder.build();
extensions = message.getExtensions(); extensions = message.getExtensions();
assertEquals(2, extensions.size()); assertEquals(2, extensions.size());
} }

View file

@ -25,7 +25,6 @@ import java.util.TimeZone;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type; import org.jivesoftware.smack.packet.Message.Type;
import org.jivesoftware.smack.packet.StanzaBuilder;
import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.packet.StreamOpen;
import org.jivesoftware.smackx.delay.packet.DelayInformation; import org.jivesoftware.smackx.delay.packet.DelayInformation;
@ -63,21 +62,21 @@ public class QueryArchiveTest extends MamTest {
@Test @Test
public void checkMamQueryResults() throws Exception { public void checkMamQueryResults() throws Exception {
Message message = StanzaBuilder.buildMessage("iasd207") Message message = new Message();
.from("coven@chat.shakespeare.lit") message.setStanzaId("iasd207");
.to("hag66@shakespeare.lit/pda") message.setFrom(JidCreate.from("coven@chat.shakespeare.lit"));
.build(); message.setTo(JidCreate.from("hag66@shakespeare.lit/pda"));
GregorianCalendar calendar = new GregorianCalendar(2002, 10 - 1, 13, 23, 58, 37); GregorianCalendar calendar = new GregorianCalendar(2002, 10 - 1, 13, 23, 58, 37);
calendar.setTimeZone(TimeZone.getTimeZone("UTC")); calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = calendar.getTime(); Date date = calendar.getTime();
DelayInformation delay = new DelayInformation(date); DelayInformation delay = new DelayInformation(date);
Message forwardedMessage = StanzaBuilder.buildMessage("162BEBB1-F6DB-4D9A-9BD8-CFDCC801A0B2") Message forwardedMessage = new Message();
.from(JidCreate.from("coven@chat.shakespeare.lit/firstwitch")) forwardedMessage.setFrom(JidCreate.from("coven@chat.shakespeare.lit/firstwitch"));
.ofType(Type.chat) forwardedMessage.setStanzaId("162BEBB1-F6DB-4D9A-9BD8-CFDCC801A0B2");
.setBody("Thrice the brinded cat hath mew.") forwardedMessage.setType(Type.chat);
.build(); forwardedMessage.setBody("Thrice the brinded cat hath mew.");
Forwarded forwarded = new Forwarded(delay, forwardedMessage); Forwarded forwarded = new Forwarded(delay, forwardedMessage);

Some files were not shown because too many files have changed in this diff Show more