diff --git a/resources/releasedocs/changelog.html b/resources/releasedocs/changelog.html
index 4d51e4594..77450e326 100644
--- a/resources/releasedocs/changelog.html
+++ b/resources/releasedocs/changelog.html
@@ -141,6 +141,24 @@ hr {
+
4.3.1 -- 2018-10-14
+
+
Bug
+
+
+- [SMACK-833] - XMLUtil.prettyFormatXml() throws on some Android devices
+
+
+
+
Improvement
+
+
+- [SMACK-829] - Disconnect BOSH client on shutdown
+
+- [SMACK-838] - FormField.getFirstValue() throws IndexOutOfBoundsException if there are no values
+
+
+
4.3.0 -- 2018-08-02
Bug
diff --git a/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java b/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java
index 441b2bdf6..d5bf5c4a4 100644
--- a/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java
+++ b/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java
@@ -254,6 +254,16 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
*/
@Override
protected void shutdown() {
+
+ if (client != null) {
+ try {
+ client.disconnect();
+ } catch (Exception e) {
+ LOGGER.log(Level.WARNING, "shutdown", e);
+ }
+ client = null;
+ }
+
setWasAuthenticated();
sessionID = null;
done = true;
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlUtil.java
index 7fc081b43..b55297d6e 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlUtil.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlUtil.java
@@ -35,7 +35,11 @@ public class XmlUtil {
private static final TransformerFactory transformerFactory = TransformerFactory.newInstance();
static {
- transformerFactory.setAttribute("indent-number", 2);
+ try {
+ transformerFactory.setAttribute("indent-number", 2);
+ } catch (IllegalArgumentException e) {
+ LOGGER.log(Level.INFO, "XML TransformerFactory does not support indent-number attribute", e);
+ }
}
public static String prettyFormatXml(CharSequence xml) {
diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/MamManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/MamManager.java
index dceb0f7f7..55846e6ce 100644
--- a/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/MamManager.java
+++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/MamManager.java
@@ -116,7 +116,7 @@ import org.jxmpp.jid.Jid;
* MamQueryArgs mamQueryArgs = MamQueryArgs.builder()
* .withJid(jid)
* .setResultPageSize(10)
- * .queryRecentPage()
+ * .queryLastPage()
* .build();
* MamQuery mamQuery = mamManager.queryArchive(mamQueryArgs);
* }
@@ -435,6 +435,14 @@ public final class MamManager extends Manager {
return this;
}
+ /**
+ * Query from the last, i.e. most recent, page of the archive. This will return the very last page of the
+ * archive holding the most recent matching messages. You usually would page backwards from there on.
+ *
+ * @return a reference to this builder.
+ * @see XEP-0059 ยง 2.5. Requesting the Last Page in
+ * a Result Set
+ */
public Builder queryLastPage() {
return beforeUid("");
}
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java
index 09f9b5892..ee9edd84c 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java
@@ -204,7 +204,10 @@ public class MultiUserChat {
@Override
public void processStanza(final Stanza packet) {
final Presence presence = (Presence) packet;
- final EntityFullJid from = presence.getFrom().asEntityFullJidOrThrow();
+ final EntityFullJid from = presence.getFrom().asEntityFullJidIfPossible();
+ if (from == null) {
+ return;
+ }
final EntityFullJid myRoomJID = myRoomJid;
final boolean isUserStatusModification = presence.getFrom().equals(myRoomJID);
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java
index 8c5a98ccd..33e36e76b 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java
@@ -19,6 +19,7 @@ package org.jivesoftware.smackx.muc;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -392,19 +393,46 @@ public final class MultiUserChatManager extends Manager {
* @throws NotConnectedException
* @throws InterruptedException
* @throws NotAMucServiceException
+ * @deprecated use {@link #getRoomsHostedBy(DomainBareJid)} instead.
*/
+ @Deprecated
+ // TODO: Remove in Smack 4.4.
public List getHostedRooms(DomainBareJid serviceName) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException, NotAMucServiceException {
+ Map hostedRooms = getRoomsHostedBy(serviceName);
+ return new ArrayList<>(hostedRooms.values());
+ }
+
+ /**
+ * Returns a Map of HostedRooms where each HostedRoom has the XMPP address of the room and the room's name.
+ * Once discovered the rooms hosted by a chat service it is possible to discover more detailed room information or
+ * join the room.
+ *
+ * @param serviceName the service that is hosting the rooms to discover.
+ * @return a map from the room's address to its HostedRoom information.
+ * @throws XMPPErrorException
+ * @throws NoResponseException
+ * @throws NotConnectedException
+ * @throws InterruptedException
+ * @throws NotAMucServiceException
+ * @since 4.3.1
+ */
+ public Map getRoomsHostedBy(DomainBareJid serviceName) throws NoResponseException, XMPPErrorException,
+ NotConnectedException, InterruptedException, NotAMucServiceException {
if (!providesMucService(serviceName)) {
throw new NotAMucServiceException(serviceName);
}
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection());
DiscoverItems discoverItems = discoManager.discoverItems(serviceName);
List items = discoverItems.getItems();
- List answer = new ArrayList(items.size());
+
+ Map answer = new HashMap<>(items.size());
for (DiscoverItems.Item item : items) {
- answer.add(new HostedRoom(item));
+ HostedRoom hostedRoom = new HostedRoom(item);
+ HostedRoom previousRoom = answer.put(hostedRoom.getJid(), hostedRoom);
+ assert previousRoom == null;
}
+
return answer;
}
diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java
index 83f882a3c..323d8cc16 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java
@@ -261,12 +261,14 @@ public class FormField implements NamedElement {
*/
public String getFirstValue() {
CharSequence firstValue;
+
synchronized (values) {
+ if (values.isEmpty()) {
+ return null;
+ }
firstValue = values.get(0);
}
- if (firstValue == null) {
- return null;
- }
+
return firstValue.toString();
}
diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java
index c4e7a0cf2..8e241151d 100644
--- a/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java
+++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java
@@ -951,8 +951,7 @@ public final class Roster extends Manager {
// This is used in case no available presence is found
Presence unavailable = null;
- for (Resourcepart resource : userPresences.keySet()) {
- Presence p = userPresences.get(resource);
+ for (Presence p : userPresences.values()) {
if (!p.isAvailable()) {
unavailable = p;
continue;