mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-10-31 17:25:58 +01:00
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:
commit
1c716bc1e0
5 changed files with 61 additions and 19 deletions
|
@ -17,7 +17,7 @@ and then send them a text message:
|
||||||
|
|
||||||
```
|
```
|
||||||
// Assume we've created an XMPPConnection name "connection"._
|
// 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() {
|
Chat newChat = chatmanager.createChat("jsmith@jivesoftware.com", new MessageListener() {
|
||||||
public void processMessage(Chat chat, Message message) {
|
public void processMessage(Chat chat, Message message) {
|
||||||
System.out.println("Received 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.
|
messages as part of this handler.
|
||||||
|
|
||||||
```
|
```
|
||||||
_// Assume we've created an XMPPConnection name "connection"._
|
// Assume we've created an XMPPConnection name "connection"._
|
||||||
ChatManager chatmanager = connection.getChatManager().addChatListener(
|
ChatManager chatManager = ChatManager.getInstanceFor(connection);
|
||||||
|
chatManager.addChatListener(
|
||||||
new ChatManagerListener() {
|
new ChatManagerListener() {
|
||||||
@Override
|
@Override
|
||||||
public void chatCreated(Chat chat, boolean createdLocally)
|
public void chatCreated(Chat chat, boolean createdLocally)
|
||||||
|
|
|
@ -141,6 +141,19 @@ hr {
|
||||||
|
|
||||||
<div id="pageBody">
|
<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 'managers'
|
||||||
|
</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>4.1.2 -- <span style="font-weight: normal;">2015-06-27</span></h2>
|
||||||
|
|
||||||
<h2> Bug
|
<h2> Bug
|
||||||
|
|
|
@ -477,7 +477,7 @@ public class PacketParserUtils {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.TEXT:
|
case XmlPullParser.TEXT:
|
||||||
xml.append(parser.getText());
|
xml.escape(parser.getText());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
event = parser.next();
|
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
|
// 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.
|
// 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())) {
|
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) {
|
if (event == XmlPullParser.END_TAG && parser.getDepth() <= depth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
|
|
|
@ -20,13 +20,13 @@ import java.io.IOException;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
|
||||||
private final static Random randomGenerator = new Random();
|
private final static Random randomGenerator = new Random();
|
||||||
|
|
||||||
/* stores one Socks5BytestreamManager for each XMPP connection */
|
/* 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
|
* assigns a user to a listener that is informed if a bytestream request for this user is
|
||||||
|
|
|
@ -159,9 +159,16 @@ public final class Roster extends Manager {
|
||||||
*/
|
*/
|
||||||
private final Object rosterListenersAndEntriesLock = new Object();
|
private final Object rosterListenersAndEntriesLock = new Object();
|
||||||
|
|
||||||
// The roster is marked as initialized when at least a single roster packet
|
private enum RosterState {
|
||||||
// has been received and processed.
|
uninitialized,
|
||||||
private boolean loaded = false;
|
loading,
|
||||||
|
loaded,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current state of the roster.
|
||||||
|
*/
|
||||||
|
private RosterState rosterState = RosterState.uninitialized;
|
||||||
|
|
||||||
private final PresencePacketListener presencePacketListener = new PresencePacketListener();
|
private final PresencePacketListener presencePacketListener = new PresencePacketListener();
|
||||||
|
|
||||||
|
@ -338,9 +345,11 @@ public final class Roster extends Manager {
|
||||||
if (rosterStore != null && isRosterVersioningSupported()) {
|
if (rosterStore != null && isRosterVersioningSupported()) {
|
||||||
packet.setVersion(rosterStore.getRosterVersion());
|
packet.setVersion(rosterStore.getRosterVersion());
|
||||||
}
|
}
|
||||||
|
rosterState = RosterState.loading;
|
||||||
connection.sendIqWithResponseCallback(packet, new RosterResultListener(), new ExceptionCallback() {
|
connection.sendIqWithResponseCallback(packet, new RosterResultListener(), new ExceptionCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void processException(Exception exception) {
|
public void processException(Exception exception) {
|
||||||
|
rosterState = RosterState.uninitialized;
|
||||||
Level logLevel;
|
Level logLevel;
|
||||||
if (exception instanceof NotConnectedException) {
|
if (exception instanceof NotConnectedException) {
|
||||||
logLevel = Level.FINE;
|
logLevel = Level.FINE;
|
||||||
|
@ -384,16 +393,15 @@ public final class Roster extends Manager {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean waitUntilLoaded() throws InterruptedException {
|
protected boolean waitUntilLoaded() throws InterruptedException {
|
||||||
final XMPPConnection connection = connection();
|
long waitTime = connection().getPacketReplyTimeout();
|
||||||
while (!loaded) {
|
long start = System.currentTimeMillis();
|
||||||
long waitTime = connection.getPacketReplyTimeout();
|
while (!isLoaded()) {
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
if (waitTime <= 0) {
|
if (waitTime <= 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!loaded) {
|
if (!isLoaded()) {
|
||||||
wait(waitTime);
|
wait(waitTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,7 +419,7 @@ public final class Roster extends Manager {
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public boolean isLoaded() {
|
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
|
@Override
|
||||||
public void processPacket(Stanza packet) throws NotConnectedException, InterruptedException {
|
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;
|
Presence presence = (Presence) packet;
|
||||||
Jid from = presence.getFrom();
|
Jid from = presence.getFrom();
|
||||||
Resourcepart fromResource = Resourcepart.EMPTY;
|
Resourcepart fromResource = Resourcepart.EMPTY;
|
||||||
|
@ -1409,7 +1432,7 @@ public final class Roster extends Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded = true;
|
rosterState = RosterState.loaded;
|
||||||
synchronized (Roster.this) {
|
synchronized (Roster.this) {
|
||||||
Roster.this.notifyAll();
|
Roster.this.notifyAll();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue