mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-26 05:52:06 +01:00
Compare commits
25 commits
daab6039a1
...
0cd3318b12
Author | SHA1 | Date | |
---|---|---|---|
|
0cd3318b12 | ||
|
a23adfab6e | ||
|
007a04c4fe | ||
|
8e88cd2e31 | ||
|
3450ffad2b | ||
|
dfae6770af | ||
|
653d9dbba7 | ||
|
c83d717a26 | ||
|
7723230589 | ||
|
a9b88d7517 | ||
|
1dd68336eb | ||
3521346c90 | |||
|
989dbb14e8 | ||
|
b1cd5066f6 | ||
|
d6e25730d0 | ||
|
a619135960 | ||
|
03fc5eb785 | ||
|
9246ea5dca | ||
|
9c4e5d0330 | ||
|
c31e93a00f | ||
|
7059b60672 | ||
|
8e52e80399 | ||
|
3ded023629 | ||
|
29af92cbd1 | ||
|
3d3d89612f |
17 changed files with 174 additions and 57 deletions
7
.github/pull_request_template.md
vendored
Normal file
7
.github/pull_request_template.md
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
Thank you for your contribution!
|
||||||
|
|
||||||
|
Before creating a Pull Request, please make sure to
|
||||||
|
* read https://github.com/igniterealtime/Smack/wiki/Guidelines-for-Smack-Developers-and-Contributors
|
||||||
|
* run `gradle check` successfully in order to make sure that your code does not break any JUnit tests and is conform to the projects code style.
|
||||||
|
* (if applicable) mention any Jira issue codes (eg. `SMACK-XXX`) in the *body* of your commit message (not the header), so that Jira automatically links the PR to the issue.
|
||||||
|
* squash your commits if possible/sensible.
|
|
@ -80,6 +80,7 @@ debugger=console
|
||||||
### Where to place the properties file
|
### Where to place the properties file
|
||||||
|
|
||||||
The framework will first load the properties file from `~/.config/smack-integration-test/properties`
|
The framework will first load the properties file from `~/.config/smack-integration-test/properties`
|
||||||
|
|
||||||
Overview of the components
|
Overview of the components
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,7 @@ This API is considered beta quality."""
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':smack-core')
|
compile project(':smack-core')
|
||||||
compile 'org.igniterealtime.jbosh:jbosh:[0.9,0.10)'
|
// See https://issues.igniterealtime.org/browse/SMACK-858 and
|
||||||
|
// comment in version.gradle why the specify the version this way.
|
||||||
|
compile 'org.igniterealtime.jbosh:jbosh:[0.9.1,0.9.999]'
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package org.jivesoftware.smack.bosh;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jivesoftware.smack.ConnectionConfiguration;
|
import org.jivesoftware.smack.ConnectionConfiguration;
|
||||||
import org.jivesoftware.smack.proxy.ProxyInfo;
|
import org.jivesoftware.smack.proxy.ProxyInfo;
|
||||||
|
@ -34,6 +36,7 @@ public final class BOSHConfiguration extends ConnectionConfiguration {
|
||||||
|
|
||||||
private final boolean https;
|
private final boolean https;
|
||||||
private final String file;
|
private final String file;
|
||||||
|
private Map<String, String> httpHeaders;
|
||||||
|
|
||||||
private BOSHConfiguration(Builder builder) {
|
private BOSHConfiguration(Builder builder) {
|
||||||
super(builder);
|
super(builder);
|
||||||
|
@ -49,6 +52,7 @@ public final class BOSHConfiguration extends ConnectionConfiguration {
|
||||||
} else {
|
} else {
|
||||||
file = builder.file;
|
file = builder.file;
|
||||||
}
|
}
|
||||||
|
httpHeaders = builder.httpHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isProxyEnabled() {
|
public boolean isProxyEnabled() {
|
||||||
|
@ -76,6 +80,10 @@ public final class BOSHConfiguration extends ConnectionConfiguration {
|
||||||
return new URI((https ? "https://" : "http://") + this.host + ":" + this.port + file);
|
return new URI((https ? "https://" : "http://") + this.host + ":" + this.port + file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getHttpHeaders() {
|
||||||
|
return httpHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
@ -83,6 +91,7 @@ public final class BOSHConfiguration extends ConnectionConfiguration {
|
||||||
public static final class Builder extends ConnectionConfiguration.Builder<Builder, BOSHConfiguration> {
|
public static final class Builder extends ConnectionConfiguration.Builder<Builder, BOSHConfiguration> {
|
||||||
private boolean https;
|
private boolean https;
|
||||||
private String file;
|
private String file;
|
||||||
|
private Map<String, String> httpHeaders = new HashMap<>();
|
||||||
|
|
||||||
private Builder() {
|
private Builder() {
|
||||||
}
|
}
|
||||||
|
@ -101,6 +110,11 @@ public final class BOSHConfiguration extends ConnectionConfiguration {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder addHttpHeader(String name, String value) {
|
||||||
|
httpHeaders.put(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BOSHConfiguration build() {
|
public BOSHConfiguration build() {
|
||||||
return new BOSHConfiguration(this);
|
return new BOSHConfiguration(this);
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.io.PipedReader;
|
||||||
import java.io.PipedWriter;
|
import java.io.PipedWriter;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@ -157,8 +158,13 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
||||||
if (config.isProxyEnabled()) {
|
if (config.isProxyEnabled()) {
|
||||||
cfgBuilder.setProxy(config.getProxyAddress(), config.getProxyPort());
|
cfgBuilder.setProxy(config.getProxyAddress(), config.getProxyPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
cfgBuilder.setCompressionEnabled(config.isCompressionEnabled());
|
cfgBuilder.setCompressionEnabled(config.isCompressionEnabled());
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> h : config.getHttpHeaders().entrySet()) {
|
||||||
|
cfgBuilder.addHttpHeader(h.getKey(), h.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
client = BOSHClient.create(cfgBuilder.build());
|
client = BOSHClient.create(cfgBuilder.build());
|
||||||
|
|
||||||
client.addBOSHClientConnListener(new BOSHConnectionListener());
|
client.addBOSHClientConnListener(new BOSHConnectionListener());
|
||||||
|
|
|
@ -858,9 +858,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
|
|
||||||
ASYNC_BUT_ORDERED.performAsyncButOrdered(this, () -> {
|
ASYNC_BUT_ORDERED.performAsyncButOrdered(this, () -> {
|
||||||
currentConnectionException = exception;
|
currentConnectionException = exception;
|
||||||
synchronized (AbstractXMPPConnection.this) {
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (StanzaCollector collector : collectors) {
|
for (StanzaCollector collector : collectors) {
|
||||||
collector.notifyConnectionError(exception);
|
collector.notifyConnectionError(exception);
|
||||||
|
@ -873,10 +870,14 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
// XMPPTCPConnection. Create delegation method?
|
// XMPPTCPConnection. Create delegation method?
|
||||||
// maybeCompressFeaturesReceived.reportGenericFailure(smackWrappedException);
|
// maybeCompressFeaturesReceived.reportGenericFailure(smackWrappedException);
|
||||||
|
|
||||||
// Closes the connection temporary. A if the connection supports stream management, then a reconnection is
|
synchronized (AbstractXMPPConnection.this) {
|
||||||
// possible. Note that a connection listener of e.g. XMPPTCPConnection will drop the SM state in
|
notifyAll();
|
||||||
// case the Exception is a StreamErrorException.
|
|
||||||
instantShutdown();
|
// Closes the connection temporary. A if the connection supports stream management, then a reconnection is
|
||||||
|
// possible. Note that a connection listener of e.g. XMPPTCPConnection will drop the SM state in
|
||||||
|
// case the Exception is a StreamErrorException.
|
||||||
|
instantShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
Async.go(() -> {
|
Async.go(() -> {
|
||||||
// Notify connection listeners of the error.
|
// Notify connection listeners of the error.
|
||||||
|
|
|
@ -58,7 +58,7 @@ class HTTPProxySocketConnection implements ProxySocketConnection {
|
||||||
proxyLine = "\r\nProxy-Authorization: Basic " + Base64.encode(username + ":" + password);
|
proxyLine = "\r\nProxy-Authorization: Basic " + Base64.encode(username + ":" + password);
|
||||||
}
|
}
|
||||||
socket.getOutputStream().write((hostport + " HTTP/1.1\r\nHost: "
|
socket.getOutputStream().write((hostport + " HTTP/1.1\r\nHost: "
|
||||||
+ hostport + proxyLine + "\r\n\r\n").getBytes("UTF-8"));
|
+ host + ":" + port + proxyLine + "\r\n\r\n").getBytes("UTF-8"));
|
||||||
|
|
||||||
InputStream in = socket.getInputStream();
|
InputStream in = socket.getInputStream();
|
||||||
StringBuilder got = new StringBuilder(100);
|
StringBuilder got = new StringBuilder(100);
|
||||||
|
@ -115,7 +115,8 @@ class HTTPProxySocketConnection implements ProxySocketConnection {
|
||||||
int code = Integer.parseInt(m.group(1));
|
int code = Integer.parseInt(m.group(1));
|
||||||
|
|
||||||
if (code != HttpURLConnection.HTTP_OK) {
|
if (code != HttpURLConnection.HTTP_OK) {
|
||||||
throw new ProxyException(ProxyInfo.ProxyType.HTTP);
|
throw new ProxyException(ProxyInfo.ProxyType.HTTP,
|
||||||
|
"Error code in proxy response: " + code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,8 +152,11 @@ public final class MultiUserChatManager extends Manager {
|
||||||
|
|
||||||
private AutoJoinFailedCallback autoJoinFailedCallback;
|
private AutoJoinFailedCallback autoJoinFailedCallback;
|
||||||
|
|
||||||
|
private final ServiceDiscoveryManager serviceDiscoveryManager;
|
||||||
|
|
||||||
private MultiUserChatManager(XMPPConnection connection) {
|
private MultiUserChatManager(XMPPConnection connection) {
|
||||||
super(connection);
|
super(connection);
|
||||||
|
serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||||
// Listens for all messages that include a MUCUser extension and fire the invitation
|
// Listens for all messages that include a MUCUser extension and fire the invitation
|
||||||
// listeners if the message includes an invitation.
|
// listeners if the message includes an invitation.
|
||||||
StanzaListener invitationPacketListener = new StanzaListener() {
|
StanzaListener invitationPacketListener = new StanzaListener() {
|
||||||
|
@ -277,7 +280,7 @@ public final class MultiUserChatManager extends Manager {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
public boolean isServiceEnabled(Jid user) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
public boolean isServiceEnabled(Jid user) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
return ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(user, MUCInitialPresence.NAMESPACE);
|
return serviceDiscoveryManager.supportsFeature(user, MUCInitialPresence.NAMESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -304,7 +307,7 @@ public final class MultiUserChatManager extends Manager {
|
||||||
public List<EntityBareJid> getJoinedRooms(EntityJid user) throws NoResponseException, XMPPErrorException,
|
public List<EntityBareJid> getJoinedRooms(EntityJid user) throws NoResponseException, XMPPErrorException,
|
||||||
NotConnectedException, InterruptedException {
|
NotConnectedException, InterruptedException {
|
||||||
// Send the disco packet to the user
|
// Send the disco packet to the user
|
||||||
DiscoverItems result = ServiceDiscoveryManager.getInstanceFor(connection()).discoverItems(user, DISCO_NODE);
|
DiscoverItems result = serviceDiscoveryManager.discoverItems(user, DISCO_NODE);
|
||||||
List<DiscoverItems.Item> items = result.getItems();
|
List<DiscoverItems.Item> items = result.getItems();
|
||||||
List<EntityBareJid> answer = new ArrayList<>(items.size());
|
List<EntityBareJid> answer = new ArrayList<>(items.size());
|
||||||
// Collect the entityID for each returned item
|
// Collect the entityID for each returned item
|
||||||
|
@ -331,7 +334,7 @@ public final class MultiUserChatManager extends Manager {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
public RoomInfo getRoomInfo(EntityBareJid room) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
public RoomInfo getRoomInfo(EntityBareJid room) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection()).discoverInfo(room);
|
DiscoverInfo info = serviceDiscoveryManager.discoverInfo(room);
|
||||||
return new RoomInfo(info);
|
return new RoomInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,8 +348,7 @@ public final class MultiUserChatManager extends Manager {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
public List<DomainBareJid> getMucServiceDomains() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
public List<DomainBareJid> getMucServiceDomains() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection());
|
return serviceDiscoveryManager.findServices(MUCInitialPresence.NAMESPACE, false, false);
|
||||||
return sdm.findServices(MUCInitialPresence.NAMESPACE, false, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -379,7 +381,7 @@ public final class MultiUserChatManager extends Manager {
|
||||||
*/
|
*/
|
||||||
public boolean providesMucService(DomainBareJid domainBareJid) throws NoResponseException,
|
public boolean providesMucService(DomainBareJid domainBareJid) throws NoResponseException,
|
||||||
XMPPErrorException, NotConnectedException, InterruptedException {
|
XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
return ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(domainBareJid,
|
return serviceDiscoveryManager.supportsFeature(domainBareJid,
|
||||||
MUCInitialPresence.NAMESPACE);
|
MUCInitialPresence.NAMESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,8 +404,7 @@ public final class MultiUserChatManager extends Manager {
|
||||||
if (!providesMucService(serviceName)) {
|
if (!providesMucService(serviceName)) {
|
||||||
throw new NotAMucServiceException(serviceName);
|
throw new NotAMucServiceException(serviceName);
|
||||||
}
|
}
|
||||||
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection());
|
DiscoverItems discoverItems = serviceDiscoveryManager.discoverItems(serviceName);
|
||||||
DiscoverItems discoverItems = discoManager.discoverItems(serviceName);
|
|
||||||
List<DiscoverItems.Item> items = discoverItems.getItems();
|
List<DiscoverItems.Item> items = discoverItems.getItems();
|
||||||
|
|
||||||
Map<EntityBareJid, HostedRoom> answer = new HashMap<>(items.size());
|
Map<EntityBareJid, HostedRoom> answer = new HashMap<>(items.size());
|
||||||
|
|
|
@ -447,6 +447,19 @@ public final class PingManager extends Manager {
|
||||||
pingFuture.onError(new ExceptionCallback<Exception>() {
|
pingFuture.onError(new ExceptionCallback<Exception>() {
|
||||||
@Override
|
@Override
|
||||||
public void processException(Exception exception) {
|
public void processException(Exception exception) {
|
||||||
|
long lastStanzaReceived = connection.getLastStanzaReceived();
|
||||||
|
if (lastStanzaReceived > 0) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
// Delta since the last stanza was received
|
||||||
|
int deltaInSeconds = (int) ((now - lastStanzaReceived) / 1000);
|
||||||
|
// If the delta is smaller then the ping interval, we have got an valid stanza in time
|
||||||
|
// So not error notification needed
|
||||||
|
if (deltaInSeconds < pingInterval) {
|
||||||
|
maybeSchedulePingServerTask(deltaInSeconds);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (PingFailedListener l : pingFailedListeners) {
|
for (PingFailedListener l : pingFailedListeners) {
|
||||||
l.pingFailed();
|
l.pingFailed();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2003-2007 Jive Software, 2016-2017 Florian Schmaus.
|
* Copyright 2003-2007 Jive Software, 2016-2019 Florian Schmaus.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -629,14 +629,40 @@ public final class Roster extends Manager {
|
||||||
* @throws NotLoggedInException If not logged in.
|
* @throws NotLoggedInException If not logged in.
|
||||||
* @throws NotConnectedException
|
* @throws NotConnectedException
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
|
* @deprecated use {@link #createItemAndRequestSubscription(BareJid, String, String[])} instead.
|
||||||
*/
|
*/
|
||||||
|
// TODO: Remove in Smack 4.5.
|
||||||
|
@Deprecated
|
||||||
public void createEntry(BareJid user, String name, String[] groups) throws NotLoggedInException, NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
public void createEntry(BareJid user, String name, String[] groups) throws NotLoggedInException, NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
|
createItemAndRequestSubscription(user, name, groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new roster item. The server will asynchronously update the roster with the subscription status.
|
||||||
|
* <p>
|
||||||
|
* There will be no presence subscription request. Consider using
|
||||||
|
* {@link #createItemAndRequestSubscription(BareJid, String, String[])} if you also want to request a presence
|
||||||
|
* subscription from the contact.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param jid the XMPP address of the contact (e.g. johndoe@jabber.org)
|
||||||
|
* @param name the nickname of the user.
|
||||||
|
* @param groups the list of group names the entry will belong to, or <tt>null</tt> if the the roster entry won't
|
||||||
|
* belong to a group.
|
||||||
|
* @throws NoResponseException if there was no response from the server.
|
||||||
|
* @throws XMPPErrorException if an XMPP exception occurs.
|
||||||
|
* @throws NotLoggedInException If not logged in.
|
||||||
|
* @throws NotConnectedException
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @since 4.4.0
|
||||||
|
*/
|
||||||
|
public void createItem(BareJid jid, String name, String[] groups) throws NotLoggedInException, NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
final XMPPConnection connection = getAuthenticatedConnectionOrThrow();
|
final XMPPConnection connection = getAuthenticatedConnectionOrThrow();
|
||||||
|
|
||||||
// Create and send roster entry creation packet.
|
// Create and send roster entry creation packet.
|
||||||
RosterPacket rosterPacket = new RosterPacket();
|
RosterPacket rosterPacket = new RosterPacket();
|
||||||
rosterPacket.setType(IQ.Type.set);
|
rosterPacket.setType(IQ.Type.set);
|
||||||
RosterPacket.Item item = new RosterPacket.Item(user, name);
|
RosterPacket.Item item = new RosterPacket.Item(jid, name);
|
||||||
if (groups != null) {
|
if (groups != null) {
|
||||||
for (String group : groups) {
|
for (String group : groups) {
|
||||||
if (group != null && group.trim().length() > 0) {
|
if (group != null && group.trim().length() > 0) {
|
||||||
|
@ -646,8 +672,27 @@ public final class Roster extends Manager {
|
||||||
}
|
}
|
||||||
rosterPacket.addRosterItem(item);
|
rosterPacket.addRosterItem(item);
|
||||||
connection.createStanzaCollectorAndSend(rosterPacket).nextResultOrThrow();
|
connection.createStanzaCollectorAndSend(rosterPacket).nextResultOrThrow();
|
||||||
|
}
|
||||||
|
|
||||||
sendSubscriptionRequest(user);
|
/**
|
||||||
|
* Creates a new roster entry and presence subscription. The server will asynchronously
|
||||||
|
* update the roster with the subscription status.
|
||||||
|
*
|
||||||
|
* @param jid the XMPP address of the contact (e.g. johndoe@jabber.org)
|
||||||
|
* @param name the nickname of the user.
|
||||||
|
* @param groups the list of group names the entry will belong to, or <tt>null</tt> if the
|
||||||
|
* the roster entry won't belong to a group.
|
||||||
|
* @throws NoResponseException if there was no response from the server.
|
||||||
|
* @throws XMPPErrorException if an XMPP exception occurs.
|
||||||
|
* @throws NotLoggedInException If not logged in.
|
||||||
|
* @throws NotConnectedException
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @since 4.4.0
|
||||||
|
*/
|
||||||
|
public void createItemAndRequestSubscription(BareJid jid, String name, String[] groups) throws NotLoggedInException, NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
|
createItem(jid, name, groups);
|
||||||
|
|
||||||
|
sendSubscriptionRequest(jid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -668,7 +713,7 @@ public final class Roster extends Manager {
|
||||||
*/
|
*/
|
||||||
public void preApproveAndCreateEntry(BareJid user, String name, String[] groups) throws NotLoggedInException, NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, FeatureNotSupportedException {
|
public void preApproveAndCreateEntry(BareJid user, String name, String[] groups) throws NotLoggedInException, NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, FeatureNotSupportedException {
|
||||||
preApprove(user);
|
preApprove(user);
|
||||||
createEntry(user, name, groups);
|
createItemAndRequestSubscription(user, name, groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -164,7 +164,7 @@ public class RosterTest extends InitSmackIm {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
serverSimulator.start();
|
serverSimulator.start();
|
||||||
roster.createEntry(contactJID, contactName, contactGroup);
|
roster.createItemAndRequestSubscription(contactJID, contactName, contactGroup);
|
||||||
serverSimulator.join();
|
serverSimulator.join();
|
||||||
|
|
||||||
// Check if an error occurred within the simulator
|
// Check if an error occurred within the simulator
|
||||||
|
@ -430,7 +430,7 @@ public class RosterTest extends InitSmackIm {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
serverSimulator.start();
|
serverSimulator.start();
|
||||||
roster.createEntry(contactJID, contactName, contactGroup);
|
roster.createItemAndRequestSubscription(contactJID, contactName, contactGroup);
|
||||||
serverSimulator.join();
|
serverSimulator.join();
|
||||||
|
|
||||||
// Check if an error occurred within the simulator
|
// Check if an error occurred within the simulator
|
||||||
|
|
|
@ -299,10 +299,32 @@ public class XmppConnectionStressTest {
|
||||||
|
|
||||||
private ErrorsWhileSendingOrReceivingException(Map<XMPPConnection, Exception> sendExceptions,
|
private ErrorsWhileSendingOrReceivingException(Map<XMPPConnection, Exception> sendExceptions,
|
||||||
Map<XMPPConnection, Exception> receiveExceptions) {
|
Map<XMPPConnection, Exception> receiveExceptions) {
|
||||||
super("Exceptions while sending and/or receiving");
|
super(createMessageFrom(sendExceptions, receiveExceptions));
|
||||||
this.sendExceptions = sendExceptions;
|
this.sendExceptions = sendExceptions;
|
||||||
this.receiveExceptions = receiveExceptions;
|
this.receiveExceptions = receiveExceptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String createMessageFrom(Map<XMPPConnection, Exception> sendExceptions,
|
||||||
|
Map<XMPPConnection, Exception> receiveExceptions) {
|
||||||
|
StringBuilder sb = new StringBuilder(1024);
|
||||||
|
sb.append("Exceptions while sending and/or receiving.");
|
||||||
|
|
||||||
|
if (!sendExceptions.isEmpty()) {
|
||||||
|
sb.append(" Send exxceptions: ");
|
||||||
|
for (Map.Entry<XMPPConnection, Exception> entry : sendExceptions.entrySet()) {
|
||||||
|
sb.append(entry.getKey()).append(": ").append(entry.getValue()).append(';');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!receiveExceptions.isEmpty()) {
|
||||||
|
sb.append(" Receive exceptions: ");
|
||||||
|
for (Map.Entry<XMPPConnection, Exception> entry : receiveExceptions.entrySet()) {
|
||||||
|
sb.append(entry.getKey()).append(": ").append(entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2015-2018 Florian Schmaus
|
* Copyright 2015-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,11 +25,13 @@ import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||||
import org.jivesoftware.smack.packet.Presence;
|
import org.jivesoftware.smack.packet.Presence;
|
||||||
import org.jivesoftware.smack.roster.AbstractPresenceEventListener;
|
import org.jivesoftware.smack.roster.AbstractPresenceEventListener;
|
||||||
|
import org.jivesoftware.smack.roster.PresenceEventListener;
|
||||||
import org.jivesoftware.smack.roster.Roster;
|
import org.jivesoftware.smack.roster.Roster;
|
||||||
import org.jivesoftware.smack.roster.RosterEntry;
|
import org.jivesoftware.smack.roster.RosterEntry;
|
||||||
import org.jivesoftware.smack.roster.SubscribeListener;
|
import org.jivesoftware.smack.roster.SubscribeListener;
|
||||||
|
|
||||||
import org.jxmpp.jid.BareJid;
|
import org.jxmpp.jid.BareJid;
|
||||||
|
import org.jxmpp.jid.EntityFullJid;
|
||||||
import org.jxmpp.jid.Jid;
|
import org.jxmpp.jid.Jid;
|
||||||
|
|
||||||
public class IntegrationTestRosterUtil {
|
public class IntegrationTestRosterUtil {
|
||||||
|
@ -39,41 +41,47 @@ public class IntegrationTestRosterUtil {
|
||||||
ensureSubscribedTo(conTwo, conOne, timeout);
|
ensureSubscribedTo(conTwo, conOne, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ensureSubscribedTo(final XMPPConnection conOne, final XMPPConnection conTwo, long timeout) throws TimeoutException, Exception {
|
public static void ensureSubscribedTo(final XMPPConnection presenceRequestReceiverConnection, final XMPPConnection presenceRequestingConnection, long timeout) throws TimeoutException, Exception {
|
||||||
Roster rosterOne = Roster.getInstanceFor(conOne);
|
final Roster presenceRequestReceiverRoster = Roster.getInstanceFor(presenceRequestReceiverConnection);
|
||||||
Roster rosterTwo = Roster.getInstanceFor(conTwo);
|
final Roster presenceRequestingRoster = Roster.getInstanceFor(presenceRequestingConnection);
|
||||||
|
|
||||||
if (rosterOne.isSubscribedToMyPresence(conTwo.getUser())) {
|
final EntityFullJid presenceRequestReceiverAddress = presenceRequestReceiverConnection.getUser();
|
||||||
|
final EntityFullJid presenceRequestingAddress = presenceRequestingConnection.getUser();
|
||||||
|
|
||||||
|
if (presenceRequestReceiverRoster.isSubscribedToMyPresence(presenceRequestingAddress)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final SubscribeListener subscribeListener = new SubscribeListener() {
|
final SubscribeListener subscribeListener = new SubscribeListener() {
|
||||||
@Override
|
@Override
|
||||||
public SubscribeAnswer processSubscribe(Jid from, Presence subscribeRequest) {
|
public SubscribeAnswer processSubscribe(Jid from, Presence subscribeRequest) {
|
||||||
if (from.equals(conTwo.getUser().asBareJid())) {
|
if (from.equals(presenceRequestingConnection.getUser().asBareJid())) {
|
||||||
return SubscribeAnswer.Approve;
|
return SubscribeAnswer.Approve;
|
||||||
}
|
}
|
||||||
return SubscribeAnswer.Deny;
|
return SubscribeAnswer.Deny;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
rosterOne.addSubscribeListener(subscribeListener);
|
presenceRequestReceiverRoster.addSubscribeListener(subscribeListener);
|
||||||
|
|
||||||
final SimpleResultSyncPoint syncPoint = new SimpleResultSyncPoint();
|
final SimpleResultSyncPoint syncPoint = new SimpleResultSyncPoint();
|
||||||
rosterTwo.addPresenceEventListener(new AbstractPresenceEventListener() {
|
final PresenceEventListener presenceEventListener = new AbstractPresenceEventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void presenceSubscribed(BareJid address, Presence subscribedPresence) {
|
public void presenceSubscribed(BareJid address, Presence subscribedPresence) {
|
||||||
if (!address.equals(conOne.getUser().asBareJid())) {
|
if (!address.equals(presenceRequestReceiverAddress.asBareJid())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
syncPoint.signal();
|
syncPoint.signal();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
rosterTwo.sendSubscriptionRequest(conOne.getUser().asBareJid());
|
presenceRequestingRoster.addPresenceEventListener(presenceEventListener);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
presenceRequestingRoster.sendSubscriptionRequest(presenceRequestReceiverAddress.asBareJid());
|
||||||
|
|
||||||
syncPoint.waitForResult(timeout);
|
syncPoint.waitForResult(timeout);
|
||||||
} finally {
|
} finally {
|
||||||
rosterOne.removeSubscribeListener(subscribeListener);
|
presenceRequestReceiverRoster.removeSubscribeListener(subscribeListener);
|
||||||
|
presenceRequestingRoster.removePresenceEventListener(presenceEventListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,12 +42,9 @@ public class LowLevelRosterIntegrationTest extends AbstractSmackLowLevelIntegrat
|
||||||
final Roster rosterOne = Roster.getInstanceFor(conOne);
|
final Roster rosterOne = Roster.getInstanceFor(conOne);
|
||||||
final Roster rosterTwo = Roster.getInstanceFor(conTwo);
|
final Roster rosterTwo = Roster.getInstanceFor(conTwo);
|
||||||
|
|
||||||
// TODO create Roster.createEntry() with boolean flag for subscribe or not.
|
rosterOne.createItem(conTwo.getUser().asBareJid(), "Con Two", null);
|
||||||
rosterOne.createEntry(conTwo.getUser().asBareJid(), "Con Two", null);
|
rosterTwo.createItem(conOne.getUser().asBareJid(), "Con One", null);
|
||||||
rosterTwo.createEntry(conOne.getUser().asBareJid(), "Con One", null);
|
|
||||||
|
|
||||||
// TODO Change timeout form '5000' to something configurable.
|
|
||||||
final long timeout = 5000;
|
|
||||||
IntegrationTestRosterUtil.ensureBothAccountsAreSubscribedToEachOther(conOne, conTwo, timeout);
|
IntegrationTestRosterUtil.ensureBothAccountsAreSubscribedToEachOther(conOne, conTwo, timeout);
|
||||||
|
|
||||||
final SimpleResultSyncPoint offlineTriggered = new SimpleResultSyncPoint();
|
final SimpleResultSyncPoint offlineTriggered = new SimpleResultSyncPoint();
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class RosterIntegrationTest extends AbstractSmackIntegrationTest {
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
rosterOne.createEntry(conTwo.getUser().asBareJid(), conTwosRosterName, null);
|
rosterOne.createItemAndRequestSubscription(conTwo.getUser().asBareJid(), conTwosRosterName, null);
|
||||||
|
|
||||||
assertTrue(addedAndSubscribed.waitForResult(2 * connection.getReplyTimeout()));
|
assertTrue(addedAndSubscribed.waitForResult(2 * connection.getReplyTimeout()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub, 2019 Florian Schmaus.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -18,9 +18,6 @@ package org.jivesoftware.smackx.mood;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.XMPPException;
|
import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
|
||||||
|
|
||||||
import org.jivesoftware.smackx.mood.element.MoodElement;
|
|
||||||
|
|
||||||
import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
|
import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
|
||||||
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||||
|
@ -28,7 +25,6 @@ import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
||||||
import org.igniterealtime.smack.inttest.util.IntegrationTestRosterUtil;
|
import org.igniterealtime.smack.inttest.util.IntegrationTestRosterUtil;
|
||||||
import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
|
import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.jxmpp.jid.BareJid;
|
|
||||||
|
|
||||||
public class MoodIntegrationTest extends AbstractSmackIntegrationTest {
|
public class MoodIntegrationTest extends AbstractSmackIntegrationTest {
|
||||||
|
|
||||||
|
@ -47,18 +43,20 @@ public class MoodIntegrationTest extends AbstractSmackIntegrationTest {
|
||||||
|
|
||||||
final SimpleResultSyncPoint moodReceived = new SimpleResultSyncPoint();
|
final SimpleResultSyncPoint moodReceived = new SimpleResultSyncPoint();
|
||||||
|
|
||||||
mm2.addMoodListener(new MoodListener() {
|
final MoodListener moodListener = (jid, message, moodElement) -> {
|
||||||
@Override
|
if (moodElement.getMood() == Mood.satisfied) {
|
||||||
public void onMoodUpdated(BareJid jid, Message message, MoodElement moodElement) {
|
moodReceived.signal();
|
||||||
if (moodElement.getMood() == Mood.satisfied) {
|
|
||||||
moodReceived.signal();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
mm2.addMoodListener(moodListener);
|
||||||
|
|
||||||
mm1.setMood(Mood.satisfied);
|
try {
|
||||||
|
mm1.setMood(Mood.satisfied);
|
||||||
|
|
||||||
moodReceived.waitForResult(timeout);
|
moodReceived.waitForResult(timeout);
|
||||||
|
} finally {
|
||||||
|
mm2.removeMoodListener(moodListener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
|
|
|
@ -609,6 +609,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
proxyInfo.getProxySocketConnection().connect(socket, host, port, timeout);
|
proxyInfo.getProxySocketConnection().connect(socket, host, port, timeout);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
hostAddress.setException(e);
|
hostAddress.setException(e);
|
||||||
|
failedAddresses.add(hostAddress);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
LOGGER.finer("Established TCP connection to " + hostAndPort);
|
LOGGER.finer("Established TCP connection to " + hostAndPort);
|
||||||
|
|
Loading…
Reference in a new issue