From 12cbeede57c195042111b000d41277b3fd3b8be5 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Sat, 3 Aug 2019 22:15:44 +0200 Subject: [PATCH 1/4] Use Enum.toString() in XmlStringBuilder.element(String, Enum) as toString() is often overriden by Enums to yield the expected XMPP wire protocol representation. --- .../main/java/org/jivesoftware/smack/util/XmlStringBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java index 56e6eb177..4f0b93680 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java @@ -112,7 +112,7 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element { public XmlStringBuilder element(String name, Enum content) { assert content != null; - element(name, content.name()); + element(name, content.toString()); return this; } From 6a0e0f0f67b3faaa4c4061ba4de6f0c298c424a8 Mon Sep 17 00:00:00 2001 From: Georg Lukas Date: Fri, 26 Jul 2019 15:02:47 +0200 Subject: [PATCH 2/4] Implement xml:lang support in ConnectionConfiguration and AbstractXMPPConnection This patch makes it possible to change the stream-level language as part of the connection configuration, to allow a properly implemented entities to provide i18n'ed response messages. The Locale type is used for this configuration, and the effective language string can be obtained via `ConnectionConfiguration.getXmlLang()`. This code does not cover XMPPBOSHConnection! Signed-off-by: Georg Lukas --- .../smack/AbstractXMPPConnection.java | 2 +- .../smack/ConnectionConfiguration.java | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index 883812f59..eff83268d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -2012,7 +2012,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { from = XmppStringUtils.completeJidFrom(localpart, to); } String id = getStreamId(); - sendNonza(new StreamOpen(to, from, id)); + sendNonza(new StreamOpen(to, from, id, config.getXmlLang(), StreamOpen.StreamContentNamespace.client)); } public static final class SmackTlsContext { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java index 730320132..e99b04ce6 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.Locale; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -118,6 +119,8 @@ public abstract class ConnectionConfiguration { private final String password; private final Resourcepart resource; + private final Locale language; + /** * The optional SASL authorization identity (see RFC 6120 § 6.3.8). */ @@ -165,6 +168,8 @@ public abstract class ConnectionConfiguration { // Resource can be null, this means that the server must provide one resource = builder.resource; + language = builder.language; + xmppServiceDomain = builder.xmppServiceDomain; if (xmppServiceDomain == null) { throw new IllegalArgumentException("Must define the XMPP domain"); @@ -476,6 +481,34 @@ public abstract class ConnectionConfiguration { return resource; } + /** + * Returns the stream language to use when connecting to the server. + * + * @return the stream language to use when connecting to the server. + */ + public Locale getLanguage() { + return language; + } + + /** + * Returns the xml:lang string of the stream language to use when connecting to the server. + * + *

If the developer sets the language to null, this will also return null, leading to + * the removal of the xml:lang tag from the stream. If a Locale("") is configured, this will + * return "", which can be used as an override.

+ * + * @return the stream language to use when connecting to the server. + */ + public String getXmlLang() { + // TODO: Change to Locale.toLanguageTag() once Smack's minimum Android API level is 21 or higher. + // This will need a workaround for new Locale("").getLanguageTag() returning "und". Expected + // behavior of this function: + // - returns null if language is null + // - returns "" if language.getLanguage() returns the empty string + // - returns language.toLanguageTag() otherwise + return language != null ? language.toString().replace("_", "-") : null; + } + /** * Returns the optional XMPP address to be requested as the SASL authorization identity. * @@ -564,6 +597,7 @@ public abstract class ConnectionConfiguration { private CharSequence username; private String password; private Resourcepart resource; + private Locale language = Locale.ENGLISH; private boolean sendPresence = true; private ProxyInfo proxy; private CallbackHandler callbackHandler; @@ -688,6 +722,19 @@ public abstract class ConnectionConfiguration { return getThis(); } + /** + * Set the stream language. + * + * @param language the language to use. + * @return a reference to this builder. + * @see RFC 6120 § 4.7.4 + * @see XML 1.0 § 2.12 Language Identification + */ + public B setLanguage(Locale language) { + this.language = language; + return getThis(); + } + /** * Set the resource we are requesting from the server. * From efb206f7bd6d7951ad025e59201cae4733a87e10 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Sat, 3 Aug 2019 22:20:05 +0200 Subject: [PATCH 3/4] Use Locale.getDefault() to initialize the language --- .../java/org/jivesoftware/smack/ConnectionConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java index e99b04ce6..e302a1159 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java @@ -597,7 +597,7 @@ public abstract class ConnectionConfiguration { private CharSequence username; private String password; private Resourcepart resource; - private Locale language = Locale.ENGLISH; + private Locale language = Locale.getDefault(); private boolean sendPresence = true; private ProxyInfo proxy; private CallbackHandler callbackHandler; From 3e74d11b45fc796984dcc2e8142c3bafad2919fe Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Sat, 3 Aug 2019 22:25:21 +0200 Subject: [PATCH 4/4] Disable MucMemoryLeakTest Although it it not that unreliable, it causes false negatives once in a while. This is because the standard Java SE API does not provide a way to force a *full* garbage collection run, we need to resort to unreliable hacks to trigger one. The test itself is still useful to diagnose or refute alleged memory leaks. This commit also move the test from JUnit 4 to Junit 5. --- .../java/org/jivesoftware/smackx/muc/MucMemoryLeakTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/muc/MucMemoryLeakTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/muc/MucMemoryLeakTest.java index ad7c24ebd..d9e35fefd 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/muc/MucMemoryLeakTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/muc/MucMemoryLeakTest.java @@ -19,12 +19,14 @@ package org.jivesoftware.smackx.muc; import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smack.util.MemoryLeakTestUtil; -import org.junit.Test; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.jxmpp.stringprep.XmppStringprepException; public class MucMemoryLeakTest extends SmackTestSuite { @Test + @Disabled public void mucMemoryLeakTest() throws XmppStringprepException, IllegalArgumentException, InterruptedException { MemoryLeakTestUtil.noResourceLeakTest(c -> MultiUserChatManager.getInstanceFor(c)); }