Smack 4.1.3

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQF8BAABCgBmBQJVpgWiXxSAAAAAAC4AKGlzc3Vlci1mcHJAbm90YXRpb25zLm9w
 ZW5wZ3AuZmlmdGhob3JzZW1hbi5uZXQxMzU3QjAxODY1QjI1MDNDMTg0NTNEMjA4
 Q0FDMkE5Njc4NTQ4RTM1AAoJEIysKpZ4VI41G1gH+gIw/seXSSY6vYlVkYEFtR+e
 LV/LArN/eN1ZGc+WjN0EysRyqOBqF8HVHuyO7fF67huDRn62s7hufVY//NTctJ5L
 m4TXwaEUvgjdul7vm/dZcNRYr0jcSpDTFWx2egkOXt3qE9AhnpbnaIJ5c3q9VVVD
 aba88c3NS7quxp0hQm1SNEAmt1CCMPom7YkxdIPKWlLj8N5AF1UuSKwckLLYSUlS
 wloBbITb6EjI1IwszhN6e6o3W+7Pz/1zbFjk0CkKUS+TmhHhKil8TonH8Se/9DYD
 1SVHxvZa8LHWsU9G/R1Nhl69K2+GHEUbGmXalFmyPIf5ifhYyNimpx9krXQUuLs=
 =3/cn
 -----END PGP SIGNATURE-----

Merge tag '4.1.3'

Smack 4.1.3
This commit is contained in:
Florian Schmaus 2015-07-15 09:37:46 +02:00
commit 1c716bc1e0
5 changed files with 61 additions and 19 deletions

View File

@ -17,7 +17,7 @@ and then send them a text message:
```
// Assume we've created an XMPPConnection name "connection"._
ChatManager chatmanager = connection.getChatManager();
ChatManager chatmanager = ChatManager.getInstanceFor(connection);
Chat newChat = chatmanager.createChat("jsmith@jivesoftware.com", new MessageListener() {
public void processMessage(Chat chat, Message message) {
System.out.println("Received message: " + message);
@ -72,8 +72,9 @@ when it happens. You can register a message listener to receive all future
messages as part of this handler.
```
_// Assume we've created an XMPPConnection name "connection"._
ChatManager chatmanager = connection.getChatManager().addChatListener(
// Assume we've created an XMPPConnection name "connection"._
ChatManager chatManager = ChatManager.getInstanceFor(connection);
chatManager.addChatListener(
new ChatManagerListener() {
@Override
public void chatCreated(Chat chat, boolean createdLocally)

View File

@ -141,6 +141,19 @@ hr {
<div id="pageBody">
<h2>4.1.3 -- <span style="font-weight: normal;">2015-07-15</span></h2>
<h2> Bug
</h2>
<ul>
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-679'>SMACK-679</a>] - Memory leak in Socks5BytestreamManager. Should use weak map for &#39;managers&#39;
</li>
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-680'>SMACK-680</a>] - XHTML bodies are un-escaped after parsing
</li>
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-681'>SMACK-681</a>] - Roster presence callbacks may not be invoked right after login
</li>
</ul>
<h2>4.1.2 -- <span style="font-weight: normal;">2015-06-27</span></h2>
<h2> Bug

View File

@ -477,7 +477,7 @@ public class PacketParserUtils {
}
break;
case XmlPullParser.TEXT:
xml.append(parser.getText());
xml.escape(parser.getText());
break;
}
event = parser.next();
@ -493,7 +493,12 @@ public class PacketParserUtils {
// Only append the text if the parser is not on on an empty element' start tag. Empty elements are reported
// twice, so in order to prevent duplication we only add their text when we are on their end tag.
if (!(event == XmlPullParser.START_TAG && parser.isEmptyElementTag())) {
sb.append(parser.getText());
CharSequence text = parser.getText();
if (event == XmlPullParser.TEXT) {
// TODO the toString() can be removed in Smack 4.2.
text = StringUtils.escapeForXML(text.toString());
}
sb.append(text);
}
if (event == XmlPullParser.END_TAG && parser.getDepth() <= depth) {
break outerloop;

View File

@ -20,13 +20,13 @@ import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeoutException;
@ -113,7 +113,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
private final static Random randomGenerator = new Random();
/* stores one Socks5BytestreamManager for each XMPP connection */
private final static Map<XMPPConnection, Socks5BytestreamManager> managers = new HashMap<XMPPConnection, Socks5BytestreamManager>();
private final static Map<XMPPConnection, Socks5BytestreamManager> managers = new WeakHashMap<>();
/*
* assigns a user to a listener that is informed if a bytestream request for this user is

View File

@ -159,9 +159,16 @@ public final class Roster extends Manager {
*/
private final Object rosterListenersAndEntriesLock = new Object();
// The roster is marked as initialized when at least a single roster packet
// has been received and processed.
private boolean loaded = false;
private enum RosterState {
uninitialized,
loading,
loaded,
}
/**
* The current state of the roster.
*/
private RosterState rosterState = RosterState.uninitialized;
private final PresencePacketListener presencePacketListener = new PresencePacketListener();
@ -338,9 +345,11 @@ public final class Roster extends Manager {
if (rosterStore != null && isRosterVersioningSupported()) {
packet.setVersion(rosterStore.getRosterVersion());
}
rosterState = RosterState.loading;
connection.sendIqWithResponseCallback(packet, new RosterResultListener(), new ExceptionCallback() {
@Override
public void processException(Exception exception) {
rosterState = RosterState.uninitialized;
Level logLevel;
if (exception instanceof NotConnectedException) {
logLevel = Level.FINE;
@ -384,16 +393,15 @@ public final class Roster extends Manager {
return true;
}
boolean waitUntilLoaded() throws InterruptedException {
final XMPPConnection connection = connection();
while (!loaded) {
long waitTime = connection.getPacketReplyTimeout();
long start = System.currentTimeMillis();
protected boolean waitUntilLoaded() throws InterruptedException {
long waitTime = connection().getPacketReplyTimeout();
long start = System.currentTimeMillis();
while (!isLoaded()) {
if (waitTime <= 0) {
break;
}
synchronized (this) {
if (!loaded) {
if (!isLoaded()) {
wait(waitTime);
}
}
@ -411,7 +419,7 @@ public final class Roster extends Manager {
* @since 4.1
*/
public boolean isLoaded() {
return loaded;
return rosterState == RosterState.loaded;
}
/**
@ -1059,7 +1067,7 @@ public final class Roster extends Manager {
}
}
}
loaded = false;
rosterState = RosterState.uninitialized;
}
/**
@ -1270,6 +1278,21 @@ public final class Roster extends Manager {
@Override
public void processPacket(Stanza packet) throws NotConnectedException, InterruptedException {
// Try to ensure that the roster is loaded when processing presence stanzas. While the
// presence listener is synchronous, the roster result listener is not, which means that
// the presence listener may be invoked with a not yet loaded roster.
if (rosterState == RosterState.loading) {
try {
waitUntilLoaded();
}
catch (InterruptedException e) {
LOGGER.log(Level.INFO, "Presence listener was interrupted", e);
}
}
if (!isLoaded()) {
LOGGER.warning("Roster not loaded while processing presence stanza");
}
Presence presence = (Presence) packet;
Jid from = presence.getFrom();
Resourcepart fromResource = Resourcepart.EMPTY;
@ -1409,7 +1432,7 @@ public final class Roster extends Manager {
}
}
loaded = true;
rosterState = RosterState.loaded;
synchronized (Roster.this) {
Roster.this.notifyAll();
}