enabledSaslMechanisms;
@@ -837,7 +926,12 @@ public abstract class ConnectionConfiguration {
throw new IllegalArgumentException(
"Port must be a 16-bit unsigned integer (i.e. between 0-65535. Port was: " + port);
}
- this.port = port;
+ UInt16 portUint16 = UInt16.from(port);
+ return setPort(portUint16);
+ }
+
+ public B setPort(UInt16 port) {
+ this.port = Objects.requireNonNull(port);
return getThis();
}
@@ -923,9 +1017,28 @@ public abstract class ConnectionConfiguration {
*
* @param context the custom SSLContext for new sockets.
* @return a reference to this builder.
+ * @deprecated use {@link #setSslContextFactory(SslContextFactory)} instead}.
*/
+ // TODO: Remove in Smack 4.5.
+ @Deprecated
public B setCustomSSLContext(SSLContext context) {
- this.customSSLContext = Objects.requireNonNull(context, "The SSLContext must not be null");
+ return setSslContextFactory(() -> {
+ return context;
+ });
+ }
+
+ /**
+ * Sets a custom SSLContext for creating SSL sockets.
+ *
+ * For more information on how to create a SSLContext see Java Secure Socket Extension (JSEE) Reference Guide: Creating Your Own X509TrustManager
+ *
+ * @param sslContextFactory the custom SSLContext for new sockets.
+ * @return a reference to this builder.
+ */
+ public B setSslContextFactory(SslContextFactory sslContextFactory) {
+ this.sslContextFactory = Objects.requireNonNull(sslContextFactory, "The provided SslContextFactory must not be null");
return getThis();
}
@@ -1166,5 +1279,4 @@ public abstract class ConnectionConfiguration {
protected abstract B getThis();
}
-
}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/Manager.java b/smack-core/src/main/java/org/jivesoftware/smack/Manager.java
index d3c4beec1..a306bc3af 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/Manager.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/Manager.java
@@ -54,6 +54,14 @@ public abstract class Manager {
}
protected static final ScheduledAction schedule(Runnable runnable, long delay, TimeUnit unit) {
- return AbstractXMPPConnection.SMACK_REACTOR.schedule(runnable, delay, unit);
+ return schedule(runnable, delay, unit, ScheduledAction.Kind.NonBlocking);
+ }
+
+ protected static final ScheduledAction scheduleBlocking(Runnable runnable, long delay, TimeUnit unit) {
+ return schedule(runnable, delay, unit, ScheduledAction.Kind.Blocking);
+ }
+
+ protected static final ScheduledAction schedule(Runnable runnable, long delay, TimeUnit unit, ScheduledAction.Kind scheduledActionKind) {
+ return AbstractXMPPConnection.SMACK_REACTOR.schedule(runnable, delay, unit, scheduledActionKind);
}
}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/ScheduledAction.java b/smack-core/src/main/java/org/jivesoftware/smack/ScheduledAction.java
index 5b5f0b238..da0377fab 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/ScheduledAction.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/ScheduledAction.java
@@ -20,20 +20,34 @@ import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
+import org.jivesoftware.smack.util.Async;
+
public class ScheduledAction implements Delayed {
- final Runnable action;
+ enum Kind {
+ NonBlocking,
+ Blocking,
+ }
+
+ private final Runnable action;
final Date releaseTime;
final SmackReactor smackReactor;
+ final Kind kind;
- ScheduledAction(Runnable action, Date releaseTime, SmackReactor smackReactor) {
+ ScheduledAction(Runnable action, Date releaseTime, SmackReactor smackReactor, Kind kind) {
this.action = action;
this.releaseTime = releaseTime;
this.smackReactor = smackReactor;
+ this.kind = kind;
}
- public void cancel() {
- smackReactor.cancel(this);
+ /**
+ * Cancels this scheduled action.
+ *
+ * @return true
if the scheduled action was still pending and got removed, false
otherwise.
+ */
+ public boolean cancel() {
+ return smackReactor.cancel(this);
}
public boolean isDue() {
@@ -63,4 +77,15 @@ public class ScheduledAction implements Delayed {
long delayInMillis = getTimeToDueMillis();
return unit.convert(delayInMillis, TimeUnit.MILLISECONDS);
}
+
+ void run() {
+ switch (kind) {
+ case NonBlocking:
+ action.run();
+ break;
+ case Blocking:
+ Async.go(() -> action.run());
+ break;
+ }
+ }
}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/SmackReactor.java b/smack-core/src/main/java/org/jivesoftware/smack/SmackReactor.java
index 76d028204..eaff9ca3d 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/SmackReactor.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/SmackReactor.java
@@ -145,15 +145,21 @@ public class SmackReactor {
}
}
- ScheduledAction schedule(Runnable runnable, long delay, TimeUnit unit) {
+ ScheduledAction schedule(Runnable runnable, long delay, TimeUnit unit, ScheduledAction.Kind scheduledActionKind) {
long releaseTimeEpoch = System.currentTimeMillis() + unit.toMillis(delay);
Date releaseTimeDate = new Date(releaseTimeEpoch);
- ScheduledAction scheduledAction = new ScheduledAction(runnable, releaseTimeDate, this);
+ ScheduledAction scheduledAction = new ScheduledAction(runnable, releaseTimeDate, this, scheduledActionKind);
scheduledActions.add(scheduledAction);
selector.wakeup();
return scheduledAction;
}
+ /**
+ * Cancels the scheduled action.
+ *
+ * @param scheduledAction the scheduled action to cancel.
+ * @return true
if the scheduled action was still pending and got removed, false
otherwise.
+ */
boolean cancel(ScheduledAction scheduledAction) {
return scheduledActions.remove(scheduledAction);
}
@@ -200,7 +206,7 @@ public class SmackReactor {
}
if (dueScheduledAction != null) {
- dueScheduledAction.action.run();
+ dueScheduledAction.run();
return;
}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java
index 9694b47b8..061d25e7a 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java
@@ -17,11 +17,6 @@
package org.jivesoftware.smack.c2s;
import java.io.IOException;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collection;
@@ -65,6 +60,8 @@ import org.jivesoftware.smack.fsm.StateDescriptorGraph.GraphVertex;
import org.jivesoftware.smack.fsm.StateMachineException;
import org.jivesoftware.smack.fsm.StateTransitionResult;
import org.jivesoftware.smack.fsm.StateTransitionResult.AttemptResult;
+import org.jivesoftware.smack.internal.AbstractStats;
+import org.jivesoftware.smack.internal.SmackTlsContext;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Nonza;
@@ -78,6 +75,7 @@ import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.sasl.SASLErrorException;
import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.util.ArrayBlockingQueueWithShutdown;
+import org.jivesoftware.smack.util.ExtendedAppendable;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
@@ -184,9 +182,7 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
@Override
- public SmackTlsContext getSmackTlsContext()
- throws KeyManagementException, NoSuchAlgorithmException, CertificateException, IOException,
- UnrecoverableKeyException, KeyStoreException, NoSuchProviderException {
+ public SmackTlsContext getSmackTlsContext() {
return ModularXmppClientToServerConnection.this.getSmackTlsContext();
}
@@ -1069,7 +1065,7 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
return new Stats(transportsStats, filterStats);
}
- public static final class Stats {
+ public static final class Stats extends AbstractStats {
public final Map, XmppClientToServerTransport.Stats> transportsStats;
public final Map filtersStats;
@@ -1079,7 +1075,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
this.filtersStats = Collections.unmodifiableMap(filtersStats);
}
- public void appendStatsTo(Appendable appendable) throws IOException {
+ @Override
+ public void appendStatsTo(ExtendedAppendable appendable) throws IOException {
StringUtils.appendHeading(appendable, "Connection stats", '#').append('\n');
for (Map.Entry, XmppClientToServerTransport.Stats> entry : transportsStats.entrySet()) {
@@ -1099,16 +1096,5 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
}
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- try {
- appendStatsTo(sb);
- } catch (IOException e) {
- // Should never happen.
- throw new AssertionError(e);
- }
- return sb.toString();
- }
}
}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/c2s/internal/ModularXmppClientToServerConnectionInternal.java b/smack-core/src/main/java/org/jivesoftware/smack/c2s/internal/ModularXmppClientToServerConnectionInternal.java
index 57452f270..b08676914 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/c2s/internal/ModularXmppClientToServerConnectionInternal.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/c2s/internal/ModularXmppClientToServerConnectionInternal.java
@@ -16,20 +16,12 @@
*/
package org.jivesoftware.smack.c2s.internal;
-import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
import java.util.ListIterator;
import java.util.Queue;
-import org.jivesoftware.smack.AbstractXMPPConnection.SmackTlsContext;
import org.jivesoftware.smack.SmackException.ConnectionUnexpectedTerminatedException;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
@@ -41,6 +33,7 @@ import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection;
import org.jivesoftware.smack.c2s.XmppClientToServerTransport;
import org.jivesoftware.smack.debugger.SmackDebugger;
import org.jivesoftware.smack.fsm.ConnectionStateEvent;
+import org.jivesoftware.smack.internal.SmackTlsContext;
import org.jivesoftware.smack.packet.Nonza;
import org.jivesoftware.smack.packet.TopLevelStreamElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
@@ -107,9 +100,7 @@ public abstract class ModularXmppClientToServerConnectionInternal {
public abstract void newStreamOpenWaitForFeaturesSequence(String waitFor) throws InterruptedException,
ConnectionUnexpectedTerminatedException, NoResponseException, NotConnectedException;
- public abstract SmackTlsContext getSmackTlsContext()
- throws KeyManagementException, NoSuchAlgorithmException, CertificateException, IOException,
- UnrecoverableKeyException, KeyStoreException, NoSuchProviderException;
+ public abstract SmackTlsContext getSmackTlsContext();
public abstract SN sendAndWaitForResponse(Nonza nonza,
Class successNonzaClass, Class failedNonzaClass)
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/compression/XMPPInputOutputStream.java b/smack-core/src/main/java/org/jivesoftware/smack/compression/XMPPInputOutputStream.java
index 837028c64..5f133a640 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/compression/XMPPInputOutputStream.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/compression/XMPPInputOutputStream.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright 2013-2018 Florian Schmaus
+ * Copyright 2013-2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,9 +20,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import org.jivesoftware.smack.util.Objects;
+
public abstract class XMPPInputOutputStream {
- protected static FlushMethod flushMethod;
+ protected static FlushMethod flushMethod = FlushMethod.SYNC_FLUSH;
/**
* Set the used flushed method when compressing data. The default is full flush which may not
@@ -33,7 +35,7 @@ public abstract class XMPPInputOutputStream {
* @param flushMethod TODO javadoc me please
*/
public static void setFlushMethod(FlushMethod flushMethod) {
- XMPPInputOutputStream.flushMethod = flushMethod;
+ XMPPInputOutputStream.flushMethod = Objects.requireNonNull(flushMethod);
}
public static FlushMethod getFlushMethod() {
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java b/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java
index f37d08b11..147d0c9f1 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaFilter.java
@@ -66,4 +66,13 @@ public interface StanzaFilter extends Predicate {
default boolean test(Stanza stanza) {
return accept(stanza);
}
+
+ default Predicate asPredicate(Class> stanzaClass) {
+ return s -> {
+ if (!stanzaClass.isAssignableFrom(s.getClass())) {
+ return false;
+ }
+ return accept(s);
+ };
+ }
}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/internal/AbstractStats.java b/smack-core/src/main/java/org/jivesoftware/smack/internal/AbstractStats.java
new file mode 100644
index 000000000..1cddd964c
--- /dev/null
+++ b/smack-core/src/main/java/org/jivesoftware/smack/internal/AbstractStats.java
@@ -0,0 +1,52 @@
+/**
+ *
+ * Copyright 2020 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.internal;
+
+import java.io.IOException;
+
+import org.jivesoftware.smack.util.ExtendedAppendable;
+
+public abstract class AbstractStats {
+
+ public final void appendStatsTo(Appendable appendable) throws IOException {
+ appendStatsTo(new ExtendedAppendable(appendable));
+ }
+
+ public abstract void appendStatsTo(ExtendedAppendable appendable) throws IOException;
+
+ private transient String toStringCache;
+
+ @Override
+ public final String toString() {
+ if (toStringCache != null) {
+ return toStringCache;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ try {
+ appendStatsTo(sb);
+ } catch (IOException e) {
+ // Should never happen.
+ throw new AssertionError(e);
+ }
+
+ toStringCache = sb.toString();
+
+ return toStringCache;
+ }
+
+}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/internal/SmackTlsContext.java b/smack-core/src/main/java/org/jivesoftware/smack/internal/SmackTlsContext.java
new file mode 100644
index 000000000..b0425b162
--- /dev/null
+++ b/smack-core/src/main/java/org/jivesoftware/smack/internal/SmackTlsContext.java
@@ -0,0 +1,32 @@
+/**
+ *
+ * Copyright 2020 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.internal;
+
+import javax.net.ssl.SSLContext;
+
+import org.jivesoftware.smack.util.dns.SmackDaneVerifier;
+
+public final class SmackTlsContext {
+ public final SSLContext sslContext;
+ public final SmackDaneVerifier daneVerifier;
+
+ public SmackTlsContext(SSLContext sslContext, SmackDaneVerifier daneVerifier) {
+ assert sslContext != null;
+ this.sslContext = sslContext;
+ this.daneVerifier = daneVerifier;
+ }
+}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/internal/package-info.java b/smack-core/src/main/java/org/jivesoftware/smack/internal/package-info.java
new file mode 100644
index 000000000..6311fbe06
--- /dev/null
+++ b/smack-core/src/main/java/org/jivesoftware/smack/internal/package-info.java
@@ -0,0 +1,21 @@
+/**
+ *
+ * Copyright 2020 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.
+ */
+
+/**
+ * Smack internal classes and interfaces.
+ */
+package org.jivesoftware.smack.internal;
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractIqBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractIqBuilder.java
index d975db0ef..5eac12435 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractIqBuilder.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractIqBuilder.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright 2019 Florian Schmaus
+ * Copyright 2019-2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,10 @@ public abstract class AbstractIqBuilder> extend
protected IQ.Type type = IQ.Type.get;
+ AbstractIqBuilder(IQ other, String stanzaId) {
+ super(other, stanzaId);
+ }
+
AbstractIqBuilder(AbstractIqBuilder> other) {
super(other);
type = other.type;
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/IqBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/IqBuilder.java
index 2e24f53b2..644f077ea 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/packet/IqBuilder.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/IqBuilder.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright 2019 Florian Schmaus
+ * Copyright 2019-2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,10 @@ import org.jivesoftware.smack.util.Objects;
public abstract class IqBuilder, I extends IQ>
extends AbstractIqBuilder {
+ protected IqBuilder(IQ other, String stanzaId) {
+ super(other, stanzaId);
+ }
+
protected IqBuilder(AbstractIqBuilder> other) {
super(other);
}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java
index 9a1d1a43d..0f819b429 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright 2003-2007 Jive Software.
+ * Copyright 2003-2007 Jive Software, 2020 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,10 +17,9 @@
package org.jivesoftware.smack.packet;
+import java.util.List;
import java.util.Locale;
-import javax.net.SocketFactory;
-
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.TypedCloneable;
@@ -29,7 +28,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jxmpp.jid.Jid;
/**
- * Represents XMPP presence packets. Every presence stanza has a type, which is one of
+ * Represents XMPP presence stanzas. Every presence stanza has a type, which is one of
* the following values:
*
* - {@link Presence.Type#available available} -- (Default) indicates the user is available to
@@ -55,7 +54,7 @@ import org.jxmpp.jid.Jid;
* {@link Mode#dnd dnd} (do not disturb).
*
*
- * Presence packets are used for two purposes. First, to notify the server of
+ * Presence stanzas are used for two purposes. First, to notify the server of
* the user's current presence status. Second, they are used to subscribe and
* unsubscribe users from the roster.
*
@@ -83,7 +82,7 @@ public final class Presence extends MessageOrPresence
* Creates a new presence update. Status, priority, and mode are left un-set.
*
* @param type the type.
- * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
+ * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead.
*/
@Deprecated
// TODO: Remove in Smack 4.5.
@@ -99,7 +98,7 @@ public final class Presence extends MessageOrPresence
* @param to the recipient.
* @param type the type.
* @since 4.2
- * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
+ * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead.
*/
@Deprecated
// TODO: Remove in Smack 4.5.
@@ -115,7 +114,7 @@ public final class Presence extends MessageOrPresence
* @param status a text message describing the presence update.
* @param priority the priority of this presence update.
* @param mode the mode type for this presence update.
- * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
+ * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead.
*/
@Deprecated
// TODO: Remove in Smack 4.5.
@@ -191,7 +190,7 @@ public final class Presence extends MessageOrPresence
* Sets the type of the presence packet.
*
* @param type the type of the presence packet.
- * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
+ * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead.
*/
@Deprecated
// TODO: Remove in Smack 4.5.
@@ -209,7 +208,7 @@ public final class Presence extends MessageOrPresence
* describing a user's presence (i.e., "gone to lunch").
*
* @param status the status message.
- * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
+ * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead.
*/
@Deprecated
// TODO: Remove in Smack 4.5.
@@ -236,7 +235,7 @@ public final class Presence extends MessageOrPresence
* @param priority the priority of the presence.
* @throws IllegalArgumentException if the priority is outside the valid range.
* @see RFC 6121 § 4.7.2.3. Priority Element
- * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
+ * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead.
*/
@Deprecated
// TODO: Remove in Smack 4.5.
@@ -265,7 +264,7 @@ public final class Presence extends MessageOrPresence
* to be the same thing as {@link Presence.Mode#available}.
*
* @param mode the mode.
- * @deprecated use {@link StanzaBuilder} or {@link SocketFactory} instead.
+ * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead.
*/
@Deprecated
// TODO: Remove in Smack 4.5.
@@ -309,6 +308,16 @@ public final class Presence extends MessageOrPresence
if (type != Type.available) {
buf.attribute("type", type);
}
+
+ List extensions = getExtensions();
+ if (status == null
+ && priority == null
+ && (mode == null || mode == Mode.available)
+ && extensions.isEmpty()
+ && getError() == null) {
+ return buf.closeEmptyElement();
+ }
+
buf.rightAngleBracket();
buf.optElement("status", status);
@@ -317,7 +326,7 @@ public final class Presence extends MessageOrPresence
buf.element("show", mode);
}
- buf.append(getExtensions());
+ buf.append(extensions);
// Add the error sub-packet, if there is one.
appendErrorIfExists(buf);
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/ExtendedAppendable.java b/smack-core/src/main/java/org/jivesoftware/smack/util/ExtendedAppendable.java
new file mode 100644
index 000000000..4cf97622c
--- /dev/null
+++ b/smack-core/src/main/java/org/jivesoftware/smack/util/ExtendedAppendable.java
@@ -0,0 +1,56 @@
+/**
+ *
+ * Copyright 2020 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.io.IOException;
+
+public class ExtendedAppendable implements Appendable {
+
+ private final Appendable appendable;
+
+ public ExtendedAppendable(Appendable appendable) {
+ this.appendable = appendable;
+ }
+
+ @Override
+ public ExtendedAppendable append(CharSequence csq) throws IOException {
+ appendable.append(csq);
+ return this;
+ }
+
+ @Override
+ public ExtendedAppendable append(CharSequence csq, int start, int end) throws IOException {
+ appendable.append(csq, start, end);
+ return this;
+ }
+
+ @Override
+ public ExtendedAppendable append(char c) throws IOException {
+ appendable.append(c);
+ return this;
+ }
+
+ public ExtendedAppendable append(boolean b) throws IOException {
+ appendable.append(String.valueOf(b));
+ return this;
+ }
+
+ public ExtendedAppendable append(int i) throws IOException {
+ appendable.append(String.valueOf(i));
+ return this;
+ }
+}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/NumberUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/NumberUtil.java
index 831ccf0ad..98635309d 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/util/NumberUtil.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/util/NumberUtil.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright © 2015-2019 Florian Schmaus
+ * Copyright © 2015-2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,15 +33,15 @@ public class NumberUtil {
/**
* Checks if the given long is within the range of an unsigned 32-bit integer, the XML type "xs:unsignedInt".
*
- * @param value TODO javadoc me please
+ * @param value the long to check.
* @return the input value.
*/
public static long requireUInt32(long value) {
if (value < 0) {
- throw new IllegalArgumentException("unsigned 32-bit integers can't be negative");
+ throw new IllegalArgumentException("unsigned 32-bit integers can't be negative: " + value);
}
if (value > ((1L << 32) - 1)) {
- throw new IllegalArgumentException("unsigned 32-bit integers can't be greater than 2^32 - 1");
+ throw new IllegalArgumentException("unsigned 32-bit integers can't be greater than 2^32 - 1: " + value);
}
return value;
}
@@ -49,15 +49,15 @@ public class NumberUtil {
/**
* Checks if the given int is within the range of an unsigned 16-bit integer, the XML type "xs:unsignedShort".
*
- * @param value TODO javadoc me please
+ * @param value the int to check.
* @return the input value.
*/
public static int requireUShort16(int value) {
if (value < 0) {
- throw new IllegalArgumentException("unsigned 16-bit integers can't be negative");
+ throw new IllegalArgumentException("unsigned 16-bit integers can't be negative: " + value);
}
if (value > ((1 << 16) - 1)) {
- throw new IllegalArgumentException("unsigned 16-bit integers can't be greater than 2^16 - 1");
+ throw new IllegalArgumentException("unsigned 16-bit integers can't be greater than 2^16 - 1: " + value);
}
return value;
}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/SslContextFactory.java b/smack-core/src/main/java/org/jivesoftware/smack/util/SslContextFactory.java
new file mode 100644
index 000000000..a3c308b9f
--- /dev/null
+++ b/smack-core/src/main/java/org/jivesoftware/smack/util/SslContextFactory.java
@@ -0,0 +1,25 @@
+/**
+ *
+ * Copyright 2020 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 javax.net.ssl.SSLContext;
+
+public interface SslContextFactory {
+
+ SSLContext createSslContext();
+
+}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/TLSUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/TLSUtils.java
index 60c644320..c1af8ba61 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/util/TLSUtils.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/util/TLSUtils.java
@@ -22,12 +22,8 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
@@ -38,13 +34,9 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import org.jivesoftware.smack.ConnectionConfiguration;
@@ -132,25 +124,13 @@ public class TLSUtils {
*
* @param builder a connection configuration builder.
* @param Type of the ConnectionConfiguration builder.
- * @throws NoSuchAlgorithmException if no such algorithm is available.
- * @throws KeyManagementException if there was a key mangement error.
* @return the given builder.
*/
- public static > B acceptAllCertificates(B builder) throws NoSuchAlgorithmException, KeyManagementException {
- SSLContext context = SSLContext.getInstance(TLS);
- context.init(null, new TrustManager[] { new AcceptAllTrustManager() }, new SecureRandom());
- builder.setCustomSSLContext(context);
+ public static > B acceptAllCertificates(B builder) {
+ builder.setCustomX509TrustManager(new AcceptAllTrustManager());
return builder;
}
- private static final HostnameVerifier DOES_NOT_VERIFY_VERIFIER = new HostnameVerifier() {
- @Override
- public boolean verify(String hostname, SSLSession session) {
- // This verifier doesn't verify the hostname, it always returns true.
- return true;
- }
- };
-
/**
* Disable the hostname verification of TLS certificates.
*
@@ -164,7 +144,9 @@ public class TLSUtils {
* @return the given builder.
*/
public static > B disableHostnameVerificationForTlsCertificates(B builder) {
- builder.setHostnameVerifier(DOES_NOT_VERIFY_VERIFIER);
+ builder.setHostnameVerifier((hostname, session) -> {
+ return true;
+ });
return builder;
}
@@ -274,24 +256,6 @@ public class TLSUtils {
}
}
- public static X509TrustManager getDefaultX509TrustManager(KeyStore keyStore) {
- String defaultAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
- TrustManagerFactory trustManagerFactory;
- try {
- trustManagerFactory = TrustManagerFactory.getInstance(defaultAlgorithm);
- trustManagerFactory.init(keyStore);
- } catch (NoSuchAlgorithmException | KeyStoreException e) {
- throw new AssertionError(e);
- }
-
- for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
- if (trustManager instanceof X509TrustManager) {
- return (X509TrustManager) trustManager;
- }
- }
- throw new AssertionError("No trust manager for the default algorithm " + defaultAlgorithm + " found");
- }
-
private static final File DEFAULT_TRUSTSTORE_PATH;
static {
diff --git a/smack-core/src/test/java/org/jivesoftware/smack/provider/ProviderManagerTest.java b/smack-core/src/test/java/org/jivesoftware/smack/provider/ProviderManagerTest.java
index 5210e6344..1c005322d 100644
--- a/smack-core/src/test/java/org/jivesoftware/smack/provider/ProviderManagerTest.java
+++ b/smack-core/src/test/java/org/jivesoftware/smack/provider/ProviderManagerTest.java
@@ -29,6 +29,7 @@ public class ProviderManagerTest {
/**
* This test should be run in a clean (e.g. forked) VM
+ * @throws Exception if exception.
*/
@Test
public void shouldInitializeSmackTest() throws Exception {
diff --git a/smack-core/src/test/java/org/jivesoftware/smack/util/DnsUtilTest.java b/smack-core/src/test/java/org/jivesoftware/smack/util/DnsUtilTest.java
index eef18918f..6a7fe8e54 100644
--- a/smack-core/src/test/java/org/jivesoftware/smack/util/DnsUtilTest.java
+++ b/smack-core/src/test/java/org/jivesoftware/smack/util/DnsUtilTest.java
@@ -25,6 +25,7 @@ import org.junit.Test;
public class DnsUtilTest {
+ @SuppressWarnings("UnnecessaryAnonymousClass")
private static final SmackDaneProvider DNS_UTIL_TEST_DANE_PROVIDER = new SmackDaneProvider() {
@Override
public SmackDaneVerifier newInstance() {
diff --git a/smack-core/src/testFixtures/java/org/jivesoftware/smack/DummyConnection.java b/smack-core/src/testFixtures/java/org/jivesoftware/smack/DummyConnection.java
index 135fd79d0..d0864842b 100644
--- a/smack-core/src/testFixtures/java/org/jivesoftware/smack/DummyConnection.java
+++ b/smack-core/src/testFixtures/java/org/jivesoftware/smack/DummyConnection.java
@@ -150,6 +150,7 @@ public class DummyConnection extends AbstractXMPPConnection {
* Returns the first stanza that's sent through {@link #sendStanza(Stanza)}
* and that has not been returned by earlier calls to this method.
*
+ * @param
the top level stream element class.
* @return a sent packet.
*/
public
P getSentPacket() {
@@ -162,6 +163,8 @@ public class DummyConnection extends AbstractXMPPConnection {
* method will block for up to the specified number of seconds if no packets
* have been sent yet.
*
+ * @param wait how long to wait in seconds.
+ * @param
the top level stream element class.
* @return a sent packet.
*/
@SuppressWarnings("unchecked")
@@ -222,6 +225,7 @@ public class DummyConnection extends AbstractXMPPConnection {
ConnectionConfiguration.Builder {
private Builder() {
+ setSecurityMode(SecurityMode.disabled);
}
@Override
diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/CarbonExtension.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/CarbonExtension.java
index 960922d07..2b7220ba1 100644
--- a/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/CarbonExtension.java
+++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/CarbonExtension.java
@@ -18,6 +18,7 @@ package org.jivesoftware.smackx.carbons.packet;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message;
+import org.jivesoftware.smack.packet.MessageBuilder;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.forward.packet.Forwarded;
@@ -158,8 +159,21 @@ public class CarbonExtension implements ExtensionElement {
* Marks a message "private", so that it will not be carbon-copied, by adding private packet
* extension to the message.
*
- * @param message the message to add the private extension to
+ * @param messageBuilder the message to add the private extension to
*/
+ public static void addTo(MessageBuilder messageBuilder) {
+ messageBuilder.addExtension(INSTANCE);
+ }
+
+ /**
+ * Marks a message "private", so that it will not be carbon-copied, by adding private packet
+ * extension to the message.
+ *
+ * @param message the message to add the private extension to
+ * @deprecated use {@link #addTo(MessageBuilder)} instead.
+ */
+ // TODO: Remove in Smack 4.6
+ @Deprecated
public static void addTo(Message message) {
message.addExtension(INSTANCE);
}
diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/fallback_indication/FallbackIndicationManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/fallback_indication/FallbackIndicationManager.java
index da58e6ae9..e0859dd26 100644
--- a/smack-experimental/src/main/java/org/jivesoftware/smackx/fallback_indication/FallbackIndicationManager.java
+++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/fallback_indication/FallbackIndicationManager.java
@@ -25,7 +25,6 @@ import org.jivesoftware.smack.AsyncButOrdered;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.SmackException;
-import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.XMPPException;
@@ -68,23 +67,20 @@ public final class FallbackIndicationManager extends Manager {
private final StanzaFilter fallbackIndicationElementFilter = new AndFilter(StanzaTypeFilter.MESSAGE,
new StanzaExtensionFilter(FallbackIndicationElement.ELEMENT, FallbackIndicationElement.NAMESPACE));
- private final StanzaListener fallbackIndicationElementListener = new StanzaListener() {
- @Override
- public void processStanza(Stanza packet) {
- Message message = (Message) packet;
- FallbackIndicationElement indicator = FallbackIndicationElement.fromMessage(message);
- String body = message.getBody();
- asyncButOrdered.performAsyncButOrdered(message.getFrom().asBareJid(), () -> {
- for (FallbackIndicationListener l : listeners) {
- l.onFallbackIndicationReceived(message, indicator, body);
- }
- });
- }
- };
+ private void fallbackIndicationElementListener(Stanza packet) {
+ Message message = (Message) packet;
+ FallbackIndicationElement indicator = FallbackIndicationElement.fromMessage(message);
+ String body = message.getBody();
+ asyncButOrdered.performAsyncButOrdered(message.getFrom().asBareJid(), () -> {
+ for (FallbackIndicationListener l : listeners) {
+ l.onFallbackIndicationReceived(message, indicator, body);
+ }
+ });
+ }
private FallbackIndicationManager(XMPPConnection connection) {
super(connection);
- connection.addAsyncStanzaListener(fallbackIndicationElementListener, fallbackIndicationElementFilter);
+ connection.addAsyncStanzaListener(this::fallbackIndicationElementListener, fallbackIndicationElementFilter);
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(FallbackIndicationElement.NAMESPACE);
}
@@ -139,7 +135,7 @@ public final class FallbackIndicationManager extends Manager {
* @param fallbackMessageBody fallback message body
* @return builder with set body and added fallback element
*/
- public MessageBuilder addFallbackIndicationWithBody(MessageBuilder messageBuilder, String fallbackMessageBody) {
+ public static MessageBuilder addFallbackIndicationWithBody(MessageBuilder messageBuilder, String fallbackMessageBody) {
return addFallbackIndication(messageBuilder).setBody(fallbackMessageBody);
}
@@ -149,7 +145,7 @@ public final class FallbackIndicationManager extends Manager {
* @param messageBuilder message builder
* @return message builder with added fallback element
*/
- public MessageBuilder addFallbackIndication(MessageBuilder messageBuilder) {
+ public static MessageBuilder addFallbackIndication(MessageBuilder messageBuilder) {
return messageBuilder.addExtension(new FallbackIndicationElement());
}
diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadManager.java
index 299466bbb..23379a4cc 100644
--- a/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadManager.java
+++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadManager.java
@@ -37,7 +37,6 @@ import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
-import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.Manager;
@@ -307,7 +306,9 @@ public final class HttpFileUploadManager extends Manager {
public URL uploadFile(InputStream inputStream, String fileName, long fileSize, UploadProgressListener listener) throws XMPPErrorException, InterruptedException, SmackException, IOException {
Objects.requireNonNull(inputStream, "Input Stream cannot be null");
Objects.requireNonNull(fileName, "Filename Stream cannot be null");
- Objects.requireNonNull(fileSize, "Filesize Stream cannot be null");
+ if (fileSize < 0) {
+ throw new IllegalArgumentException("File size cannot be negative");
+ }
final Slot slot = requestSlot(fileName, fileSize, "application/octet-stream");
upload(inputStream, fileSize, slot, listener);
return slot.getGetUrl();
@@ -324,8 +325,7 @@ public final class HttpFileUploadManager extends Manager {
* supported by the service.
* @throws InterruptedException if the calling thread was interrupted.
* @throws XMPPException.XMPPErrorException if there was an XMPP error returned.
- * @throws SmackException.NotConnectedException if the XMPP connection is not connected.
- * @throws SmackException.NoResponseException if there was no response from the remote entity.
+ * @throws SmackException if smack exception.
*/
public Slot requestSlot(String filename, long fileSize) throws InterruptedException,
XMPPException.XMPPErrorException, SmackException {
@@ -348,7 +348,7 @@ public final class HttpFileUploadManager extends Manager {
* @throws SmackException.NotConnectedException if the XMPP connection is not connected.
* @throws InterruptedException if the calling thread was interrupted.
* @throws XMPPException.XMPPErrorException if there was an XMPP error returned.
- * @throws SmackException.NoResponseException if there was no response from the remote entity.
+ * @throws SmackException if smack exception.
*/
public Slot requestSlot(String filename, long fileSize, String contentType) throws SmackException,
InterruptedException, XMPPException.XMPPErrorException {
@@ -427,11 +427,6 @@ public final class HttpFileUploadManager extends Manager {
this.tlsSocketFactory = tlsContext.getSocketFactory();
}
- public void useTlsSettingsFrom(ConnectionConfiguration connectionConfiguration) {
- SSLContext sslContext = connectionConfiguration.getCustomSSLContext();
- setTlsContext(sslContext);
- }
-
private void upload(InputStream iStream, long fileSize, Slot slot, UploadProgressListener listener) throws IOException {
final URL putUrl = slot.getPutUrl();
diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamElements.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamElements.java
index 034245a5a..9fcff7b9c 100644
--- a/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamElements.java
+++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamElements.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright © 2016 Florian Schmaus and Fernando Ramirez
+ * Copyright © 2016-2020 Florian Schmaus and Fernando Ramirez
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ import org.jxmpp.jid.Jid;
*/
public class MamElements {
- public static final String NAMESPACE = "urn:xmpp:mam:1";
+ public static final String NAMESPACE = "urn:xmpp:mam:2";
/**
* MAM result extension class.
diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/MessageRetractionManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/MessageRetractionManager.java
index e5d211161..7fcac31de 100644
--- a/smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/MessageRetractionManager.java
+++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/MessageRetractionManager.java
@@ -102,7 +102,7 @@ public final class MessageRetractionManager extends Manager {
* @param retractedMessageId {@link OriginIdElement OriginID} of the message that the user wants to retract
* @param carrierMessageBuilder message used to transmit the message retraction to the recipient
*/
- public void addRetractionElementToMessage(OriginIdElement retractedMessageId, MessageBuilder carrierMessageBuilder) {
+ public static void addRetractionElementToMessage(OriginIdElement retractedMessageId, MessageBuilder carrierMessageBuilder) {
FasteningElement fasteningElement = FasteningElement.builder()
.setOriginId(retractedMessageId)
.addWrappedPayload(new RetractElement())
diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdManager.java
index d8911aa3e..35242eba9 100644
--- a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdManager.java
+++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdManager.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright 2018 Paul Schaub
+ * Copyright 2018 Paul Schaub, 2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,10 +29,6 @@ import org.jivesoftware.smack.filter.NotFilter;
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.filter.ToTypeFilter;
-import org.jivesoftware.smack.packet.Message;
-import org.jivesoftware.smack.packet.MessageBuilder;
-import org.jivesoftware.smack.util.Consumer;
-import org.jivesoftware.smack.util.Predicate;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.sid.element.OriginIdElement;
@@ -62,14 +58,8 @@ public final class StableUniqueStanzaIdManager extends Manager {
// Filter that filters for messages with an origin id
private static final StanzaFilter ORIGIN_ID_FILTER = new StanzaExtensionFilter(OriginIdElement.ELEMENT, NAMESPACE);
- // Listener for outgoing stanzas that adds origin-ids to outgoing stanzas.
- private static final Consumer ADD_ORIGIN_ID_INTERCEPTOR = mb -> OriginIdElement.addOriginId(mb);
-
// We need a filter for outgoing messages that do not carry an origin-id already.
private static final StanzaFilter ADD_ORIGIN_ID_FILTER = new AndFilter(OUTGOING_FILTER, new NotFilter(ORIGIN_ID_FILTER));
- private static final Predicate ADD_ORIGIN_ID_PREDICATE = m -> {
- return ADD_ORIGIN_ID_FILTER.accept(m);
- };
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@@ -113,7 +103,7 @@ public final class StableUniqueStanzaIdManager extends Manager {
* Start appending origin-id elements to outgoing stanzas and add the feature to disco.
*/
public synchronized void enable() {
- connection().addMessageInterceptor(ADD_ORIGIN_ID_INTERCEPTOR, ADD_ORIGIN_ID_PREDICATE);
+ connection().addMessageInterceptor(OriginIdElement::addTo, ADD_ORIGIN_ID_FILTER::accept);
ServiceDiscoveryManager.getInstanceFor(connection()).addFeature(NAMESPACE);
}
@@ -122,7 +112,7 @@ public final class StableUniqueStanzaIdManager extends Manager {
*/
public synchronized void disable() {
ServiceDiscoveryManager.getInstanceFor(connection()).removeFeature(NAMESPACE);
- connection().removeMessageInterceptor(ADD_ORIGIN_ID_INTERCEPTOR);
+ connection().removeMessageInterceptor(OriginIdElement::addTo);
}
/**
diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java
index b157b40a0..1a448b516 100644
--- a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java
+++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java
@@ -39,7 +39,7 @@ public class OriginIdElement extends StableAndUniqueIdElement {
*
* @param message message.
* @return the added origin-id element.
- * @deprecated use {@link #addOriginId(MessageBuilder)} instead.
+ * @deprecated use {@link #addTo(MessageBuilder)} instead.
*/
@Deprecated
// TODO: Remove in Smack 4.5.
@@ -57,7 +57,7 @@ public class OriginIdElement extends StableAndUniqueIdElement {
* @param messageBuilder the message builder to add an origin ID to.
* @return the added origin-id element.
*/
- public static OriginIdElement addOriginId(MessageBuilder messageBuilder) {
+ public static OriginIdElement addTo(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.
diff --git a/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers b/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers
index a6791cbb7..8e6d3df51 100644
--- a/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers
+++ b/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers
@@ -17,22 +17,22 @@
prefs
- urn:xmpp:mam:1
+ urn:xmpp:mam:2
org.jivesoftware.smackx.mam.provider.MamPrefsIQProvider
query
- urn:xmpp:mam:1
+ urn:xmpp:mam:2
org.jivesoftware.smackx.mam.provider.MamQueryIQProvider
fin
- urn:xmpp:mam:1
+ urn:xmpp:mam:2
org.jivesoftware.smackx.mam.provider.MamFinIQProvider
result
- urn:xmpp:mam:1
+ urn:xmpp:mam:2
org.jivesoftware.smackx.mam.provider.MamResultProvider
diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/fallback_indication/FallbackIndicationTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/fallback_indication/FallbackIndicationTest.java
index 342e783b5..7695ac47d 100644
--- a/smack-experimental/src/test/java/org/jivesoftware/smackx/fallback_indication/FallbackIndicationTest.java
+++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/fallback_indication/FallbackIndicationTest.java
@@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import org.jivesoftware.smack.packet.Message;
-import org.jivesoftware.smack.packet.MessageBuilder;
+import org.jivesoftware.smack.packet.StanzaBuilder;
import org.jivesoftware.smackx.fallback_indication.element.FallbackIndicationElement;
@@ -30,11 +30,11 @@ public class FallbackIndicationTest {
@Test
public void testFallbackIndicationElementFromMessageTest() {
- Message messageWithoutFallback = MessageBuilder.buildMessage()
+ Message messageWithoutFallback = StanzaBuilder.buildMessage()
.build();
assertNull(FallbackIndicationElement.fromMessage(messageWithoutFallback));
- Message messageWithFallback = MessageBuilder.buildMessage()
+ Message messageWithFallback = StanzaBuilder.buildMessage()
.addExtension(new FallbackIndicationElement())
.build();
assertNotNull(FallbackIndicationElement.fromMessage(messageWithFallback));
diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamFinProviderTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamFinProviderTest.java
index f0cd5df68..cbb1b5c1d 100644
--- a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamFinProviderTest.java
+++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamFinProviderTest.java
@@ -34,7 +34,7 @@ import org.junit.jupiter.api.Test;
public class MamFinProviderTest extends MamTest {
- static final String exmapleMamFinXml = ""
+ static final String exmapleMamFinXml = ""
+ "" + "10" + "09af3-cc343-b409f"
+ "" + "";
@@ -56,7 +56,7 @@ public class MamFinProviderTest extends MamTest {
public void checkQueryLimitedResults() throws Exception {
// @formatter:off
final String IQ_LIMITED_RESULTS_EXAMPLE = ""
- + ""
+ + ""
+ ""
+ "23452-4534-1"
+ "390-2342-22" + "16"
diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamPrefIQProviderTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamPrefIQProviderTest.java
index 1c0ff85f8..cd5d4c0ca 100644
--- a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamPrefIQProviderTest.java
+++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamPrefIQProviderTest.java
@@ -33,19 +33,19 @@ import org.jxmpp.jid.Jid;
public class MamPrefIQProviderTest extends MamTest {
- private static final String exampleMamPrefsIQ1 = "" + ""
+ private static final String exampleMamPrefsIQ1 = "" + ""
+ "" + "romeo@montague.lit" + "" + ""
+ "montague@montague.lit" + "" + "" + "";
- private static final String exampleMamPrefsIQ2 = "" + ""
+ private static final String exampleMamPrefsIQ2 = "" + ""
+ "" + "romeo@montague.lit" + "montague@montague.lit" + ""
+ "" + "" + "" + "";
- private static final String exampleMamPrefsIQ3 = "" + "" + ""
+ private static final String exampleMamPrefsIQ3 = "" + "" + ""
+ "";
private static final String exampleMamPrefsResultIQ = ""
- + "" + "" + "romeo@montague.lit"
+ + "" + "" + "romeo@montague.lit"
+ "" + "" + "sarasa@montague.lit" + "montague@montague.lit"
+ "" + "" + "";
diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamQueryIQProviderTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamQueryIQProviderTest.java
index c9f3be99e..eeac45f5e 100644
--- a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamQueryIQProviderTest.java
+++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamQueryIQProviderTest.java
@@ -35,18 +35,18 @@ import org.junit.jupiter.api.Test;
public class MamQueryIQProviderTest {
- private static final String exampleMamQueryIQ1 = "" + ""
+ private static final String exampleMamQueryIQ1 = "" + ""
+ "" + ""
- + "urn:xmpp:mam:1" + ""
+ + "urn:xmpp:mam:2" + ""
+ ""
+ "Where arth thou, my Juliet?" + ""
+ ""
+ "{http://jabber.org/protocol/mood}mood/lonely" + "" + "" + ""
+ "";
- private static final String exampleMamQueryIQ2 = "" + ""
+ private static final String exampleMamQueryIQ2 = "" + ""
+ "" + ""
- + "urn:xmpp:mam:1" + "" + ""
+ + "urn:xmpp:mam:2" + "" + ""
+ "" + ""
+ ""
+ "" + "" + "" + "";
@@ -80,7 +80,7 @@ public class MamQueryIQProviderTest {
assertEquals(dataForm2.getType(), DataForm.Type.form);
List fields2 = dataForm2.getFields();
- assertEquals(fields2.get(0).getValues().get(0).toString(), "urn:xmpp:mam:1");
+ assertEquals(fields2.get(0).getValues().get(0).toString(), "urn:xmpp:mam:2");
assertTrue(fields2.get(0).getValues().size() == 1);
assertEquals(fields2.get(1).getType(), FormField.Type.jid_single);
assertEquals(fields2.get(2).getType(), FormField.Type.text_single);
diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamResultProviderTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamResultProviderTest.java
index 7fbcd7c7e..f7a0a28b4 100644
--- a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamResultProviderTest.java
+++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/MamResultProviderTest.java
@@ -34,7 +34,7 @@ import org.junit.jupiter.api.Test;
public class MamResultProviderTest {
- private static final String exampleMamResultXml = ""
+ private static final String exampleMamResultXml = ""
+ "" + ""
+ ""
@@ -42,7 +42,7 @@ public class MamResultProviderTest {
+ "" + "" + "";
private static final String exampleResultMessage = ""
- + ""
+ + ""
+ "" + ""
+ ""
+ "Hail to thee" + "" + "" + "" + "";
diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/PagingTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/PagingTest.java
index 1f1450efd..9a3a4e61a 100644
--- a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/PagingTest.java
+++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/PagingTest.java
@@ -29,9 +29,9 @@ import org.junit.jupiter.api.Test;
public class PagingTest extends MamTest {
- private static final String pagingStanza = "" + ""
+ private static final String pagingStanza = "" + ""
+ "" + ""
- + "urn:xmpp:mam:1" + "" + "" + ""
+ + "urn:xmpp:mam:2" + "" + "" + ""
+ "10" + "" + "" + "";
@Test
@@ -46,7 +46,7 @@ public class PagingTest extends MamTest {
mamQueryIQ.addExtension(rsmSet);
assertEquals(mamQueryIQ.getDataForm(), dataForm);
- assertEquals(mamQueryIQ.getDataForm().getFields().get(0).getValues().get(0).toString(), "urn:xmpp:mam:1");
+ assertEquals(mamQueryIQ.getDataForm().getFields().get(0).getValues().get(0).toString(), "urn:xmpp:mam:2");
assertEquals(pagingStanza, mamQueryIQ.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/QueryArchiveTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/QueryArchiveTest.java
index 8fe38eeec..1603fb99f 100644
--- a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/QueryArchiveTest.java
+++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/QueryArchiveTest.java
@@ -40,12 +40,12 @@ import org.jxmpp.jid.impl.JidCreate;
public class QueryArchiveTest extends MamTest {
- private static final String mamSimpleQueryIQ = "" + ""
+ private static final String mamSimpleQueryIQ = "" + ""
+ "" + "" + ""
+ MamElements.NAMESPACE + "" + "" + "" + "" + "";
private static final String mamQueryResultExample = ""
- + ""
+ + ""
+ ""
+ "" + ""
+ private static final String resultsLimitStanza = "" + ""
+ "" + "" + ""
+ MamElements.NAMESPACE + "" + "" + "" + ""
+ "10" + "" + "" + "";
diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/message_fastening/MessageFasteningElementsTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/message_fastening/MessageFasteningElementsTest.java
index 8228fccfb..7a36752da 100644
--- a/smack-experimental/src/test/java/org/jivesoftware/smackx/message_fastening/MessageFasteningElementsTest.java
+++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/message_fastening/MessageFasteningElementsTest.java
@@ -29,6 +29,7 @@ import java.util.Arrays;
import org.jivesoftware.smack.packet.MessageBuilder;
import org.jivesoftware.smack.packet.StandardExtensionElement;
+import org.jivesoftware.smack.packet.StanzaBuilder;
import org.jivesoftware.smack.packet.StanzaFactory;
import org.jivesoftware.smack.packet.id.StandardStanzaIdSource;
import org.jivesoftware.smack.parsing.SmackParsingException;
@@ -166,10 +167,10 @@ public class MessageFasteningElementsTest {
@Test
public void hasFasteningElementTest() {
- MessageBuilder messageBuilderWithFasteningElement = MessageBuilder.buildMessage()
+ MessageBuilder messageBuilderWithFasteningElement = StanzaBuilder.buildMessage()
.setBody("Hi!")
.addExtension(FasteningElement.builder().setOriginId("origin-id-1").build());
- MessageBuilder messageBuilderWithoutFasteningElement = MessageBuilder.buildMessage()
+ MessageBuilder messageBuilderWithoutFasteningElement = StanzaBuilder.buildMessage()
.setBody("Ho!");
assertTrue(FasteningElement.hasFasteningElement(messageBuilderWithFasteningElement));
diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdTest.java
index c9c4367a8..a95e5caac 100644
--- a/smack-experimental/src/test/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdTest.java
+++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/sid/StableUniqueStanzaIdTest.java
@@ -78,7 +78,7 @@ public class StableUniqueStanzaIdTest extends SmackTestSuite {
assertFalse(OriginIdElement.hasOriginId(message));
assertFalse(StanzaIdElement.hasStanzaId(message));
- OriginIdElement.addOriginId(messageBuilder);
+ OriginIdElement.addTo(messageBuilder);
message = messageBuilder.build();
assertTrue(OriginIdElement.hasOriginId(message));
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java
index d7ee5b45a..c63471bcb 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java
@@ -33,8 +33,6 @@ import java.util.SortedSet;
import java.util.TreeSet;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.ConnectionListener;
@@ -51,13 +49,11 @@ import org.jivesoftware.smack.filter.PresenceTypeFilter;
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.filter.StanzaTypeFilter;
-import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.PresenceBuilder;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.roster.AbstractPresenceEventListener;
import org.jivesoftware.smack.roster.Roster;
-import org.jivesoftware.smack.util.Consumer;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.stringencoder.Base64;
@@ -87,7 +83,6 @@ import org.jxmpp.util.cache.LruCache;
* @see XEP-0115: Entity Capabilities
*/
public final class EntityCapsManager extends Manager {
- private static final Logger LOGGER = Logger.getLogger(EntityCapsManager.class.getName());
public static final String NAMESPACE = CapsExtension.NAMESPACE;
public static final String ELEMENT = CapsExtension.ELEMENT;
@@ -307,7 +302,6 @@ public final class EntityCapsManager extends Manager {
private boolean entityCapsEnabled;
private CapsVersionAndHash currentCapsVersion;
- private volatile Presence presenceSend;
/**
* The entity node String used by this EntityCapsManager instance.
@@ -317,11 +311,11 @@ public final class EntityCapsManager extends Manager {
// Intercept presence packages and add caps data when intended.
// XEP-0115 specifies that a client SHOULD include entity capabilities
// with every presence notification it sends.
- private final Consumer presenceInterceptor = presenceBuilder -> {
+ private void addCapsExtension(PresenceBuilder presenceBuilder) {
CapsVersionAndHash capsVersionAndHash = getCapsVersionAndHash();
CapsExtension caps = new CapsExtension(entityNode, capsVersionAndHash.version, capsVersionAndHash.hash);
presenceBuilder.overrideExtension(caps);
- };
+ }
private EntityCapsManager(XMPPConnection connection) {
super(connection);
@@ -342,11 +336,6 @@ public final class EntityCapsManager extends Manager {
// feature, so we try to process it after we are connected and
// once after we are authenticated.
processCapsStreamFeatureIfAvailable(connection);
-
- // Reset presenceSend when the connection was not resumed
- if (!resumed) {
- presenceSend = null;
- }
}
private void processCapsStreamFeatureIfAvailable(XMPPConnection connection) {
CapsExtension capsExtension = connection.getFeature(
@@ -359,9 +348,6 @@ public final class EntityCapsManager extends Manager {
}
});
- // This calculates the local entity caps version
- updateLocalEntityCaps();
-
if (autoEnableEntityCaps)
enableEntityCaps();
@@ -387,26 +373,16 @@ public final class EntityCapsManager extends Manager {
}
});
- connection.addStanzaSendingListener(new StanzaListener() {
- @Override
- public void processStanza(Stanza packet) {
- presenceSend = (Presence) packet;
- }
- }, PresenceTypeFilter.OUTGOING_PRESENCE_BROADCAST);
-
-
- enableEntityCaps();
-
// It's important to do this as last action. Since it changes the
// behavior of the SDM in some ways
sdm.addEntityCapabilitiesChangedListener(new EntityCapabilitiesChangedListener() {
@Override
- public void onEntityCapailitiesChanged() {
+ public void onEntityCapabilitiesChanged(DiscoverInfo synthesizedDiscoveryInfo) {
if (!entityCapsEnabled()) {
return;
}
- updateLocalEntityCaps();
+ updateLocalEntityCaps(synthesizedDiscoveryInfo);
}
});
}
@@ -425,13 +401,12 @@ public final class EntityCapsManager extends Manager {
}
public synchronized void enableEntityCaps() {
- connection().addPresenceInterceptor(presenceInterceptor, p -> {
+ connection().addPresenceInterceptor(this::addCapsExtension, p -> {
return PresenceTypeFilter.AVAILABLE.accept(p);
});
// Add Entity Capabilities (XEP-0115) feature node.
sdm.addFeature(NAMESPACE);
- updateLocalEntityCaps();
entityCapsEnabled = true;
}
@@ -439,18 +414,13 @@ public final class EntityCapsManager extends Manager {
entityCapsEnabled = false;
sdm.removeFeature(NAMESPACE);
- connection().removePresenceInterceptor(presenceInterceptor);
+ connection().removePresenceInterceptor(this::addCapsExtension);
}
public boolean entityCapsEnabled() {
return entityCapsEnabled;
}
- public void setEntityNode(String entityNode) {
- this.entityNode = entityNode;
- updateLocalEntityCaps();
- }
-
/**
* Remove a record telling what entity caps node a user has.
*
@@ -522,13 +492,10 @@ public final class EntityCapsManager extends Manager {
* presence is send to inform others about your new Entity Caps node string.
*
*/
- private void updateLocalEntityCaps() {
+ private void updateLocalEntityCaps(DiscoverInfo synthesizedDiscoveryInfo) {
XMPPConnection connection = connection();
- DiscoverInfoBuilder discoverInfoBuilder = DiscoverInfo.builder("synthetized-disco-info-response")
- .ofType(IQ.Type.result);
- sdm.addDiscoverInfoTo(discoverInfoBuilder);
-
+ DiscoverInfoBuilder discoverInfoBuilder = synthesizedDiscoveryInfo.asBuilder("synthesized-disco-info-result");
// getLocalNodeVer() will return a result only after currentCapsVersion is set. Therefore
// set it first and then call getLocalNodeVer()
currentCapsVersion = generateVerificationString(discoverInfoBuilder);
@@ -564,20 +531,6 @@ public final class EntityCapsManager extends Manager {
return packetExtensions;
}
});
-
- // Re-send the last sent presence, and let the stanza interceptor
- // add a node to it.
- // See http://xmpp.org/extensions/xep-0115.html#advertise
- // We only send a presence packet if there was already one send
- // to respect ConnectionConfiguration.isSendPresence()
- if (connection != null && connection.isAuthenticated() && presenceSend != null) {
- try {
- connection.sendStanza(presenceSend.cloneWithNewId());
- }
- catch (InterruptedException | NotConnectedException e) {
- LOGGER.log(Level.WARNING, "Could could not update presence with caps info", e);
- }
- }
}
/**
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java
index 0f4614181..c2627dd5b 100755
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java
@@ -517,7 +517,7 @@ public final class AdHocCommandManager extends Manager {
private boolean sessionSweeperScheduled;
- private final Runnable sessionSweeper = () -> {
+ private void sessionSweeper() {
final long currentTime = System.currentTimeMillis();
synchronized (this) {
for (Iterator> it = executingCommands.entrySet().iterator(); it.hasNext();) {
@@ -553,7 +553,7 @@ public final class AdHocCommandManager extends Manager {
}
sessionSweeperScheduled = true;
- schedule(sessionSweeper, 10, TimeUnit.SECONDS);
+ schedule(this::sessionSweeper, 10, TimeUnit.SECONDS);
}
/**
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/EntityCapabilitiesChangedListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/EntityCapabilitiesChangedListener.java
index e075117f2..bb790813f 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/EntityCapabilitiesChangedListener.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/EntityCapabilitiesChangedListener.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright 2018 Florian Schmaus.
+ * Copyright 2018-2020 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,10 @@
*/
package org.jivesoftware.smackx.disco;
+import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
+
public interface EntityCapabilitiesChangedListener {
- void onEntityCapailitiesChanged();
+ void onEntityCapabilitiesChanged(DiscoverInfo synthesizedDiscoveryInfo);
}
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java
index 84b529aad..61103d2ee 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java
@@ -16,6 +16,7 @@
*/
package org.jivesoftware.smackx.disco;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -28,20 +29,30 @@ import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.jivesoftware.smack.ConnectionCreationListener;
+import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.Manager;
+import org.jivesoftware.smack.ScheduledAction;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
+import org.jivesoftware.smack.filter.PresenceTypeFilter;
+import org.jivesoftware.smack.internal.AbstractStats;
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.StanzaError;
import org.jivesoftware.smack.util.CollectionUtil;
+import org.jivesoftware.smack.util.ExtendedAppendable;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.StringUtils;
@@ -71,6 +82,8 @@ import org.jxmpp.util.cache.ExpirationCache;
*/
public final class ServiceDiscoveryManager extends Manager {
+ private static final Logger LOGGER = Logger.getLogger(ServiceDiscoveryManager.class.getName());
+
private static final String DEFAULT_IDENTITY_NAME = "Smack";
private static final String DEFAULT_IDENTITY_CATEGORY = "client";
private static final String DEFAULT_IDENTITY_TYPE = "pc";
@@ -91,6 +104,8 @@ public final class ServiceDiscoveryManager extends Manager {
private List extendedInfos = new ArrayList<>(2);
private final Map nodeInformationProviders = new ConcurrentHashMap<>();
+ private volatile Presence presenceSend;
+
// Create a new ServiceDiscoveryManager on every established connection
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@@ -190,6 +205,18 @@ public final class ServiceDiscoveryManager extends Manager {
return response;
}
});
+
+ connection.addConnectionListener(new ConnectionListener() {
+ @Override
+ public void authenticated(XMPPConnection connection, boolean resumed) {
+ // Reset presenceSend when the connection was not resumed
+ if (!resumed) {
+ presenceSend = null;
+ }
+ }
+ });
+ connection.addStanzaSendingListener(p -> presenceSend = (Presence) p,
+ PresenceTypeFilter.OUTGOING_PRESENCE_BROADCAST);
}
/**
@@ -894,13 +921,55 @@ public final class ServiceDiscoveryManager extends Manager {
return entityCapabilitiesChangedListeners.add(entityCapabilitiesChangedListener);
}
+ private static final int RENEW_ENTITY_CAPS_DELAY_MILLIS = 25;
+
+ private ScheduledAction renewEntityCapsScheduledAction;
+
+ private final AtomicInteger renewEntityCapsPerformed = new AtomicInteger();
+ private int renewEntityCapsRequested = 0;
+ private int scheduledRenewEntityCapsAvoided = 0;
+
/**
* Notify the {@link EntityCapabilitiesChangedListener} about changed capabilities.
*/
- private void renewEntityCapsVersion() {
- for (EntityCapabilitiesChangedListener entityCapabilitiesChangedListener : entityCapabilitiesChangedListeners) {
- entityCapabilitiesChangedListener.onEntityCapailitiesChanged();
+ private synchronized void renewEntityCapsVersion() {
+ renewEntityCapsRequested++;
+ if (renewEntityCapsScheduledAction != null) {
+ boolean canceled = renewEntityCapsScheduledAction.cancel();
+ if (canceled) {
+ scheduledRenewEntityCapsAvoided++;
+ }
}
+
+ final XMPPConnection connection = connection();
+
+ renewEntityCapsScheduledAction = scheduleBlocking(() -> {
+ renewEntityCapsPerformed.incrementAndGet();
+
+ DiscoverInfoBuilder discoverInfoBuilder = DiscoverInfo.builder("synthetized-disco-info-response")
+ .ofType(IQ.Type.result);
+ addDiscoverInfoTo(discoverInfoBuilder);
+ DiscoverInfo synthesizedDiscoveryInfo = discoverInfoBuilder.build();
+
+ for (EntityCapabilitiesChangedListener entityCapabilitiesChangedListener : entityCapabilitiesChangedListeners) {
+ entityCapabilitiesChangedListener.onEntityCapabilitiesChanged(synthesizedDiscoveryInfo);
+ }
+
+ // Re-send the last sent presence, and let the stanza interceptor
+ // add a node to it.
+ // See http://xmpp.org/extensions/xep-0115.html#advertise
+ // We only send a presence packet if there was already one send
+ // to respect ConnectionConfiguration.isSendPresence()
+ final Presence presenceSend = this.presenceSend;
+ if (connection.isAuthenticated() && presenceSend != null) {
+ try {
+ connection.sendStanza(presenceSend.cloneWithNewId());
+ }
+ catch (InterruptedException | NotConnectedException e) {
+ LOGGER.log(Level.WARNING, "Could could not update presence with caps info", e);
+ }
+ }
+ }, RENEW_ENTITY_CAPS_DELAY_MILLIS, TimeUnit.MILLISECONDS);
}
public static void addDiscoInfoLookupShortcutMechanism(DiscoInfoLookupShortcutMechanism discoInfoLookupShortcutMechanism) {
@@ -915,4 +984,30 @@ public final class ServiceDiscoveryManager extends Manager {
discoInfoLookupShortcutMechanisms.remove(discoInfoLookupShortcutMechanism);
}
}
+
+ public synchronized Stats getStats() {
+ return new Stats(this);
+ }
+
+ public static final class Stats extends AbstractStats {
+
+ public final int renewEntityCapsRequested;
+ public final int renewEntityCapsPerformed;
+ public final int scheduledRenewEntityCapsAvoided;
+
+ private Stats(ServiceDiscoveryManager serviceDiscoveryManager) {
+ renewEntityCapsRequested = serviceDiscoveryManager.renewEntityCapsRequested;
+ renewEntityCapsPerformed = serviceDiscoveryManager.renewEntityCapsPerformed.get();
+ scheduledRenewEntityCapsAvoided = serviceDiscoveryManager.scheduledRenewEntityCapsAvoided;
+ }
+
+ @Override
+ public void appendStatsTo(ExtendedAppendable appendable) throws IOException {
+ StringUtils.appendHeading(appendable, "ServiceDiscoveryManager stats", '#').append('\n');
+ appendable.append("renew-entitycaps-requested: ").append(renewEntityCapsRequested).append('\n');
+ appendable.append("renew-entitycaps-performed: ").append(renewEntityCapsPerformed).append('\n');
+ appendable.append("scheduled-renew-entitycaps-avoided: ").append(scheduledRenewEntityCapsAvoided).append('\n');
+ }
+
+ }
}
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java
index 796e51857..7de48f1be 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java
@@ -299,8 +299,8 @@ public class DiscoverInfo extends IQ implements DiscoverInfoView, TypedCloneable
return containsDuplicateFeatures;
}
- public DiscoverInfoBuilder asBuilder() {
- return new DiscoverInfoBuilder(this);
+ public DiscoverInfoBuilder asBuilder(String stanzaId) {
+ return new DiscoverInfoBuilder(this, stanzaId);
}
// TODO: Deprecate in favor of asBuilder().
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfoBuilder.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfoBuilder.java
index 66f965de4..b8e179c70 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfoBuilder.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfoBuilder.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright 2019 Florian Schmaus
+ * Copyright 2019-2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,8 +48,8 @@ public class DiscoverInfoBuilder extends IqBuilder AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER = mb -> DeliveryReceiptRequest.addTo(mb);
-
/**
* Enables automatic requests of delivery receipts for outgoing messages of
* {@link org.jivesoftware.smack.packet.Message.Type#normal}, {@link org.jivesoftware.smack.packet.Message.Type#chat} or {@link org.jivesoftware.smack.packet.Message.Type#headline}, and
@@ -284,7 +280,7 @@ public final class DeliveryReceiptManager extends Manager {
* @see #dontAutoAddDeliveryReceiptRequests()
*/
public void autoAddDeliveryReceiptRequests() {
- connection().addMessageInterceptor(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER, m -> {
+ connection().addMessageInterceptor(DeliveryReceiptRequest::addTo, m -> {
return MESSAGES_TO_REQUEST_RECEIPTS_FOR.accept(m);
});
}
@@ -296,7 +292,7 @@ public final class DeliveryReceiptManager extends Manager {
* @see #autoAddDeliveryReceiptRequests()
*/
public void dontAutoAddDeliveryReceiptRequests() {
- connection().removeMessageInterceptor(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER);
+ connection().removeMessageInterceptor(DeliveryReceiptRequest::addTo);
}
/**
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/softwareinfo/SoftwareInfoManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/softwareinfo/SoftwareInfoManager.java
index 11af9b810..b6c05922e 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/softwareinfo/SoftwareInfoManager.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/softwareinfo/SoftwareInfoManager.java
@@ -16,18 +16,14 @@
*/
package org.jivesoftware.smackx.softwareinfo;
-import java.io.IOException;
import java.util.Map;
import java.util.WeakHashMap;
import org.jivesoftware.smack.Manager;
-import org.jivesoftware.smack.SmackException.FeatureNotSupportedException;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
-import org.jivesoftware.smack.parsing.SmackParsingException;
-import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
import org.jivesoftware.smackx.softwareinfo.form.SoftwareInfoForm;
@@ -44,11 +40,11 @@ import org.jxmpp.jid.Jid;
*/
public final class SoftwareInfoManager extends Manager {
- private static final String FEATURE = "http://jabber.org/protocol/disco";
private static final Map INSTANCES = new WeakHashMap<>();
+
private final ServiceDiscoveryManager serviceDiscoveryManager;
- public static synchronized SoftwareInfoManager getInstanceFor (XMPPConnection connection) throws IOException, XmlPullParserException, SmackParsingException {
+ public static synchronized SoftwareInfoManager getInstanceFor (XMPPConnection connection) {
SoftwareInfoManager manager = INSTANCES.get(connection);
if (manager == null) {
manager = new SoftwareInfoManager(connection);
@@ -57,25 +53,11 @@ public final class SoftwareInfoManager extends Manager {
return manager;
}
- private SoftwareInfoManager(XMPPConnection connection) throws IOException, XmlPullParserException, SmackParsingException {
+ private SoftwareInfoManager(XMPPConnection connection) {
super(connection);
serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
}
- /**
- * Returns true if the feature is supported by the Jid.
- *
- * @param jid Jid to be checked for support
- * @return boolean
- * @throws NoResponseException if there was no response from the remote entity
- * @throws XMPPErrorException if there was an XMPP error returned
- * @throws NotConnectedException if the XMPP connection is not connected
- * @throws InterruptedException if the calling thread was interrupted
- */
- public boolean isSupported(Jid jid) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
- return serviceDiscoveryManager.supportsFeatures(jid, FEATURE);
- }
-
/**
* Publishes the provided {@link SoftwareInfoForm} as an extended info.
*
@@ -86,20 +68,16 @@ public final class SoftwareInfoManager extends Manager {
}
/**
- * Get SoftwareInfoForm from Jid provided.
- *
+ * Get Software Information from the provided XMPP address. Returns null
in case the queried entity does not announce that information.
+ *
* @param jid jid to get software information from
- * @return {@link SoftwareInfoForm} Form containing software information
+ * @return {@link SoftwareInfoForm} Form containing software information or null
.
* @throws NoResponseException if there was no response from the remote entity
* @throws XMPPErrorException if there was an XMPP error returned
* @throws NotConnectedException if the XMPP connection is not connected
* @throws InterruptedException if the calling thread was interrupted
- * @throws FeatureNotSupportedException if the feature is not supported
*/
- public SoftwareInfoForm fromJid(Jid jid) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, FeatureNotSupportedException {
- if (!isSupported(jid)) {
- throw new FeatureNotSupportedException(SoftwareInfoForm.FORM_TYPE, jid);
- }
+ public SoftwareInfoForm fromJid(Jid jid) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
DiscoverInfo discoverInfo = serviceDiscoveryManager.discoverInfo(jid);
DataForm dataForm = DataForm.from(discoverInfo, SoftwareInfoForm.FORM_TYPE);
if (dataForm == null) {
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/element/UserTuneElement.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/element/UserTuneElement.java
index 36daa66af..a564f5331 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/element/UserTuneElement.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/element/UserTuneElement.java
@@ -186,8 +186,8 @@ public final class UserTuneElement implements ExtensionElement {
/**
* Artist is an optional element in UserTuneElement.
- * @param artist.
- * @return builder.
+ * @param artist the artist.
+ * @return a reference to this builder.
*/
public Builder setArtist(String artist) {
this.artist = artist;
@@ -196,8 +196,8 @@ public final class UserTuneElement implements ExtensionElement {
/**
* Length is an optional element in UserTuneElement.
- * @param length.
- * @return builder.
+ * @param length the length.
+ * @return a reference to this builder.
*/
public Builder setLength(int length) {
return setLength(UInt16.from(length));
@@ -205,8 +205,8 @@ public final class UserTuneElement implements ExtensionElement {
/**
* Length is an optional element in UserTuneElement.
- * @param length.
- * @return builder.
+ * @param length the length.
+ * @return a reference to this builder.
*/
public Builder setLength(UInt16 length) {
this.length = length;
@@ -215,8 +215,8 @@ public final class UserTuneElement implements ExtensionElement {
/**
* Rating is an optional element in UserTuneElement.
- * @param rating.
- * @return builder.
+ * @param rating the rating.
+ * @return a reference to this builder.
*/
public Builder setRating(int rating) {
this.rating = rating;
@@ -225,8 +225,8 @@ public final class UserTuneElement implements ExtensionElement {
/**
* Source is an optional element in UserTuneElement.
- * @param source.
- * @return builder.
+ * @param source the source.
+ * @return a reference to this builder.
*/
public Builder setSource(String source) {
this.source = source;
@@ -235,8 +235,8 @@ public final class UserTuneElement implements ExtensionElement {
/**
* Title is an optional element in UserTuneElement.
- * @param title.
- * @return builder.
+ * @param title the title.
+ * @return a reference to this builder.
*/
public Builder setTitle(String title) {
this.title = title;
@@ -245,8 +245,8 @@ public final class UserTuneElement implements ExtensionElement {
/**
* Track is an optional element in UserTuneElement.
- * @param track.
- * @return builder.
+ * @param track the track.
+ * @return a reference to this builder.
*/
public Builder setTrack(String track) {
this.track = track;
@@ -255,8 +255,8 @@ public final class UserTuneElement implements ExtensionElement {
/**
* URI is an optional element in UserTuneElement.
- * @param uri.
- * @return builder.
+ * @param uri the URI.
+ * @return a reference to this builder.
*/
public Builder setUri(URI uri) {
this.uri = uri;
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/XHTMLManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/XHTMLManager.java
index de2def875..695af1124 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/XHTMLManager.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/XHTMLManager.java
@@ -26,6 +26,8 @@ import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.packet.Message;
+import org.jivesoftware.smack.packet.MessageBuilder;
+import org.jivesoftware.smack.packet.MessageView;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.xhtmlim.packet.XHTMLExtension;
@@ -57,7 +59,7 @@ public class XHTMLManager {
* @param message an XHTML message
* @return an Iterator for the bodies in the message or null if none.
*/
- public static List getBodies(Message message) {
+ public static List getBodies(MessageView message) {
XHTMLExtension xhtmlExtension = XHTMLExtension.from(message);
if (xhtmlExtension != null)
return xhtmlExtension.getBodies();
@@ -68,9 +70,29 @@ public class XHTMLManager {
/**
* Adds an XHTML body to the message.
*
- * @param message the message that will receive the XHTML body
+ * @param messageBuilder the message that will receive the XHTML body
* @param xhtmlText the string to add as an XHTML body to the message
*/
+ public static void addBody(MessageBuilder messageBuilder, XHTMLText xhtmlText) {
+ XHTMLExtension xhtmlExtension = XHTMLExtension.from(messageBuilder);
+ if (xhtmlExtension == null) {
+ // Create an XHTMLExtension and add it to the message
+ xhtmlExtension = new XHTMLExtension();
+ messageBuilder.addExtension(xhtmlExtension);
+ }
+ // Add the required bodies to the message
+ xhtmlExtension.addBody(xhtmlText.toXML());
+ }
+
+ /**
+ * Adds an XHTML body to the message.
+ *
+ * @param message the message that will receive the XHTML body
+ * @param xhtmlText the string to add as an XHTML body to the message
+ * @deprecated use {@link #addBody(MessageBuilder, XHTMLText)} instead.
+ */
+ // TODO: Remove in Smack 4.6
+ @Deprecated
public static void addBody(Message message, XHTMLText xhtmlText) {
XHTMLExtension xhtmlExtension = XHTMLExtension.from(message);
if (xhtmlExtension == null) {
diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ProxyTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ProxyTest.java
index 99dd32d22..b72c35b69 100644
--- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ProxyTest.java
+++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ProxyTest.java
@@ -86,7 +86,7 @@ public class Socks5ProxyTest {
* When inserting new network addresses to the proxy the order should remain in the order they
* were inserted.
*
- * @throws UnknownHostException
+ * @throws UnknownHostException if unknown host.
*/
@Test
public void shouldPreserveAddressOrderOnInsertions() throws UnknownHostException {
@@ -114,7 +114,7 @@ public class Socks5ProxyTest {
* When replacing network addresses of the proxy the order should remain in the order if the
* given list.
*
- * @throws UnknownHostException
+ * @throws UnknownHostException if unknown host.
*/
@Test
public void shouldPreserveAddressOrderOnReplace() throws UnknownHostException {
diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/xdatavalidation/DataValidationHelperTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/xdatavalidation/DataValidationHelperTest.java
index a12effdb6..42f08f499 100644
--- a/smack-extensions/src/test/java/org/jivesoftware/smackx/xdatavalidation/DataValidationHelperTest.java
+++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/xdatavalidation/DataValidationHelperTest.java
@@ -44,9 +44,8 @@ public class DataValidationHelperTest {
() -> element.checkConsistency(field));
assertEquals("Field type 'jid-single' is not consistent with validation method 'basic'.", vce.getMessage());
- IllegalArgumentException iae = assertThrows(IllegalArgumentException.class,
+ assertThrows(IllegalArgumentException.class,
() -> new ListRange(-1L, 1L));
- assertEquals("unsigned 32-bit integers can't be negative", iae.getMessage());
element.setListRange(new ListRange(10L, 100L));
vce = assertThrows(ValidationConsistencyException.class, () -> element.checkConsistency(field));
diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStore.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStore.java
index dec89bc68..a78a44c28 100644
--- a/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStore.java
+++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStore.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright 2013-2015 the original author or authors
+ * Copyright 2013-2015 the original author or authors, 2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
package org.jivesoftware.smack.roster.rosterstore;
import java.io.File;
-import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
@@ -56,15 +55,10 @@ public final class DirectoryRosterStore implements RosterStore {
private static final String STORE_ID = "DEFAULT_ROSTER_STORE";
private static final Logger LOGGER = Logger.getLogger(DirectoryRosterStore.class.getName());
- private static final FileFilter rosterDirFilter = new FileFilter() {
-
- @Override
- public boolean accept(File file) {
- String name = file.getName();
- return name.startsWith(ENTRY_PREFIX);
- }
-
- };
+ private static boolean rosterDirFilter(File file) {
+ String name = file.getName();
+ return name.startsWith(ENTRY_PREFIX);
+ }
/**
* @param baseDir TODO javadoc me please
@@ -122,7 +116,7 @@ public final class DirectoryRosterStore implements RosterStore {
public List- getEntries() {
List
- entries = new ArrayList<>();
- for (File file : fileDir.listFiles(rosterDirFilter)) {
+ for (File file : fileDir.listFiles(DirectoryRosterStore::rosterDirFilter)) {
Item entry = readEntry(file);
if (entry == null) {
// Roster directory store corrupt. Abort and signal this by returning null.
@@ -168,7 +162,7 @@ public final class DirectoryRosterStore implements RosterStore {
@Override
public boolean resetEntries(Collection
- items, String version) {
- for (File file : fileDir.listFiles(rosterDirFilter)) {
+ for (File file : fileDir.listFiles(DirectoryRosterStore::rosterDirFilter)) {
file.delete();
}
for (Item item : items) {
diff --git a/smack-im/src/test/java/org/jivesoftware/smack/roster/RosterTest.java b/smack-im/src/test/java/org/jivesoftware/smack/roster/RosterTest.java
index 8bd98748c..adb75cb09 100644
--- a/smack-im/src/test/java/org/jivesoftware/smack/roster/RosterTest.java
+++ b/smack-im/src/test/java/org/jivesoftware/smack/roster/RosterTest.java
@@ -95,6 +95,8 @@ public class RosterTest extends InitSmackIm {
* Test a simple roster initialization according to the example in
* RFC3921: Retrieving One's Roster on Login.
+ *
+ * @throws Exception in case of an exception.
*/
@Test
public void testSimpleRosterInitialization() throws Exception {
@@ -131,6 +133,8 @@ public class RosterTest extends InitSmackIm {
* Test adding a roster item according to the example in
* RFC3921: Adding a Roster Item.
+ *
+ * @throws Throwable in case a throwable is thrown.
*/
@Test
public void testAddRosterItem() throws Throwable {
@@ -203,6 +207,8 @@ public class RosterTest extends InitSmackIm {
* Test updating a roster item according to the example in
* RFC3921: Updating a Roster Item.
+ *
+ * @throws Throwable in case a throwable is thrown.
*/
@Test
public void testUpdateRosterItem() throws Throwable {
@@ -279,6 +285,7 @@ public class RosterTest extends InitSmackIm {
* Test deleting a roster item according to the example in
* RFC3921: Deleting a Roster Item.
+ * @throws Throwable if throwable is thrown.
*/
@Test
public void testDeleteRosterItem() throws Throwable {
@@ -327,6 +334,7 @@ public class RosterTest extends InitSmackIm {
* Test a simple roster push according to the example in
* RFC3921bis-03: Roster Push.
+ * @throws Throwable in case a throwable is thrown.
*/
@Test
public void testSimpleRosterPush() throws Throwable {
@@ -398,6 +406,7 @@ public class RosterTest extends InitSmackIm {
* Test if adding an user with an empty group is equivalent with providing
* no group.
*
+ * @throws Throwable in case a throwable is thrown.
* @see SMACK-294
*/
@Test(timeout = 5000)
@@ -466,6 +475,7 @@ public class RosterTest extends InitSmackIm {
* Test processing a roster push with an empty group is equivalent with providing
* no group.
*
+ * @throws Throwable in case a throwable is thrown.
* @see SMACK-294
*/
@Test
diff --git a/smack-im/src/test/java/org/jivesoftware/smack/roster/RosterVersioningTest.java b/smack-im/src/test/java/org/jivesoftware/smack/roster/RosterVersioningTest.java
index 91be648ed..aa2a51687 100644
--- a/smack-im/src/test/java/org/jivesoftware/smack/roster/RosterVersioningTest.java
+++ b/smack-im/src/test/java/org/jivesoftware/smack/roster/RosterVersioningTest.java
@@ -97,6 +97,8 @@ public class RosterVersioningTest {
* by all entries of the roster store.
* @throws SmackException if Smack detected an exceptional situation.
* @throws XMPPException if an XMPP protocol error was received.
+ * @throws InterruptedException if interrupted.
+ * @throws IOException if IO exception.
*/
@Test(timeout = 300000)
public void testEqualVersionStored() throws InterruptedException, IOException, XMPPException, SmackException {
@@ -172,6 +174,7 @@ public class RosterVersioningTest {
/**
* Test roster versioning with roster pushes.
+ * @throws Throwable in case a throwable is thrown.
*/
@SuppressWarnings("UndefinedEquals")
@Test(timeout = 5000)
diff --git a/smack-im/src/test/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStoreTest.java b/smack-im/src/test/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStoreTest.java
index bf116b874..9dc9ba3c7 100644
--- a/smack-im/src/test/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStoreTest.java
+++ b/smack-im/src/test/java/org/jivesoftware/smack/roster/rosterstore/DirectoryRosterStoreTest.java
@@ -57,6 +57,7 @@ public class DirectoryRosterStoreTest {
/**
* Tests that opening an uninitialized directory fails.
+ * @throws IOException if IO exception.
*/
@Test
public void testStoreUninitialized() throws IOException {
@@ -66,6 +67,7 @@ public class DirectoryRosterStoreTest {
/**
* Tests that an initialized directory is empty.
+ * @throws IOException if IO exception.
*/
@Test
public void testStoreInitializedEmpty() throws IOException {
@@ -80,6 +82,7 @@ public class DirectoryRosterStoreTest {
/**
* Tests adding and removing entries.
+ * @throws IOException if IO exception.
*/
@Test
public void testStoreAddRemove() throws IOException {
diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntTest.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntTest.java
index 2bdb340bd..2b94b2190 100644
--- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntTest.java
+++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntTest.java
@@ -84,9 +84,9 @@ public abstract class AbstractSmackIntTest {
protected HttpURLConnection getHttpUrlConnectionFor(URL url) throws IOException {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
- if (sinttestConfiguration.tlsContext != null && urlConnection instanceof HttpsURLConnection) {
+ if (sinttestConfiguration.sslContextFactory != null && urlConnection instanceof HttpsURLConnection) {
HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) urlConnection;
- httpsUrlConnection.setSSLSocketFactory(sinttestConfiguration.tlsContext.getSocketFactory());
+ httpsUrlConnection.setSSLSocketFactory(sinttestConfiguration.sslContextFactory.createSslContext().getSocketFactory());
}
return urlConnection;
}
diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntegrationTest.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntegrationTest.java
index befb94c08..593d5b847 100644
--- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntegrationTest.java
+++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntegrationTest.java
@@ -20,7 +20,15 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.XMPPConnection;
+import org.jivesoftware.smack.filter.AndFilter;
+import org.jivesoftware.smack.filter.FromMatchesFilter;
+import org.jivesoftware.smack.filter.PresenceTypeFilter;
+import org.jivesoftware.smack.packet.Stanza;
+import org.jivesoftware.smack.util.Async.ThrowingRunnable;
+
+import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
public abstract class AbstractSmackIntegrationTest extends AbstractSmackIntTest {
@@ -58,4 +66,48 @@ public abstract class AbstractSmackIntegrationTest extends AbstractSmackIntTest
connectionsLocal.add(conThree);
this.connections = Collections.unmodifiableList(connectionsLocal);
}
+
+ /**
+ * Perform action and wait until conA observes a presence form conB.
+ *
+ * This method is usually used so that 'action' performs an operation that changes one entities
+ * features/nodes/capabilities, and we want to check that another connection is able to observe this change, and use
+ * that new "thing" that was added to the connection.
+ *
+ *
+ * Note that this method is a workaround at best and not reliable. Because it is not guaranteed that any XEP-0030
+ * related manager, e.g. EntityCapsManager, already processed the presence when this method returns.
+ *
+ * TODO: Come up with a better solution.
+ *
+ * @param conA the connection to observe the presence on.
+ * @param conB the connection sending the presence
+ * @param action the action to perform.
+ * @throws Exception in case of an exception.
+ */
+ protected void performActionAndWaitForPresence(XMPPConnection conA, XMPPConnection conB, ThrowingRunnable action)
+ throws Exception {
+ final SimpleResultSyncPoint presenceReceivedSyncPoint = new SimpleResultSyncPoint();
+ final StanzaListener presenceListener = new StanzaListener() {
+ @Override
+ public void processStanza(Stanza packet) {
+ presenceReceivedSyncPoint.signal();
+ }
+ };
+
+ // Add a stanzaListener to listen for incoming presence
+ conA.addAsyncStanzaListener(presenceListener, new AndFilter(
+ PresenceTypeFilter.AVAILABLE,
+ FromMatchesFilter.create(conB.getUser())
+ ));
+
+ action.runOrThrow();
+
+ try {
+ // wait for the dummy feature to get sent via presence
+ presenceReceivedSyncPoint.waitForResult(timeout);
+ } finally {
+ conA.removeAsyncStanzaListener(presenceListener);
+ }
+ }
}
diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/Configuration.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/Configuration.java
index 258fb3c1f..9f5c32633 100644
--- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/Configuration.java
+++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/Configuration.java
@@ -36,6 +36,7 @@ import org.jivesoftware.smack.debugger.ConsoleDebugger;
import org.jivesoftware.smack.util.Function;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.ParserUtils;
+import org.jivesoftware.smack.util.SslContextFactory;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.debugger.EnhancedDebugger;
@@ -72,7 +73,7 @@ public final class Configuration {
public final String serviceTlsPin;
- public final SSLContext tlsContext;
+ public final SslContextFactory sslContextFactory;
public final SecurityMode securityMode;
@@ -121,9 +122,10 @@ public final class Configuration {
"'service' must be set. Either via 'properties' files or via system property 'sinttest.service'.");
serviceTlsPin = builder.serviceTlsPin;
if (serviceTlsPin != null) {
- tlsContext = Java7Pinning.forPin(serviceTlsPin);
+ SSLContext sslContext = Java7Pinning.forPin(serviceTlsPin);
+ sslContextFactory = () -> sslContext;
} else {
- tlsContext = null;
+ sslContextFactory = null;
}
securityMode = builder.securityMode;
if (builder.replyTimeout > 0) {
@@ -168,8 +170,8 @@ public final class Configuration {
this.testPackages = builder.testPackages;
this.configurationApplier = b -> {
- if (tlsContext != null) {
- b.setCustomSSLContext(tlsContext);
+ if (sslContextFactory != null) {
+ b.setSslContextFactory(sslContextFactory);
}
b.setSecurityMode(securityMode);
b.setXmppDomain(service);
diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/caps/EntityCapsTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/caps/EntityCapsTest.java
index 0a0110882..4c373a9ce 100644
--- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/caps/EntityCapsTest.java
+++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/caps/EntityCapsTest.java
@@ -31,6 +31,7 @@ import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.NotLoggedInException;
import org.jivesoftware.smack.StanzaListener;
+import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.filter.AndFilter;
@@ -40,6 +41,7 @@ import org.jivesoftware.smack.filter.PresenceTypeFilter;
import org.jivesoftware.smack.filter.StanzaTypeFilter;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.roster.RosterUtil;
+import org.jivesoftware.smack.util.Async.ThrowingRunnable;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
@@ -49,7 +51,6 @@ import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
import org.igniterealtime.smack.inttest.annotations.AfterClass;
import org.igniterealtime.smack.inttest.annotations.BeforeClass;
import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest;
-import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
public class EntityCapsTest extends AbstractSmackIntegrationTest {
@@ -124,11 +125,7 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest {
/**
* Test if entity caps actually prevent a disco info request and reply.
*
- * @throws XMPPException if an XMPP protocol error was received.
- * @throws InterruptedException if the calling thread was interrupted.
- * @throws NotConnectedException if the XMPP connection is not connected.
- * @throws NoResponseException if there was no response from the remote entity.
- *
+ * @throws Exception if exception.
*/
@SmackIntegrationTest
public void testPreventDiscoInfo() throws Exception {
@@ -143,26 +140,7 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest {
}, new AndFilter(new StanzaTypeFilter(DiscoverInfo.class), IQTypeFilter.GET));
- final SimpleResultSyncPoint presenceReceivedSyncPoint = new SimpleResultSyncPoint();
- final StanzaListener presenceListener = new StanzaListener() {
- @Override
- public void processStanza(Stanza packet) {
- presenceReceivedSyncPoint.signal();
- }
- };
-
- // Add a stanzaListener to listen for incoming presence
- conOne.addAsyncStanzaListener(presenceListener, PresenceTypeFilter.AVAILABLE);
-
- // add a bogus feature so that con1 ver won't match con0's
- sdmTwo.addFeature(dummyFeature);
-
- try {
- // wait for the dummy feature to get sent via presence
- presenceReceivedSyncPoint.waitForResult(timeout);
- } finally {
- conOne.removeAsyncStanzaListener(presenceListener);
- }
+ addFeatureAndWaitForPresence(conOne, conTwo, dummyFeature);
dropCapsCache();
// discover that
@@ -181,10 +159,10 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest {
}
@SmackIntegrationTest
- public void testCapsChanged() {
+ public void testCapsChanged() throws Exception {
final String dummyFeature = getNewDummyFeature();
String nodeVerBefore = EntityCapsManager.getNodeVersionByJid(conTwo.getUser());
- sdmTwo.addFeature(dummyFeature);
+ addFeatureAndWaitForPresence(conOne, conTwo, dummyFeature);
String nodeVerAfter = EntityCapsManager.getNodeVersionByJid(conTwo.getUser());
assertFalse(nodeVerBefore.equals(nodeVerAfter));
@@ -229,4 +207,24 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest {
private static void dropCapsCache() {
EntityCapsManager.CAPS_CACHE.clear();
}
+
+ /**
+ * Adds 'feature' to conB and waits until conA observes a presence form conB.
+ *
+ * @param conA the connection to observe the presence on.
+ * @param conB the connection to add the feature to.
+ * @param feature the feature to add.
+ * @throws Exception in case of an exception.
+ */
+ private void addFeatureAndWaitForPresence(XMPPConnection conA, XMPPConnection conB, String feature)
+ throws Exception {
+ final ServiceDiscoveryManager sdmB = ServiceDiscoveryManager.getInstanceFor(conB);
+ ThrowingRunnable action = new ThrowingRunnable() {
+ @Override
+ public void runOrThrow() throws Exception {
+ sdmB.addFeature(feature);
+ }
+ };
+ performActionAndWaitForPresence(conA, conB, action);
+ }
}
diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java
index 6b153b3a2..11e1340f4 100644
--- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java
+++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java
@@ -21,7 +21,6 @@ import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.chatstates.ChatState;
-import org.jivesoftware.smackx.chatstates.ChatStateListener;
import org.jivesoftware.smackx.chatstates.ChatStateManager;
import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
@@ -34,25 +33,19 @@ public class ChatStateIntegrationTest extends AbstractSmackIntegrationTest {
// Listener for composing chat state
private final SimpleResultSyncPoint composingSyncPoint = new SimpleResultSyncPoint();
- private final ChatStateListener composingListener = new ChatStateListener() {
- @Override
- public void stateChanged(Chat chat, ChatState state, Message message) {
- if (state.equals(ChatState.composing)) {
- composingSyncPoint.signal();
- }
+ private void composingListener(Chat chat, ChatState state, Message message) {
+ if (state.equals(ChatState.composing)) {
+ composingSyncPoint.signal();
}
- };
+ }
// Listener for active chat state
private final SimpleResultSyncPoint activeSyncPoint = new SimpleResultSyncPoint();
- private final ChatStateListener activeListener = new ChatStateListener() {
- @Override
- public void stateChanged(Chat chat, ChatState state, Message message) {
- if (state.equals(ChatState.active)) {
- activeSyncPoint.signal();
- }
+ private void activeListener(Chat chat, ChatState state, Message message) {
+ if (state.equals(ChatState.active)) {
+ activeSyncPoint.signal();
}
- };
+ }
public ChatStateIntegrationTest(SmackIntegrationTestEnvironment environment) {
@@ -65,8 +58,8 @@ public class ChatStateIntegrationTest extends AbstractSmackIntegrationTest {
ChatStateManager manTwo = ChatStateManager.getInstance(conTwo);
// Add chatState listeners.
- manTwo.addChatStateListener(composingListener);
- manTwo.addChatStateListener(activeListener);
+ manTwo.addChatStateListener(this::composingListener);
+ manTwo.addChatStateListener(this::activeListener);
Chat chatOne = ChatManager.getInstanceFor(conOne)
.chatWith(conTwo.getUser().asEntityBareJid());
@@ -86,7 +79,7 @@ public class ChatStateIntegrationTest extends AbstractSmackIntegrationTest {
@AfterClass
public void cleanup() {
ChatStateManager manTwo = ChatStateManager.getInstance(conTwo);
- manTwo.removeChatStateListener(composingListener);
- manTwo.removeChatStateListener(activeListener);
+ manTwo.removeChatStateListener(this::composingListener);
+ manTwo.removeChatStateListener(this::activeListener);
}
}
diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadIntegrationTest.java
index 7736c0657..243bfec36 100644
--- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadIntegrationTest.java
+++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadIntegrationTest.java
@@ -57,7 +57,9 @@ public class HttpFileUploadIntegrationTest extends AbstractSmackIntegrationTest
+ " does not accept files of size " + FILE_SIZE
+ ". It only accepts files with a maximum size of " + uploadService.getMaxFileSize());
}
- hfumOne.setTlsContext(environment.configuration.tlsContext);
+ if (environment.configuration.sslContextFactory != null) {
+ hfumOne.setTlsContext(environment.configuration.sslContextFactory.createSslContext());
+ }
}
@SmackIntegrationTest
diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/softwareInfo/SoftwareInfoIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/softwareInfo/SoftwareInfoIntegrationTest.java
index e2e37fae5..f289c96be 100644
--- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/softwareInfo/SoftwareInfoIntegrationTest.java
+++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/softwareInfo/SoftwareInfoIntegrationTest.java
@@ -16,13 +16,14 @@
*/
package org.jivesoftware.smackx.softwareInfo;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.jivesoftware.smack.parsing.SmackParsingException;
+import org.jivesoftware.smack.util.Async.ThrowingRunnable;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.mediaelement.element.MediaElement;
import org.jivesoftware.smackx.softwareinfo.SoftwareInfoManager;
@@ -54,9 +55,14 @@ public class SoftwareInfoIntegrationTest extends AbstractSmackIntegrationTest {
@SmackIntegrationTest
public void test() throws Exception {
SoftwareInfoForm softwareInfoSent = createSoftwareInfoForm();
- sim1.publishSoftwareInformationForm(softwareInfoSent);
+ performActionAndWaitForPresence(conTwo, conOne, new ThrowingRunnable() {
+ @Override
+ public void runOrThrow() throws Exception {
+ sim1.publishSoftwareInformationForm(softwareInfoSent);
+ }
+ });
SoftwareInfoForm softwareInfoFormReceived = sim2.fromJid(conOne.getUser());
- assertTrue(softwareInfoFormReceived.equals(softwareInfoSent));
+ assertEquals(softwareInfoSent, softwareInfoFormReceived);
}
private static SoftwareInfoForm createSoftwareInfoForm() throws URISyntaxException {
diff --git a/smack-omemo-signal/src/test/java/org/jivesoftware/smackx/omemo/SignalOmemoStoreTest.java b/smack-omemo-signal/src/test/java/org/jivesoftware/smackx/omemo/SignalOmemoStoreTest.java
index 37b493a26..a4a9bedea 100644
--- a/smack-omemo-signal/src/test/java/org/jivesoftware/smackx/omemo/SignalOmemoStoreTest.java
+++ b/smack-omemo-signal/src/test/java/org/jivesoftware/smackx/omemo/SignalOmemoStoreTest.java
@@ -60,7 +60,7 @@ public class SignalOmemoStoreTest extends OmemoStoreTest omemoMessageListeners = new HashSet<>();
private final HashSet omemoMucMessageListeners = new HashSet<>();
+ private final PepManager pepManager;
+
private OmemoTrustCallback trustCallback;
private BareJid ownJid;
@@ -120,6 +115,7 @@ public final class OmemoManager extends Manager {
super(connection);
service = OmemoService.getInstance();
+ pepManager = PepManager.getInstanceFor(connection);
this.deviceId = deviceId;
@@ -138,9 +134,6 @@ public final class OmemoManager extends Manager {
// StanzaListeners
resumeStanzaAndPEPListeners();
-
- // Announce OMEMO support
- ServiceDiscoveryManager.getInstanceFor(connection).addFeature(PEP_NODE_DEVICE_LIST_NOTIFY);
}
/**
@@ -251,7 +244,6 @@ public final class OmemoManager extends Manager {
}
getOmemoService().init(new LoggedInOmemoManager(this));
- ServiceDiscoveryManager.getInstanceFor(connection()).addFeature(PEP_NODE_DEVICE_LIST_NOTIFY);
}
/**
@@ -893,27 +885,25 @@ public final class OmemoManager extends Manager {
* after {@link #stopStanzaAndPEPListeners()} was called.
*/
public void resumeStanzaAndPEPListeners() {
- PepManager pepManager = PepManager.getInstanceFor(connection());
CarbonManager carbonManager = CarbonManager.getInstanceFor(connection());
// Remove listeners to avoid them getting added twice
- connection().removeAsyncStanzaListener(internalOmemoMessageStanzaListener);
- carbonManager.removeCarbonCopyReceivedListener(internalOmemoCarbonCopyListener);
- pepManager.removePepListener(deviceListUpdateListener);
+ connection().removeAsyncStanzaListener(this::internalOmemoMessageStanzaListener);
+ carbonManager.removeCarbonCopyReceivedListener(this::internalOmemoCarbonCopyListener);
// Add listeners
- pepManager.addPepListener(deviceListUpdateListener);
- connection().addAsyncStanzaListener(internalOmemoMessageStanzaListener, omemoMessageStanzaFilter);
- carbonManager.addCarbonCopyReceivedListener(internalOmemoCarbonCopyListener);
+ pepManager.addPepEventListener(OmemoConstants.PEP_NODE_DEVICE_LIST, OmemoDeviceListElement.class, pepOmemoDeviceListEventListener);
+ connection().addAsyncStanzaListener(this::internalOmemoMessageStanzaListener, OmemoManager::isOmemoMessage);
+ carbonManager.addCarbonCopyReceivedListener(this::internalOmemoCarbonCopyListener);
}
/**
* Remove active stanza listeners needed for OMEMO.
*/
public void stopStanzaAndPEPListeners() {
- PepManager.getInstanceFor(connection()).removePepListener(deviceListUpdateListener);
- connection().removeAsyncStanzaListener(internalOmemoMessageStanzaListener);
- CarbonManager.getInstanceFor(connection()).removeCarbonCopyReceivedListener(internalOmemoCarbonCopyListener);
+ pepManager.removePepEventListener(pepOmemoDeviceListEventListener);
+ connection().removeAsyncStanzaListener(this::internalOmemoMessageStanzaListener);
+ CarbonManager.getInstanceFor(connection()).removeCarbonCopyReceivedListener(this::internalOmemoCarbonCopyListener);
}
/**
@@ -961,127 +951,87 @@ public final class OmemoManager extends Manager {
/**
* StanzaListener that listens for incoming Stanzas which contain OMEMO elements.
*/
- private final StanzaListener internalOmemoMessageStanzaListener = new StanzaListener() {
+ private void internalOmemoMessageStanzaListener(final Stanza packet) {
+ Async.go(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ getOmemoService().onOmemoMessageStanzaReceived(packet,
+ new LoggedInOmemoManager(OmemoManager.this));
+ } catch (SmackException.NotLoggedInException | IOException e) {
+ LOGGER.log(Level.SEVERE, "Exception while processing OMEMO stanza", e);
+ }
+ }
+ });
+ }
- @Override
- public void processStanza(final Stanza packet) {
- Async.go(new Runnable() {
- @Override
- public void run() {
+ /**
+ * CarbonCopyListener that listens for incoming carbon copies which contain OMEMO elements.
+ */
+ private void internalOmemoCarbonCopyListener(final CarbonExtension.Direction direction,
+ final Message carbonCopy,
+ final Message wrappingMessage) {
+ Async.go(new Runnable() {
+ @Override
+ public void run() {
+ if (isOmemoMessage(carbonCopy)) {
try {
- getOmemoService().onOmemoMessageStanzaReceived(packet,
+ getOmemoService().onOmemoCarbonCopyReceived(direction, carbonCopy, wrappingMessage,
new LoggedInOmemoManager(OmemoManager.this));
} catch (SmackException.NotLoggedInException | IOException e) {
LOGGER.log(Level.SEVERE, "Exception while processing OMEMO stanza", e);
}
}
- });
- }
- };
+ }
+ });
+ }
- /**
- * CarbonCopyListener that listens for incoming carbon copies which contain OMEMO elements.
- */
- private final CarbonCopyReceivedListener internalOmemoCarbonCopyListener = new CarbonCopyReceivedListener() {
- @Override
- public void onCarbonCopyReceived(final CarbonExtension.Direction direction,
- final Message carbonCopy,
- final Message wrappingMessage) {
- Async.go(new Runnable() {
- @Override
- public void run() {
- if (omemoMessageStanzaFilter.accept(carbonCopy)) {
- try {
- getOmemoService().onOmemoCarbonCopyReceived(direction, carbonCopy, wrappingMessage,
- new LoggedInOmemoManager(OmemoManager.this));
- } catch (SmackException.NotLoggedInException | IOException e) {
- LOGGER.log(Level.SEVERE, "Exception while processing OMEMO stanza", e);
- }
- }
- }
- });
- }
- };
+ @SuppressWarnings("UnnecessaryLambda")
+ private final PepEventListener pepOmemoDeviceListEventListener =
+ (from, receivedDeviceList, id, message) -> {
+ // Device List
+ OmemoCachedDeviceList deviceList;
+ try {
+ getOmemoService().getOmemoStoreBackend().mergeCachedDeviceList(getOwnDevice(), from,
+ receivedDeviceList);
- /**
- * PEPListener that listens for OMEMO deviceList updates.
- */
- private final PepListener deviceListUpdateListener = new PepListener() {
- @Override
- public void eventReceived(EntityBareJid from, EventElement event, Message message) {
-
- // Unknown sender, no more work to do.
- if (from == null) {
- // TODO: This DOES happen for some reason. Figure out when...
+ if (!from.asBareJid().equals(getOwnJid())) {
return;
}
- for (ExtensionElement items : event.getExtensions()) {
- if (!(items instanceof ItemsExtension)) {
- continue;
- }
-
- for (ExtensionElement item : ((ItemsExtension) items).getExtensions()) {
- if (!(item instanceof PayloadItem>)) {
- continue;
- }
-
- PayloadItem> payloadItem = (PayloadItem>) item;
-
- if (!(payloadItem.getPayload() instanceof OmemoDeviceListElement)) {
- continue;
- }
-
- // Device List
- OmemoCachedDeviceList deviceList;
- OmemoDeviceListElement receivedDeviceList = (OmemoDeviceListElement) payloadItem.getPayload();
- try {
- getOmemoService().getOmemoStoreBackend().mergeCachedDeviceList(getOwnDevice(), from,
- receivedDeviceList);
-
- if (!from.asBareJid().equals(getOwnJid())) {
- continue;
- }
-
- deviceList = getOmemoService().cleanUpDeviceList(getOwnDevice());
- } catch (IOException e) {
- LOGGER.log(Level.SEVERE,
- "IOException while processing OMEMO PEP device updates. Message: " + message,
+ deviceList = getOmemoService().cleanUpDeviceList(getOwnDevice());
+ } catch (IOException e) {
+ LOGGER.log(Level.SEVERE,
+ "IOException while processing OMEMO PEP device updates. Message: " + message,
e);
- continue;
- }
- final OmemoDeviceListElement_VAxolotl newDeviceList = new OmemoDeviceListElement_VAxolotl(deviceList);
+ return;
+ }
+ final OmemoDeviceListElement_VAxolotl newDeviceList = new OmemoDeviceListElement_VAxolotl(deviceList);
- if (!newDeviceList.copyDeviceIds().equals(receivedDeviceList.copyDeviceIds())) {
- LOGGER.log(Level.FINE, "Republish deviceList due to changes:" +
- " Received: " + Arrays.toString(receivedDeviceList.copyDeviceIds().toArray()) +
- " Published: " + Arrays.toString(newDeviceList.copyDeviceIds().toArray()));
- Async.go(new Runnable() {
- @Override
- public void run() {
- try {
- OmemoService.publishDeviceList(connection(), newDeviceList);
- } catch (InterruptedException | XMPPException.XMPPErrorException |
- SmackException.NotConnectedException | SmackException.NoResponseException | PubSubException.NotALeafNodeException e) {
- LOGGER.log(Level.WARNING, "Could not publish our deviceList upon an received update.", e);
- }
- }
- });
+ if (!newDeviceList.copyDeviceIds().equals(receivedDeviceList.copyDeviceIds())) {
+ LOGGER.log(Level.FINE, "Republish deviceList due to changes:" +
+ " Received: " + Arrays.toString(receivedDeviceList.copyDeviceIds().toArray()) +
+ " Published: " + Arrays.toString(newDeviceList.copyDeviceIds().toArray()));
+ Async.go(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ OmemoService.publishDeviceList(connection(), newDeviceList);
+ } catch (InterruptedException | XMPPException.XMPPErrorException |
+ SmackException.NotConnectedException | SmackException.NoResponseException | PubSubException.NotALeafNodeException e) {
+ LOGGER.log(Level.WARNING, "Could not publish our deviceList upon an received update.", e);
}
}
- }
+ });
}
};
/**
* StanzaFilter that filters messages containing a OMEMO element.
*/
- private final StanzaFilter omemoMessageStanzaFilter = new StanzaFilter() {
- @Override
- public boolean accept(Stanza stanza) {
- return stanza instanceof Message && OmemoManager.stanzaContainsOmemoElement(stanza);
- }
- };
+ private static boolean isOmemoMessage(Stanza stanza) {
+ return stanza instanceof Message && OmemoManager.stanzaContainsOmemoElement(stanza);
+ }
/**
* Guard class which ensures that the wrapped OmemoManager knows its BareJid.
diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoConstants.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoConstants.java
index f91dc199f..352853450 100644
--- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoConstants.java
+++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoConstants.java
@@ -31,7 +31,6 @@ public final class OmemoConstants {
// PubSub Node names
public static final String PEP_NODE_DEVICE_LIST = OMEMO_NAMESPACE_V_AXOLOTL + ".devicelist";
- public static final String PEP_NODE_DEVICE_LIST_NOTIFY = PEP_NODE_DEVICE_LIST + "+notify";
public static final String PEP_NODE_BUNDLES = OMEMO_NAMESPACE_V_AXOLOTL + ".bundles";
/**
diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java
index d16296a05..a3a8a7c1b 100644
--- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java
+++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java
@@ -1,6 +1,6 @@
/**
*
- * Copyright 2017-2019 Florian Schmaus, 2018 Paul Schaub.
+ * Copyright 2017-2020 Florian Schmaus, 2018 Paul Schaub.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,7 +39,6 @@ import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.chat2.Chat;
import org.jivesoftware.smack.chat2.ChatManager;
-import org.jivesoftware.smack.chat2.IncomingChatMessageListener;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.util.Async;
import org.jivesoftware.smack.util.stringencoder.Base64;
@@ -69,12 +68,10 @@ import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore;
import org.jivesoftware.smackx.ox.util.OpenPgpPubSubUtil;
import org.jivesoftware.smackx.ox.util.SecretKeyBackupHelper;
+import org.jivesoftware.smackx.pep.PepEventListener;
import org.jivesoftware.smackx.pep.PepListener;
import org.jivesoftware.smackx.pep.PepManager;
-import org.jivesoftware.smackx.pubsub.EventElement;
-import org.jivesoftware.smackx.pubsub.ItemsExtension;
import org.jivesoftware.smackx.pubsub.LeafNode;
-import org.jivesoftware.smackx.pubsub.PayloadItem;
import org.jivesoftware.smackx.pubsub.PubSubException;
import org.jivesoftware.smackx.pubsub.PubSubFeature;
@@ -173,6 +170,9 @@ public final class OpenPgpManager extends Manager {
private final Set signElementReceivedListeners = new HashSet<>();
private final Set cryptElementReceivedListeners = new HashSet<>();
+ @SuppressWarnings("UnnecessaryLambda")
+ private final PepEventListener pepPublicKeyListElementListener = (from, listElement, id, message) -> processPublicKeysListElement(from, listElement);;
+
/**
* Private constructor to avoid instantiation without putting the object into {@code INSTANCES}.
*
@@ -180,7 +180,7 @@ public final class OpenPgpManager extends Manager {
*/
private OpenPgpManager(XMPPConnection connection) {
super(connection);
- ChatManager.getInstanceFor(connection).addIncomingListener(incomingOpenPgpMessageListener);
+ ChatManager.getInstanceFor(connection).addIncomingListener(this::incomingChatMessageListener);
pepManager = PepManager.getInstanceFor(connection);
}
@@ -279,7 +279,7 @@ public final class OpenPgpManager extends Manager {
publishPublicKey(pepManager, pubkeyElement, primaryFingerprint);
// Subscribe to public key changes
- PepManager.getInstanceFor(connection()).addPepListener(metadataListener);
+ pepManager.addPepEventListener(PEP_NODE_PUBLIC_KEYS, PublicKeysListElement.class, pepPublicKeyListElementListener);
ServiceDiscoveryManager.getInstanceFor(connection())
.addFeature(PEP_NODE_PUBLIC_KEYS_NOTIFY);
}
@@ -381,7 +381,7 @@ public final class OpenPgpManager extends Manager {
* Remove the metadata listener. This method is mainly used in tests.
*/
public void stopMetadataListener() {
- PepManager.getInstanceFor(connection()).removePepListener(metadataListener);
+ pepManager.removePepEventListener(pepPublicKeyListElementListener);
}
/**
@@ -497,31 +497,6 @@ public final class OpenPgpManager extends Manager {
Private stuff.
*/
- /**
- * {@link PepListener} that listens for changes to the OX public keys metadata node.
- *
- * @see XEP-0373 §4.4
- */
- private final PepListener metadataListener = new PepListener() {
- @Override
- public void eventReceived(final EntityBareJid from, final EventElement event, final Message message) {
- if (PEP_NODE_PUBLIC_KEYS.equals(event.getEvent().getNode())) {
- final BareJid contact = from.asBareJid();
- LOGGER.log(Level.INFO, "Received OpenPGP metadata update from " + contact);
- Async.go(new Runnable() {
- @Override
- public void run() {
- ItemsExtension items = (ItemsExtension) event.getExtensions().get(0);
- PayloadItem> payload = (PayloadItem>) items.getItems().get(0);
- PublicKeysListElement listElement = (PublicKeysListElement) payload.getPayload();
-
- processPublicKeysListElement(from, listElement);
- }
- }, "ProcessOXMetadata");
- }
- }
- };
-
private void processPublicKeysListElement(BareJid contact, PublicKeysListElement listElement) {
OpenPgpContact openPgpContact = getOpenPgpContact(contact.asEntityBareJidIfPossible());
try {
@@ -548,62 +523,60 @@ public final class OpenPgpManager extends Manager {
return provider.decryptAndOrVerify(element, getOpenPgpSelf(), sender);
}
- private final IncomingChatMessageListener incomingOpenPgpMessageListener =
- new IncomingChatMessageListener() {
- @Override
- public void newIncomingMessage(final EntityBareJid from, final Message message, Chat chat) {
- Async.go(new Runnable() {
- @Override
- public void run() {
- OpenPgpElement element = message.getExtension(OpenPgpElement.class);
- if (element == null) {
- // Message does not contain an OpenPgpElement -> discard
- return;
- }
-
- OpenPgpContact contact = getOpenPgpContact(from);
-
- OpenPgpMessage decrypted = null;
- OpenPgpContentElement contentElement = null;
- try {
- decrypted = decryptOpenPgpElement(element, contact);
- contentElement = decrypted.getOpenPgpContentElement();
- } catch (PGPException e) {
- LOGGER.log(Level.WARNING, "Could not decrypt incoming OpenPGP encrypted message", e);
- } catch (XmlPullParserException | IOException e) {
- LOGGER.log(Level.WARNING, "Invalid XML content of incoming OpenPGP encrypted message", e);
- } catch (SmackException.NotLoggedInException e) {
- LOGGER.log(Level.WARNING, "Cannot determine our JID, since we are not logged in.", e);
- }
-
- if (contentElement instanceof SigncryptElement) {
- for (SigncryptElementReceivedListener l : signcryptElementReceivedListeners) {
- l.signcryptElementReceived(contact, message, (SigncryptElement) contentElement, decrypted.getMetadata());
- }
- return;
- }
-
- if (contentElement instanceof SignElement) {
- for (SignElementReceivedListener l : signElementReceivedListeners) {
- l.signElementReceived(contact, message, (SignElement) contentElement, decrypted.getMetadata());
- }
- return;
- }
-
- if (contentElement instanceof CryptElement) {
- for (CryptElementReceivedListener l : cryptElementReceivedListeners) {
- l.cryptElementReceived(contact, message, (CryptElement) contentElement, decrypted.getMetadata());
- }
- return;
- }
-
- else {
- throw new AssertionError("Invalid element received: " + contentElement.getClass().getName());
- }
- }
- });
+ private void incomingChatMessageListener(final EntityBareJid from, final Message message, Chat chat) {
+ Async.go(new Runnable() {
+ @Override
+ public void run() {
+ OpenPgpElement element = message.getExtension(OpenPgpElement.class);
+ if (element == null) {
+ // Message does not contain an OpenPgpElement -> discard
+ return;
}
- };
+
+ OpenPgpContact contact = getOpenPgpContact(from);
+
+ OpenPgpMessage decrypted = null;
+ OpenPgpContentElement contentElement = null;
+ try {
+ decrypted = decryptOpenPgpElement(element, contact);
+ contentElement = decrypted.getOpenPgpContentElement();
+ } catch (PGPException e) {
+ LOGGER.log(Level.WARNING, "Could not decrypt incoming OpenPGP encrypted message", e);
+ } catch (XmlPullParserException | IOException e) {
+ LOGGER.log(Level.WARNING, "Invalid XML content of incoming OpenPGP encrypted message", e);
+ } catch (SmackException.NotLoggedInException e) {
+ LOGGER.log(Level.WARNING, "Cannot determine our JID, since we are not logged in.", e);
+ }
+
+ if (contentElement instanceof SigncryptElement) {
+ for (SigncryptElementReceivedListener l : signcryptElementReceivedListeners) {
+ l.signcryptElementReceived(contact, message, (SigncryptElement) contentElement,
+ decrypted.getMetadata());
+ }
+ return;
+ }
+
+ if (contentElement instanceof SignElement) {
+ for (SignElementReceivedListener l : signElementReceivedListeners) {
+ l.signElementReceived(contact, message, (SignElement) contentElement, decrypted.getMetadata());
+ }
+ return;
+ }
+
+ if (contentElement instanceof CryptElement) {
+ for (CryptElementReceivedListener l : cryptElementReceivedListeners) {
+ l.cryptElementReceived(contact, message, (CryptElement) contentElement,
+ decrypted.getMetadata());
+ }
+ return;
+ }
+
+ else {
+ throw new AssertionError("Invalid element received: " + contentElement.getClass().getName());
+ }
+ }
+ });
+ }
/**
* Create a {@link PubkeyElement} which contains the OpenPGP public key of {@code owner} which belongs to
diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManager.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManager.java
index 1ccdabe0f..4383a02b3 100644
--- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManager.java
+++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManager.java
@@ -44,7 +44,6 @@ import org.jivesoftware.smackx.ox.crypto.OpenPgpElementAndMetadata;
import org.jivesoftware.smackx.ox.element.OpenPgpContentElement;
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
import org.jivesoftware.smackx.ox.element.SigncryptElement;
-import org.jivesoftware.smackx.ox.listener.SigncryptElementReceivedListener;
import org.bouncycastle.openpgp.PGPException;
import org.jxmpp.jid.BareJid;
@@ -127,7 +126,7 @@ public final class OXInstantMessagingManager extends Manager {
private OXInstantMessagingManager(final XMPPConnection connection) {
super(connection);
openPgpManager = OpenPgpManager.getInstanceFor(connection);
- openPgpManager.registerSigncryptReceivedListener(signcryptElementReceivedListener);
+ openPgpManager.registerSigncryptReceivedListener(this::signcryptElementReceivedListener);
announceSupportForOxInstantMessaging();
}
@@ -358,12 +357,9 @@ public final class OXInstantMessagingManager extends Manager {
message.setBody("This message is encrypted using XEP-0374: OpenPGP for XMPP: Instant Messaging.");
}
- private final SigncryptElementReceivedListener signcryptElementReceivedListener = new SigncryptElementReceivedListener() {
- @Override
- public void signcryptElementReceived(OpenPgpContact contact, Message originalMessage, SigncryptElement signcryptElement, OpenPgpMetadata metadata) {
- for (OxMessageListener listener : oxMessageListeners) {
- listener.newIncomingOxMessage(contact, originalMessage, signcryptElement, metadata);
- }
+ private void signcryptElementReceivedListener(OpenPgpContact contact, Message originalMessage, SigncryptElement signcryptElement, OpenPgpMetadata metadata) {
+ for (OxMessageListener listener : oxMessageListeners) {
+ listener.newIncomingOxMessage(contact, originalMessage, signcryptElement, metadata);
}
- };
+ }
}
diff --git a/smack-repl/build.gradle b/smack-repl/build.gradle
index 3176e1985..2ba95bcc4 100644
--- a/smack-repl/build.gradle
+++ b/smack-repl/build.gradle
@@ -2,6 +2,9 @@ plugins {
id "com.github.alisiikh.scalastyle_2.12" version "2.0.2"
}
+description = """\
+A REPL (Read-Eval-Print-Loop) for Smack, or, in other words, a CLI (Command Line Interface) for Smack."""
+
apply plugin: 'scala'
apply plugin: 'com.github.alisiikh.scalastyle_2.12'
diff --git a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java
index d9d766447..af4b939d6 100644
--- a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java
+++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java
@@ -42,6 +42,8 @@ import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.sm.StreamManagementModuleDescriptor;
import org.jivesoftware.smack.tcp.XmppTcpTransportModuleDescriptor;
+import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
+
import org.jxmpp.util.XmppDateTime;
public class Nio {
@@ -128,9 +130,10 @@ public class Nio {
connection.disconnect();
ModularXmppClientToServerConnection.Stats connectionStats = connection.getStats();
+ ServiceDiscoveryManager.Stats serviceDiscoveryManagerStats = ServiceDiscoveryManager.getInstanceFor(connection).getStats();
// CHECKSTYLE:OFF
- System.out.println("NIO successfully finished, yeah!\n" + connectionStats);
+ System.out.println("NIO successfully finished, yeah!\n" + connectionStats + '\n' + serviceDiscoveryManagerStats);
// CHECKSTYLE:ON
}
diff --git a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/TlsTest.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/TlsTest.java
index 557f1812d..08bd25b6d 100644
--- a/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/TlsTest.java
+++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/TlsTest.java
@@ -89,7 +89,7 @@ public class TlsTest {
if (StringUtils.isNotEmpty(tlsPin)) {
SSLContext sslContext = Java7Pinning.forPin(tlsPin);
- builder.setCustomSSLContext(sslContext);
+ builder.setSslContextFactory(() -> sslContext);
}
diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java
index f71e3f196..ea34b9518 100644
--- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java
+++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java
@@ -81,6 +81,7 @@ import org.jivesoftware.smack.compress.packet.Compressed;
import org.jivesoftware.smack.compression.XMPPInputOutputStream;
import org.jivesoftware.smack.datatypes.UInt16;
import org.jivesoftware.smack.filter.StanzaFilter;
+import org.jivesoftware.smack.internal.SmackTlsContext;
import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java
index ead3a6438..74286fdd9 100644
--- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java
+++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java
@@ -21,13 +21,9 @@ import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collection;
@@ -49,7 +45,6 @@ import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
-import org.jivesoftware.smack.AbstractXMPPConnection.SmackTlsContext;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.ConnectionException;
@@ -61,7 +56,6 @@ import org.jivesoftware.smack.SmackException.SecurityRequiredByServerException;
import org.jivesoftware.smack.SmackException.SmackWrappedException;
import org.jivesoftware.smack.SmackFuture;
import org.jivesoftware.smack.SmackFuture.InternalSmackFuture;
-import org.jivesoftware.smack.SmackReactor.ChannelSelectedCallback;
import org.jivesoftware.smack.SmackReactor.SelectionKeyAttachment;
import org.jivesoftware.smack.XMPPException.FailedNonzaException;
import org.jivesoftware.smack.XmppInputOutputFilter;
@@ -75,6 +69,7 @@ import org.jivesoftware.smack.debugger.SmackDebugger;
import org.jivesoftware.smack.fsm.State;
import org.jivesoftware.smack.fsm.StateDescriptor;
import org.jivesoftware.smack.fsm.StateTransitionResult;
+import org.jivesoftware.smack.internal.SmackTlsContext;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.StartTls;
import org.jivesoftware.smack.packet.StreamOpen;
@@ -280,294 +275,292 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
}
};
- private final ChannelSelectedCallback channelSelectedCallback =
- (selectedChannel, selectedSelectionKey) -> {
- assert selectionKey == null || selectionKey == selectedSelectionKey;
- SocketChannel selectedSocketChannel = (SocketChannel) selectedChannel;
- // We are *always* interested in OP_READ.
- int newInterestedOps = SelectionKey.OP_READ;
- boolean newPendingOutputFilterData = false;
+ private void onChannelSelected(SelectableChannel selectedChannel, SelectionKey selectedSelectionKey) {
+ assert selectionKey == null || selectionKey == selectedSelectionKey;
+ SocketChannel selectedSocketChannel = (SocketChannel) selectedChannel;
+ // We are *always* interested in OP_READ.
+ int newInterestedOps = SelectionKey.OP_READ;
+ boolean newPendingOutputFilterData = false;
- if (!channelSelectedCallbackLock.tryLock()) {
- rejectedChannelSelectedCallbacks.incrementAndGet();
+ if (!channelSelectedCallbackLock.tryLock()) {
+ rejectedChannelSelectedCallbacks.incrementAndGet();
+ return;
+ }
+
+ handledChannelSelectedCallbacks++;
+
+ long callbackBytesRead = 0;
+ long callbackBytesWritten = 0;
+
+ try {
+ boolean destinationAddressChanged = false;
+ boolean isLastPartOfElement = false;
+ TopLevelStreamElement currentlyOutgonigTopLevelStreamElement = null;
+ StringBuilder outgoingStreamForDebugger = null;
+
+ writeLoop: while (true) {
+ final boolean moreDataAvailable = !isLastPartOfElement || !connectionInternal.outgoingElementsQueue.isEmpty();
+
+ if (filteredOutgoingBuffer != null || !networkOutgoingBuffers.isEmpty()) {
+ if (filteredOutgoingBuffer != null) {
+ networkOutgoingBuffers.add(filteredOutgoingBuffer);
+ networkOutgoingBuffersBytes += filteredOutgoingBuffer.remaining();
+
+ filteredOutgoingBuffer = null;
+ if (moreDataAvailable && networkOutgoingBuffersBytes < 8096) {
+ continue;
+ }
+ }
+
+ ByteBuffer[] output = networkOutgoingBuffers.toArray(new ByteBuffer[networkOutgoingBuffers.size()]);
+ long bytesWritten;
+ try {
+ bytesWritten = selectedSocketChannel.write(output);
+ } catch (IOException e) {
+ // We have seen here so far
+ // - IOException "Broken pipe"
+ handleReadWriteIoException(e);
+ break;
+ }
+
+ if (bytesWritten == 0) {
+ newInterestedOps |= SelectionKey.OP_WRITE;
+ break;
+ }
+
+ callbackBytesWritten += bytesWritten;
+
+ networkOutgoingBuffersBytes -= bytesWritten;
+
+ List extends Buffer> prunedBuffers = pruneBufferList(networkOutgoingBuffers);
+
+ for (Buffer prunedBuffer : prunedBuffers) {
+ List sendElements = bufferToElementMap.remove(prunedBuffer);
+ if (sendElements == null) {
+ continue;
+ }
+ for (TopLevelStreamElement elementJustSend : sendElements) {
+ connectionInternal.fireFirstLevelElementSendListeners(elementJustSend);
+ }
+ }
+
+ // Prevent one callback from dominating the reactor thread. Break out of the write-loop if we have
+ // written a certain amount.
+ if (callbackBytesWritten > CALLBACK_MAX_BYTES_WRITEN) {
+ newInterestedOps |= SelectionKey.OP_WRITE;
+ callbackPreemtBecauseBytesWritten++;
+ break;
+ }
+ } else if (outgoingBuffer != null || pendingOutputFilterData) {
+ pendingOutputFilterData = false;
+
+ if (outgoingBuffer != null) {
+ totalBytesWrittenBeforeFilter += outgoingBuffer.remaining();
+ if (isLastPartOfElement) {
+ assert currentlyOutgonigTopLevelStreamElement != null;
+ currentlyOutgoingElements.add(currentlyOutgonigTopLevelStreamElement);
+ }
+ }
+
+ ByteBuffer outputFilterInputData = outgoingBuffer;
+ // We can now null the outgoingBuffer since the filter step will take care of it from now on.
+ outgoingBuffer = null;
+
+ for (ListIterator it = connectionInternal.getXmppInputOutputFilterBeginIterator(); it.hasNext();) {
+ XmppInputOutputFilter inputOutputFilter = it.next();
+ XmppInputOutputFilter.OutputResult outputResult;
+ try {
+ outputResult = inputOutputFilter.output(outputFilterInputData, isLastPartOfElement,
+ destinationAddressChanged, moreDataAvailable);
+ } catch (IOException e) {
+ connectionInternal.notifyConnectionError(e);
+ break writeLoop;
+ }
+ newPendingOutputFilterData |= outputResult.pendingFilterData;
+ outputFilterInputData = outputResult.filteredOutputData;
+ if (outputFilterInputData != null) {
+ outputFilterInputData.flip();
+ }
+ }
+
+ // It is ok if outpuFilterInputData is 'null' here, this is expected behavior.
+ if (outputFilterInputData != null && outputFilterInputData.hasRemaining()) {
+ filteredOutgoingBuffer = outputFilterInputData;
+ } else {
+ filteredOutgoingBuffer = null;
+ }
+
+ // If the filters did eventually not produce any output data but if there is
+ // pending output data then we have a pending write request after read.
+ if (filteredOutgoingBuffer == null && newPendingOutputFilterData) {
+ pendingWriteInterestAfterRead = true;
+ }
+
+ if (filteredOutgoingBuffer != null && isLastPartOfElement) {
+ bufferToElementMap.put(filteredOutgoingBuffer, new ArrayList<>(currentlyOutgoingElements));
+ currentlyOutgoingElements.clear();
+ }
+
+ // Reset that the destination address has changed.
+ if (destinationAddressChanged) {
+ destinationAddressChanged = false;
+ }
+ } else if (outgoingCharSequenceIterator != null) {
+ CharSequence nextCharSequence = outgoingCharSequenceIterator.next();
+ outgoingBuffer = UTF8.encode(nextCharSequence);
+ if (!outgoingCharSequenceIterator.hasNext()) {
+ outgoingCharSequenceIterator = null;
+ isLastPartOfElement = true;
+ } else {
+ isLastPartOfElement = false;
+ }
+
+ final SmackDebugger debugger = connectionInternal.smackDebugger;
+ if (debugger != null) {
+ if (outgoingStreamForDebugger == null) {
+ outgoingStreamForDebugger = new StringBuilder();
+ }
+ outgoingStreamForDebugger.append(nextCharSequence);
+
+ if (isLastPartOfElement) {
+ try {
+ outputDebugSplitter.append(outgoingStreamForDebugger);
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ debugger.onOutgoingElementCompleted();
+ outgoingStreamForDebugger = null;
+ }
+ }
+ } else if (!connectionInternal.outgoingElementsQueue.isEmpty()) {
+ currentlyOutgonigTopLevelStreamElement = connectionInternal.outgoingElementsQueue.poll();
+ if (currentlyOutgonigTopLevelStreamElement instanceof Stanza) {
+ Stanza currentlyOutgoingStanza = (Stanza) currentlyOutgonigTopLevelStreamElement;
+ Jid currentDestinationAddress = currentlyOutgoingStanza.getTo();
+ destinationAddressChanged = !JidUtil.equals(lastDestinationAddress, currentDestinationAddress);
+ lastDestinationAddress = currentDestinationAddress;
+ }
+ CharSequence nextCharSequence = currentlyOutgonigTopLevelStreamElement.toXML(StreamOpen.CLIENT_NAMESPACE);
+ if (nextCharSequence instanceof XmlStringBuilder) {
+ XmlStringBuilder xmlStringBuilder = (XmlStringBuilder) nextCharSequence;
+ XmlEnvironment outgoingStreamXmlEnvironment = connectionInternal.getOutgoingStreamXmlEnvironment();
+ outgoingCharSequenceIterator = xmlStringBuilder.toList(outgoingStreamXmlEnvironment).iterator();
+ } else {
+ outgoingCharSequenceIterator = Collections.singletonList(nextCharSequence).iterator();
+ }
+ assert outgoingCharSequenceIterator != null;
+ } else {
+ // There is nothing more to write.
+ break;
+ }
+ }
+
+ pendingOutputFilterData = newPendingOutputFilterData;
+ if (!pendingWriteInterestAfterRead && pendingOutputFilterData) {
+ newInterestedOps |= SelectionKey.OP_WRITE;
+ }
+
+ readLoop: while (true) {
+ // Prevent one callback from dominating the reactor thread. Break out of the read-loop if we have
+ // read a certain amount.
+ if (callbackBytesRead > CALLBACK_MAX_BYTES_READ) {
+ callbackPreemtBecauseBytesRead++;
+ break;
+ }
+
+ int bytesRead;
+ incomingBuffer.clear();
+ try {
+ bytesRead = selectedSocketChannel.read(incomingBuffer);
+ } catch (IOException e) {
+ handleReadWriteIoException(e);
return;
}
- handledChannelSelectedCallbacks++;
-
- long callbackBytesRead = 0;
- long callbackBytesWritten = 0;
-
- try {
- boolean destinationAddressChanged = false;
- boolean isLastPartOfElement = false;
- TopLevelStreamElement currentlyOutgonigTopLevelStreamElement = null;
- StringBuilder outgoingStreamForDebugger = null;
-
- writeLoop: while (true) {
- final boolean moreDataAvailable = !isLastPartOfElement || !connectionInternal.outgoingElementsQueue.isEmpty();
-
- if (filteredOutgoingBuffer != null || !networkOutgoingBuffers.isEmpty()) {
- if (filteredOutgoingBuffer != null) {
- networkOutgoingBuffers.add(filteredOutgoingBuffer);
- networkOutgoingBuffersBytes += filteredOutgoingBuffer.remaining();
-
- filteredOutgoingBuffer = null;
- if (moreDataAvailable && networkOutgoingBuffersBytes < 8096) {
- continue;
- }
- }
-
- ByteBuffer[] output = networkOutgoingBuffers.toArray(new ByteBuffer[networkOutgoingBuffers.size()]);
- long bytesWritten;
- try {
- bytesWritten = selectedSocketChannel.write(output);
- } catch (IOException e) {
- // We have seen here so far
- // - IOException "Broken pipe"
- handleReadWriteIoException(e);
- break;
- }
-
- if (bytesWritten == 0) {
- newInterestedOps |= SelectionKey.OP_WRITE;
- break;
- }
-
- callbackBytesWritten += bytesWritten;
-
- networkOutgoingBuffersBytes -= bytesWritten;
-
- List extends Buffer> prunedBuffers = pruneBufferList(networkOutgoingBuffers);
-
- for (Buffer prunedBuffer : prunedBuffers) {
- List sendElements = bufferToElementMap.remove(prunedBuffer);
- if (sendElements == null) {
- continue;
- }
- for (TopLevelStreamElement elementJustSend : sendElements) {
- connectionInternal.fireFirstLevelElementSendListeners(elementJustSend);
- }
- }
-
- // Prevent one callback from dominating the reactor thread. Break out of the write-loop if we have
- // written a certain amount.
- if (callbackBytesWritten > CALLBACK_MAX_BYTES_WRITEN) {
- newInterestedOps |= SelectionKey.OP_WRITE;
- callbackPreemtBecauseBytesWritten++;
- break;
- }
- } else if (outgoingBuffer != null || pendingOutputFilterData) {
- pendingOutputFilterData = false;
-
- if (outgoingBuffer != null) {
- totalBytesWrittenBeforeFilter += outgoingBuffer.remaining();
- if (isLastPartOfElement) {
- assert currentlyOutgonigTopLevelStreamElement != null;
- currentlyOutgoingElements.add(currentlyOutgonigTopLevelStreamElement);
- }
- }
-
- ByteBuffer outputFilterInputData = outgoingBuffer;
- // We can now null the outgoingBuffer since the filter step will take care of it from now on.
- outgoingBuffer = null;
-
- for (ListIterator it = connectionInternal.getXmppInputOutputFilterBeginIterator(); it.hasNext();) {
- XmppInputOutputFilter inputOutputFilter = it.next();
- XmppInputOutputFilter.OutputResult outputResult;
- try {
- outputResult = inputOutputFilter.output(outputFilterInputData, isLastPartOfElement,
- destinationAddressChanged, moreDataAvailable);
- } catch (IOException e) {
- connectionInternal.notifyConnectionError(e);
- break writeLoop;
- }
- newPendingOutputFilterData |= outputResult.pendingFilterData;
- outputFilterInputData = outputResult.filteredOutputData;
- if (outputFilterInputData != null) {
- outputFilterInputData.flip();
- }
- }
-
- // It is ok if outpuFilterInputData is 'null' here, this is expected behavior.
- if (outputFilterInputData != null && outputFilterInputData.hasRemaining()) {
- filteredOutgoingBuffer = outputFilterInputData;
- } else {
- filteredOutgoingBuffer = null;
- }
-
- // If the filters did eventually not produce any output data but if there is
- // pending output data then we have a pending write request after read.
- if (filteredOutgoingBuffer == null && newPendingOutputFilterData) {
- pendingWriteInterestAfterRead = true;
- }
-
- if (filteredOutgoingBuffer != null && isLastPartOfElement) {
- bufferToElementMap.put(filteredOutgoingBuffer, new ArrayList<>(currentlyOutgoingElements));
- currentlyOutgoingElements.clear();
- }
-
- // Reset that the destination address has changed.
- if (destinationAddressChanged) {
- destinationAddressChanged = false;
- }
- } else if (outgoingCharSequenceIterator != null) {
- CharSequence nextCharSequence = outgoingCharSequenceIterator.next();
- outgoingBuffer = UTF8.encode(nextCharSequence);
- if (!outgoingCharSequenceIterator.hasNext()) {
- outgoingCharSequenceIterator = null;
- isLastPartOfElement = true;
- } else {
- isLastPartOfElement = false;
- }
-
- final SmackDebugger debugger = connectionInternal.smackDebugger;
- if (debugger != null) {
- if (outgoingStreamForDebugger == null) {
- outgoingStreamForDebugger = new StringBuilder();
- }
- outgoingStreamForDebugger.append(nextCharSequence);
-
- if (isLastPartOfElement) {
- try {
- outputDebugSplitter.append(outgoingStreamForDebugger);
- } catch (IOException e) {
- throw new AssertionError(e);
- }
- debugger.onOutgoingElementCompleted();
- outgoingStreamForDebugger = null;
- }
- }
- } else if (!connectionInternal.outgoingElementsQueue.isEmpty()) {
- currentlyOutgonigTopLevelStreamElement = connectionInternal.outgoingElementsQueue.poll();
- if (currentlyOutgonigTopLevelStreamElement instanceof Stanza) {
- Stanza currentlyOutgoingStanza = (Stanza) currentlyOutgonigTopLevelStreamElement;
- Jid currentDestinationAddress = currentlyOutgoingStanza.getTo();
- destinationAddressChanged = !JidUtil.equals(lastDestinationAddress, currentDestinationAddress);
- lastDestinationAddress = currentDestinationAddress;
- }
- CharSequence nextCharSequence = currentlyOutgonigTopLevelStreamElement.toXML(StreamOpen.CLIENT_NAMESPACE);
- if (nextCharSequence instanceof XmlStringBuilder) {
- XmlStringBuilder xmlStringBuilder = (XmlStringBuilder) nextCharSequence;
- XmlEnvironment outgoingStreamXmlEnvironment = connectionInternal.getOutgoingStreamXmlEnvironment();
- outgoingCharSequenceIterator = xmlStringBuilder.toList(outgoingStreamXmlEnvironment).iterator();
- } else {
- outgoingCharSequenceIterator = Collections.singletonList(nextCharSequence).iterator();
- }
- assert outgoingCharSequenceIterator != null;
- } else {
- // There is nothing more to write.
- break;
- }
- }
-
- pendingOutputFilterData = newPendingOutputFilterData;
- if (!pendingWriteInterestAfterRead && pendingOutputFilterData) {
- newInterestedOps |= SelectionKey.OP_WRITE;
- }
-
- readLoop: while (true) {
- // Prevent one callback from dominating the reactor thread. Break out of the read-loop if we have
- // read a certain amount.
- if (callbackBytesRead > CALLBACK_MAX_BYTES_READ) {
- callbackPreemtBecauseBytesRead++;
- break;
- }
-
- int bytesRead;
- incomingBuffer.clear();
- try {
- bytesRead = selectedSocketChannel.read(incomingBuffer);
- } catch (IOException e) {
- handleReadWriteIoException(e);
- return;
- }
-
- if (bytesRead < 0) {
- LOGGER.finer("NIO read() returned " + bytesRead
- + " for " + this + ". This probably means that the TCP connection was terminated.");
- // According to the socket channel javadoc section about "asynchronous reads" a socket channel's
- // read() may return -1 if the input side of a socket is shut down.
-
- // Note that we do not call notifyConnectionError() here because the connection may be
- // cleanly shutdown which would also cause read() to return '-1. I assume that this socket
- // will be selected again, on which read() would throw an IOException, which will be catched
- // and invoke notifyConnectionError() (see a few lines above).
- /*
- IOException exception = new IOException("NIO read() returned " + bytesRead);
- notifyConnectionError(exception);
- */
- return;
- }
-
- if (!pendingInputFilterData) {
- if (bytesRead == 0) {
- // Nothing more to read.
- break;
- }
- } else {
- pendingInputFilterData = false;
- }
-
- // We have successfully read something. It is now possible that a filter is now also able to write
- // additional data (for example SSLEngine).
- if (pendingWriteInterestAfterRead) {
- pendingWriteInterestAfterRead = false;
- newInterestedOps |= SelectionKey.OP_WRITE;
- }
-
- callbackBytesRead += bytesRead;
-
- ByteBuffer filteredIncomingBuffer = incomingBuffer;
- for (ListIterator it = connectionInternal.getXmppInputOutputFilterEndIterator(); it.hasPrevious();) {
- filteredIncomingBuffer.flip();
-
- ByteBuffer newFilteredIncomingBuffer;
- try {
- newFilteredIncomingBuffer = it.previous().input(filteredIncomingBuffer);
- } catch (IOException e) {
- connectionInternal.notifyConnectionError(e);
- return;
- }
- if (newFilteredIncomingBuffer == null) {
- break readLoop;
- }
- filteredIncomingBuffer = newFilteredIncomingBuffer;
- }
-
- final int bytesReadAfterFilter = filteredIncomingBuffer.flip().remaining();
-
- totalBytesReadAfterFilter += bytesReadAfterFilter;
-
- try {
- splitter.write(filteredIncomingBuffer);
- } catch (IOException e) {
- connectionInternal.notifyConnectionError(e);
- return;
- }
- }
- } finally {
- totalBytesWritten += callbackBytesWritten;
- totalBytesRead += callbackBytesRead;
-
- channelSelectedCallbackLock.unlock();
+ if (bytesRead < 0) {
+ LOGGER.finer("NIO read() returned " + bytesRead
+ + " for " + this + ". This probably means that the TCP connection was terminated.");
+ // According to the socket channel javadoc section about "asynchronous reads" a socket channel's
+ // read() may return -1 if the input side of a socket is shut down.
+ // Note that we do not call notifyConnectionError() here because the connection may be
+ // cleanly shutdown which would also cause read() to return '-1. I assume that this socket
+ // will be selected again, on which read() would throw an IOException, which will be catched
+ // and invoke notifyConnectionError() (see a few lines above).
+ /*
+ IOException exception = new IOException("NIO read() returned " + bytesRead);
+ notifyConnectionError(exception);
+ */
+ return;
}
- // Indicate that there is no reactor thread racing towards handling this selection key.
- final SelectionKeyAttachment selectionKeyAttachment = this.selectionKeyAttachment;
- if (selectionKeyAttachment != null) {
- selectionKeyAttachment.resetReactorThreadRacing();
+ if (!pendingInputFilterData) {
+ if (bytesRead == 0) {
+ // Nothing more to read.
+ break;
+ }
+ } else {
+ pendingInputFilterData = false;
}
- // Check the queue again to prevent lost wakeups caused by elements inserted before we
- // called resetReactorThreadRacing() a few lines above.
- if (!connectionInternal.outgoingElementsQueue.isEmpty()) {
- setWriteInterestAfterChannelSelectedCallback.incrementAndGet();
+ // We have successfully read something. It is now possible that a filter is now also able to write
+ // additional data (for example SSLEngine).
+ if (pendingWriteInterestAfterRead) {
+ pendingWriteInterestAfterRead = false;
newInterestedOps |= SelectionKey.OP_WRITE;
}
- connectionInternal.setInterestOps(selectionKey, newInterestedOps);
- };
+ callbackBytesRead += bytesRead;
+
+ ByteBuffer filteredIncomingBuffer = incomingBuffer;
+ for (ListIterator it = connectionInternal.getXmppInputOutputFilterEndIterator(); it.hasPrevious();) {
+ filteredIncomingBuffer.flip();
+
+ ByteBuffer newFilteredIncomingBuffer;
+ try {
+ newFilteredIncomingBuffer = it.previous().input(filteredIncomingBuffer);
+ } catch (IOException e) {
+ connectionInternal.notifyConnectionError(e);
+ return;
+ }
+ if (newFilteredIncomingBuffer == null) {
+ break readLoop;
+ }
+ filteredIncomingBuffer = newFilteredIncomingBuffer;
+ }
+
+ final int bytesReadAfterFilter = filteredIncomingBuffer.flip().remaining();
+
+ totalBytesReadAfterFilter += bytesReadAfterFilter;
+
+ try {
+ splitter.write(filteredIncomingBuffer);
+ } catch (IOException e) {
+ connectionInternal.notifyConnectionError(e);
+ return;
+ }
+ }
+ } finally {
+ totalBytesWritten += callbackBytesWritten;
+ totalBytesRead += callbackBytesRead;
+
+ channelSelectedCallbackLock.unlock();
+ }
+
+ // Indicate that there is no reactor thread racing towards handling this selection key.
+ final SelectionKeyAttachment selectionKeyAttachment = this.selectionKeyAttachment;
+ if (selectionKeyAttachment != null) {
+ selectionKeyAttachment.resetReactorThreadRacing();
+ }
+
+ // Check the queue again to prevent lost wakeups caused by elements inserted before we
+ // called resetReactorThreadRacing() a few lines above.
+ if (!connectionInternal.outgoingElementsQueue.isEmpty()) {
+ setWriteInterestAfterChannelSelectedCallback.incrementAndGet();
+ newInterestedOps |= SelectionKey.OP_WRITE;
+ }
+
+ connectionInternal.setInterestOps(selectionKey, newInterestedOps);
+ }
private void handleReadWriteIoException(IOException e) {
if (e instanceof ClosedChannelException && !tcpNioTransport.isConnected()) {
@@ -677,7 +670,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
}
@Override
- public Stats getStats() {
+ public XmppTcpTransportModule.Stats getStats() {
return XmppTcpTransportModule.this.getStats();
}
@@ -774,7 +767,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
remoteAddress = (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress();
selectionKey = connectionInternal.registerWithSelector(socketChannel, SelectionKey.OP_READ,
- channelSelectedCallback);
+ XmppTcpTransportModule.this::onChannelSelected);
selectionKeyAttachment = (SelectionKeyAttachment) selectionKey.attachment();
connectionInternal.setTransport(tcpNioTransport);
@@ -869,13 +862,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
ConnectionUnexpectedTerminatedException, NoResponseException, NotConnectedException {
connectionInternal.sendAndWaitForResponse(StartTls.INSTANCE, TlsProceed.class, TlsFailure.class);
- SmackTlsContext smackTlsContext;
- try {
- smackTlsContext = connectionInternal.getSmackTlsContext();
- } catch (KeyManagementException | UnrecoverableKeyException | NoSuchAlgorithmException
- | CertificateException | KeyStoreException | NoSuchProviderException e) {
- throw new SmackWrappedException(e);
- }
+ SmackTlsContext smackTlsContext = connectionInternal.getSmackTlsContext();
tlsState = new TlsState(smackTlsContext);
connectionInternal.addXmppInputOutputFilter(tlsState);
@@ -1316,7 +1303,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
pendingOutputFilterData = true;
}
- channelSelectedCallback.onChannelSelected(channel, key);
+ onChannelSelected(channel, key);
} finally {
channelSelectedCallbackLock.unlock();
}
@@ -1347,7 +1334,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
return CollectionUtil.removeUntil(buffers, b -> b.hasRemaining());
}
- public Stats getStats() {
+ public XmppTcpTransportModule.Stats getStats() {
return new Stats(this);
}
diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/IpTcpRemoteConnectionEndpoint.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/IpTcpRemoteConnectionEndpoint.java
index 2dabe1950..5f6a23ad5 100644
--- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/IpTcpRemoteConnectionEndpoint.java
+++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/IpTcpRemoteConnectionEndpoint.java
@@ -16,18 +16,14 @@
*/
package org.jivesoftware.smack.tcp.rce;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
import java.net.InetAddress;
import org.jivesoftware.smack.datatypes.UInt16;
import org.jivesoftware.smack.util.rce.SingleAddressRemoteConnectionEndpoint;
-import org.minidns.record.A;
-import org.minidns.record.AAAA;
import org.minidns.record.InternetAddressRR;
-public final class IpTcpRemoteConnectionEndpoint
+public final class IpTcpRemoteConnectionEndpoint>
implements Rfc6120TcpRemoteConnectionEndpoint, SingleAddressRemoteConnectionEndpoint {
private final CharSequence host;
@@ -42,17 +38,11 @@ public final class IpTcpRemoteConnectionEndpoint
this.internetAddressResourceRecord = internetAddressResourceRecord;
}
- public static IpTcpRemoteConnectionEndpoint from(CharSequence host, int port,
+ public static IpTcpRemoteConnectionEndpoint> from(CharSequence host, UInt16 port,
InetAddress inetAddress) {
- InternetAddressRR internetAddressResourceRecord;
- // TODO: Use InternetAddressRR.from(InetAddress) once MiniDNS is updated.
- if (inetAddress instanceof Inet4Address) {
- internetAddressResourceRecord = new A((Inet4Address) inetAddress);
- } else {
- internetAddressResourceRecord = new AAAA((Inet6Address) inetAddress);
- }
+ InternetAddressRR> internetAddressResourceRecord = InternetAddressRR.from(inetAddress);
- return new IpTcpRemoteConnectionEndpoint(host, UInt16.from(port),
+ return new IpTcpRemoteConnectionEndpoint>(host, port,
internetAddressResourceRecord);
}
diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/RemoteXmppTcpConnectionEndpoints.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/RemoteXmppTcpConnectionEndpoints.java
index 9328d0fe7..6b7da5ccf 100644
--- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/RemoteXmppTcpConnectionEndpoints.java
+++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/RemoteXmppTcpConnectionEndpoints.java
@@ -26,6 +26,7 @@ import java.util.logging.Logger;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode;
+import org.jivesoftware.smack.datatypes.UInt16;
import org.jivesoftware.smack.util.DNSUtil;
import org.jivesoftware.smack.util.dns.DNSResolver;
import org.jivesoftware.smack.util.rce.RemoteConnectionEndpoint;
@@ -61,7 +62,7 @@ public class RemoteXmppTcpConnectionEndpoints {
if (hostAddress != null) {
lookupFailures = Collections.emptyList();
- IpTcpRemoteConnectionEndpoint connectionEndpoint = IpTcpRemoteConnectionEndpoint.from(
+ IpTcpRemoteConnectionEndpoint> connectionEndpoint = IpTcpRemoteConnectionEndpoint.from(
hostAddress.toString(), config.getPort(), hostAddress);
discoveredRemoteConnectionEndpoints = Collections.singletonList(connectionEndpoint);
} else if (host != null) {
@@ -72,9 +73,9 @@ public class RemoteXmppTcpConnectionEndpoints {
if (hostAddresses != null) {
discoveredRemoteConnectionEndpoints = new ArrayList<>(hostAddresses.size());
- int port = config.getPort();
+ UInt16 port = config.getPort();
for (InetAddress inetAddress : hostAddresses) {
- IpTcpRemoteConnectionEndpoint connectionEndpoint = IpTcpRemoteConnectionEndpoint.from(
+ IpTcpRemoteConnectionEndpoint> connectionEndpoint = IpTcpRemoteConnectionEndpoint.from(
host, port, inetAddress);
discoveredRemoteConnectionEndpoints.add(connectionEndpoint);
}
@@ -198,13 +199,13 @@ public class RemoteXmppTcpConnectionEndpoints {
LOGGER.info("Could not resolve DNS SRV resource records for " + srvDomain + ". Consider adding those.");
}
- int defaultPort;
+ UInt16 defaultPort;
switch (domainType) {
case client:
- defaultPort = 5222;
+ defaultPort = UInt16.from(5222);
break;
case server:
- defaultPort = 5269;
+ defaultPort = UInt16.from(5269);
break;
default:
throw new AssertionError();
@@ -214,7 +215,7 @@ public class RemoteXmppTcpConnectionEndpoints {
List hostAddresses = dnsResolver.lookupHostAddress(domain, lookupFailures, dnssecMode);
if (hostAddresses != null) {
for (InetAddress inetAddress : hostAddresses) {
- IpTcpRemoteConnectionEndpoint endpoint = IpTcpRemoteConnectionEndpoint.from(domain, defaultPort, inetAddress);
+ IpTcpRemoteConnectionEndpoint> endpoint = IpTcpRemoteConnectionEndpoint.from(domain, defaultPort, inetAddress);
endpoints.add(endpoint);
}
}
diff --git a/smack-tcp/src/test/java/org/jivesoftware/smack/tcp/PacketWriterTest.java b/smack-tcp/src/test/java/org/jivesoftware/smack/tcp/PacketWriterTest.java
index 9658b9f7f..95f74bc60 100644
--- a/smack-tcp/src/test/java/org/jivesoftware/smack/tcp/PacketWriterTest.java
+++ b/smack-tcp/src/test/java/org/jivesoftware/smack/tcp/PacketWriterTest.java
@@ -52,12 +52,12 @@ public class PacketWriterTest {
* interrupt.
*
* @throws InterruptedException if the calling thread was interrupted.
- * @throws BrokenBarrierException
+ * @throws BrokenBarrierException in case of a broken barrier.
* @throws NotConnectedException if the XMPP connection is not connected.
* @throws XmppStringprepException if the provided string is invalid.
* @throws SecurityException if there was a security violation.
- * @throws NoSuchFieldException
- * @throws IllegalAccessException
+ * @throws NoSuchFieldException if there is no such field.
+ * @throws IllegalAccessException if there was an illegal access.
* @throws IllegalArgumentException if an illegal argument was given.
*/
@Test
diff --git a/version b/version
index 60c4355df..92560b19f 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-4.4.0-alpha3-SNAPSHOT
+4.4.0-alpha4-SNAPSHOT