1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-09-10 09:39:39 +02:00

Merge branch '4.2'

This commit is contained in:
Florian Schmaus 2017-11-22 08:37:47 +01:00
commit 81002c4fbd
63 changed files with 391 additions and 266 deletions

View file

@ -17,6 +17,7 @@
package org.jivesoftware.smackx.bytestreams.ibb;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.NotLoggedInException;
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
import org.jivesoftware.smack.packet.IQ;
@ -65,7 +66,7 @@ class DataListener extends AbstractIqRequestHandler {
ibbSession.processIQPacket(data);
}
}
catch (NotConnectedException | InterruptedException e) {
catch (NotConnectedException | InterruptedException | NotLoggedInException e) {
return null;
}
return null;

View file

@ -25,6 +25,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.NotLoggedInException;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.AndFilter;
@ -847,8 +848,9 @@ public class InBandBytestreamSession implements BytestreamSession {
* @param data
* @throws NotConnectedException
* @throws InterruptedException
* @throws NotLoggedInException
*/
public void processIQPacket(Data data) throws NotConnectedException, InterruptedException {
public void processIQPacket(Data data) throws NotConnectedException, InterruptedException, NotLoggedInException {
inputStream.dataPacketListener.processStanza(data);
}

View file

@ -27,7 +27,6 @@ import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.ConnectionCreationListener;
@ -766,6 +765,25 @@ public final class ServiceDiscoveryManager extends Manager {
*/
public List<DiscoverInfo> findServicesDiscoverInfo(String feature, boolean stopOnFirst, boolean useCache)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
return findServicesDiscoverInfo(feature, stopOnFirst, useCache, null);
}
/**
* Find all services under the users service that provide a given feature.
*
* @param feature the feature to search for
* @param stopOnFirst if true, stop searching after the first service was found
* @param useCache if true, query a cache first to avoid network I/O
* @param encounteredExceptions an optional map which will be filled with the exceptions encountered
* @return a possible empty list of services providing the given feature
* @throws NoResponseException
* @throws XMPPErrorException
* @throws NotConnectedException
* @throws InterruptedException
* @since 4.2.2
*/
public List<DiscoverInfo> findServicesDiscoverInfo(String feature, boolean stopOnFirst, boolean useCache, Map<? super Jid, Exception> encounteredExceptions)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
List<DiscoverInfo> serviceDiscoInfo = null;
DomainBareJid serviceName = connection().getXMPPServiceDomain();
if (useCache) {
@ -780,8 +798,9 @@ public final class ServiceDiscoveryManager extends Manager {
try {
info = discoverInfo(serviceName);
} catch (XMPPErrorException e) {
// Be extra robust here: Return the empty linked list and log this situation
LOGGER.log(Level.WARNING, "Could not discover information about service", e);
if (encounteredExceptions != null) {
encounteredExceptions.put(serviceName, e);
}
return serviceDiscoInfo;
}
// Check if the server supports the feature
@ -800,25 +819,27 @@ public final class ServiceDiscoveryManager extends Manager {
// Get the disco items and send the disco packet to each server item
items = discoverItems(serviceName);
} catch (XMPPErrorException e) {
LOGGER.log(Level.WARNING, "Could not discover items about service", e);
if (encounteredExceptions != null) {
encounteredExceptions.put(serviceName, e);
}
return serviceDiscoInfo;
}
for (DiscoverItems.Item item : items.getItems()) {
Jid address = item.getEntityID();
try {
// TODO is it OK here in all cases to query without the node attribute?
// MultipleRecipientManager queried initially also with the node attribute, but this
// could be simply a fault instead of intentional.
info = discoverInfo(item.getEntityID());
info = discoverInfo(address);
}
catch (XMPPErrorException | NoResponseException e) {
// Don't throw this exceptions if one of the server's items fail
LOGGER.log(Level.WARNING, "Exception while discovering info for feature " + feature
+ " of " + item.getEntityID() + " node: " + item.getNode(), e);
if (encounteredExceptions != null) {
encounteredExceptions.put(address, e);
}
continue;
}
if (info.containsFeature(feature)) {
serviceDiscoInfo.add(info);
//serviceAddresses.add(item.getEntityID().asDomainBareJid());
if (stopOnFirst) {
break;
}

View file

@ -303,7 +303,7 @@ public class OutgoingFileTransfer extends FileTransfer {
transferThread = new Thread(new Runnable() {
@Override
public void run() {
//Create packet filter
// Create packet filter.
try {
outputStream = negotiateStream(fileName, fileSize, description);
} catch (XMPPErrorException e) {

View file

@ -84,7 +84,7 @@ public final class JingleManager extends Manager {
JingleSessionHandler sessionHandler = jingleSessionHandlers.get(fullJidAndSessionId);
if (sessionHandler != null) {
//Handle existing session
// Handle existing session
return sessionHandler.handleJingleSessionRequest(jingle);
}
@ -96,19 +96,19 @@ public final class JingleManager extends Manager {
description.getNamespace());
if (jingleDescriptionHandler == null) {
//Unsupported Application
// Unsupported Application
LOGGER.log(Level.WARNING, "Unsupported Jingle application.");
return jutil.createSessionTerminateUnsupportedApplications(fullFrom, sid);
}
return jingleDescriptionHandler.handleJingleRequest(jingle);
}
//Unknown session
// Unknown session
LOGGER.log(Level.WARNING, "Unknown session.");
return jutil.createErrorUnknownSession(jingle);
}
});
//Register transports.
// Register transports.
JingleTransportMethodManager transportMethodManager = JingleTransportMethodManager.getInstanceFor(connection);
transportMethodManager.registerTransportManager(JingleIBBTransportManager.getInstanceFor(connection));
transportMethodManager.registerTransportManager(JingleS5BTransportManager.getInstanceFor(connection));

View file

@ -59,6 +59,6 @@ public final class JingleIBBTransportManager extends JingleTransportManager<Jing
@Override
public void authenticated(XMPPConnection connection, boolean resumed) {
//Nothing to do.
// Nothing to do.
}
}

View file

@ -105,7 +105,7 @@ public class JingleIBBTransportSession extends JingleTransportSession<JingleIBBT
@Override
public IQ handleTransportInfo(Jingle transportInfo) {
return IQ.createResultIQ(transportInfo);
//TODO
// TODO
}
@Override

View file

@ -77,7 +77,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
.setStreamId(sid).setMode(mode).setDestinationAddress(
Socks5Utils.createDigest(sid, jingleSession.getLocal(), jingleSession.getRemote()));
//Local host
// Local host
if (JingleS5BTransportManager.isUseLocalCandidates()) {
for (Bytestream.StreamHost host : transportManager().getLocalStreamHosts()) {
jb.addTransportCandidate(new JingleS5BTransportCandidate(host, 100, JingleS5BTransportCandidate.Type.direct));
@ -204,7 +204,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
case JingleS5BTransportInfo.ProxyError.ELEMENT:
return handleProxyError(transportInfo);
}
//We should never go here, but lets be gracious...
// We should never go here, but lets be gracious...
return IQ.createResultIQ(transportInfo);
}
@ -239,7 +239,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
}
public IQ handleProxyError(Jingle jingle) {
//TODO
// TODO
return IQ.createResultIQ(jingle);
}
@ -265,7 +265,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
LOGGER.log(Level.INFO, "Ready.");
//Determine nominated candidate.
// Determine nominated candidate.
UsedCandidate nominated;
if (ourChoice != CANDIDATE_FAILURE && theirChoice != CANDIDATE_FAILURE) {
if (ourChoice.candidate.getPriority() > theirChoice.candidate.getPriority()) {
@ -288,7 +288,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
nominated = connectToOurCandidate(nominated.candidate);
} catch (InterruptedException | IOException | XMPPException | SmackException | TimeoutException e) {
LOGGER.log(Level.INFO, "Could not connect to our candidate.", e);
//TODO: Proxy-Error
// TODO: Proxy-Error
return;
}
@ -326,7 +326,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
callback.onSessionInitiated(bs);
}
//Our choice
// Our choice
else {
LOGGER.log(Level.INFO, "Our choice, so their candidate was used.");
boolean isProxy = nominated.candidate.getType() == JingleS5BTransportCandidate.Type.proxy;

View file

@ -333,7 +333,7 @@ public class MultiUserChat {
new NotFilter(MessageWithThreadFilter.INSTANCE))
);
// @formatter:on
connection.addSyncStanzaListener(declinesListener, DECLINE_FILTER);
connection.addSyncStanzaListener(declinesListener, new AndFilter(fromRoomFilter, DECLINE_FILTER));
connection.addPacketInterceptor(presenceInterceptor, new AndFilter(ToMatchesFilter.create(room),
StanzaTypeFilter.PRESENCE));
messageCollector = connection.createStanzaCollector(fromRoomGroupchatFilter);
@ -727,20 +727,19 @@ public class MultiUserChat {
* @throws InterruptedException
*/
public synchronized void leave() throws NotConnectedException, InterruptedException {
// If not joined already, do nothing.
if (!joined) {
return;
}
// Note that this method is intentionally not guarded by
// "if (!joined) return" because it should be always be possible to leave the room in case the instance's
// state does not reflect the actual state.
// Reset occupant information first so that we are assume that we left the room even if sendStanza() would
// throw.
userHasLeft();
// We leave a room by sending a presence packet where the "to"
// field is in the form "roomName@service/nickname"
Presence leavePresence = new Presence(Presence.Type.unavailable);
leavePresence.setTo(JidCreate.fullFrom(room, nickname));
connection.sendStanza(leavePresence);
// Reset occupant information.
occupantsMap.clear();
nickname = null;
joined = false;
userHasLeft();
}
/**
@ -878,12 +877,21 @@ public class MultiUserChat {
Destroy destroy = new Destroy(alternateJID, reason);
iq.setDestroy(destroy);
connection.createStanzaCollectorAndSend(iq).nextResultOrThrow();
try {
connection.createStanzaCollectorAndSend(iq).nextResultOrThrow();
}
catch (XMPPErrorException e) {
// Note that we do not call userHasLeft() here because an XMPPErrorException would usually indicate that the
// room was not destroyed and we therefore we also did not leave the room.
throw e;
}
catch (NoResponseException | NotConnectedException | InterruptedException e) {
// Reset occupant information.
userHasLeft();
throw e;
}
// Reset occupant information.
occupantsMap.clear();
nickname = null;
joined = false;
userHasLeft();
}
@ -2011,6 +2019,7 @@ public class MultiUserChat {
private void removeConnectionCallbacks() {
connection.removeSyncStanzaListener(messageListener);
connection.removeSyncStanzaListener(presenceListener);
connection.removeSyncStanzaListener(subjectListener);
connection.removeSyncStanzaListener(declinesListener);
connection.removePacketInterceptor(presenceInterceptor);
if (messageCollector != null) {
@ -2023,6 +2032,11 @@ public class MultiUserChat {
* Remove all callbacks and resources necessary when the user has left the room for some reason.
*/
private synchronized void userHasLeft() {
// We do not reset nickname here, in case this method has been called erroneously, it should still be possible
// to call leave() in order to resync the state. And leave() requires the nickname to send the unsubscribe
// presence.
occupantsMap.clear();
joined = false;
// Update the list of joined rooms
multiUserChatManager.removeJoinedRoom(room);
removeConnectionCallbacks();
@ -2340,15 +2354,12 @@ public class MultiUserChat {
if (statusCodes.contains(Status.KICKED_307)) {
// Check if this occupant was kicked
if (isUserModification) {
joined = false;
// Reset occupant information.
userHasLeft();
for (UserStatusListener listener : userStatusListeners) {
listener.kicked(mucUser.getItem().getActor(), mucUser.getItem().getReason());
}
// Reset occupant information.
occupantsMap.clear();
nickname = null;
userHasLeft();
}
else {
for (ParticipantStatusListener listener : participantStatusListeners) {
@ -2397,7 +2408,7 @@ public class MultiUserChat {
listener.nicknameChanged(from, mucUser.getItem().getNick());
}
}
//The room has been destroyed
// The room has been destroyed.
if (mucUser.getDestroy() != null) {
MultiUserChat alternateMUC = multiUserChatManager.getMultiUserChat(mucUser.getDestroy().getJid());
for (UserStatusListener listener : userStatusListeners) {

View file

@ -19,6 +19,8 @@ package org.jivesoftware.smackx.offline;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
@ -58,6 +60,8 @@ import org.jivesoftware.smackx.xdata.Form;
*/
public class OfflineMessageManager {
private static final Logger LOGGER = Logger.getLogger(OfflineMessageManager.class.getName());
private final static String namespace = "http://jabber.org/protocol/offline";
private final XMPPConnection connection;
@ -144,7 +148,7 @@ public class OfflineMessageManager {
* @throws InterruptedException
*/
public List<Message> getMessages(final List<String> nodes) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
List<Message> messages = new ArrayList<Message>();
List<Message> messages = new ArrayList<Message>(nodes.size());
OfflineMessageRequest request = new OfflineMessageRequest();
for (String node : nodes) {
OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
@ -165,12 +169,17 @@ public class OfflineMessageManager {
try {
connection.createStanzaCollectorAndSend(request).nextResultOrThrow();
// Collect the received offline messages
Message message = messageCollector.nextResult();
while (message != null && pendingNodes > 0) {
pendingNodes--;
messages.add(message);
Message message;
do {
message = messageCollector.nextResult();
}
if (message != null) {
messages.add(message);
pendingNodes--;
} else if (message == null && pendingNodes > 0) {
LOGGER.log(Level.WARNING,
"Did not receive all expected offline messages. " + pendingNodes + " are missing.");
}
} while (message != null && pendingNodes > 0);
}
finally {
// Stop queuing offline messages

View file

@ -704,7 +704,7 @@ public class VCard extends IQ {
}
private boolean hasContent() {
//noinspection OverlyComplexBooleanExpression
// noinspection OverlyComplexBooleanExpression
return hasNameField()
|| hasOrganizationFields()
|| emailHome != null

View file

@ -55,8 +55,8 @@ public class VersionTest extends InitExtensions {
assertTrue(replyPacket instanceof Version);
Version reply = (Version) replyPacket;
//getFrom check is pending for SMACK-547
//assertEquals("juliet@capulet.lit/balcony", reply.getFrom());
// getFrom check is pending for SMACK-547
// assertEquals("juliet@capulet.lit/balcony", reply.getFrom());
assertThat("capulet.lit", equalsCharSequence(reply.getTo()));
assertEquals("s2c1", reply.getStanzaId());
assertEquals(IQ.Type.result, reply.getType());

View file

@ -124,7 +124,7 @@ public class PingTest extends InitExtensions {
@Test
public void checkFailedPingToEntityError() throws Exception {
ThreadedDummyConnection threadedCon = getAuthentiactedDummyConnection();
//@formatter:off
// @formatter:off
String reply =
"<iq type='error' id='qrzSp-16' to='test@myserver.com'>" +
"<ping xmlns='urn:xmpp:ping'/>" +
@ -132,7 +132,7 @@ public class PingTest extends InitExtensions {
"<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>" +
"</error>" +
"</iq>";
//@formatter:on
// @formatter:on
IQ serviceUnavailable = (IQ) PacketParserUtils.parseStanza(reply);
threadedCon.addIQReply(serviceUnavailable);
@ -160,7 +160,7 @@ public class PingTest extends InitExtensions {
@Test
public void checkPingToServerError() throws Exception {
ThreadedDummyConnection con = getAuthentiactedDummyConnection();
//@formatter:off
// @formatter:off
String reply =
"<iq type='error' id='qrzSp-16' to='test@myserver.com' from='" + con.getXMPPServiceDomain() + "'>" +
"<ping xmlns='urn:xmpp:ping'/>" +
@ -168,7 +168,7 @@ public class PingTest extends InitExtensions {
"<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>" +
"</error>" +
"</iq>";
//@formatter:on
// @formatter:on
IQ serviceUnavailable = (IQ) PacketParserUtils.parseStanza(reply);
con.addIQReply(serviceUnavailable);
@ -194,13 +194,13 @@ public class PingTest extends InitExtensions {
DiscoverInfo info = new DiscoverInfo();
info.addFeature(Ping.NAMESPACE);
//@formatter:off
// @formatter:off
String reply =
"<iq type='result' id='qrzSp-16' to='test@myserver.com'>" +
"<query xmlns='http://jabber.org/protocol/disco#info'><identity category='client' type='pc' name='Pidgin'/>" +
"<feature var='urn:xmpp:ping'/>" +
"</query></iq>";
//@formatter:on
// @formatter:on
IQ discoReply = (IQ) PacketParserUtils.parseStanza(reply);
con.addIQReply(discoReply);
@ -216,13 +216,13 @@ public class PingTest extends InitExtensions {
DiscoverInfo info = new DiscoverInfo();
info.addFeature(Ping.NAMESPACE);
//@formatter:off
// @formatter:off
String reply =
"<iq type='result' id='qrzSp-16' to='test@myserver.com'>" +
"<query xmlns='http://jabber.org/protocol/disco#info'><identity category='client' type='pc' name='Pidgin'/>" +
"<feature var='urn:xmpp:noping'/>" +
"</query></iq>";
//@formatter:on
// @formatter:on
IQ discoReply = (IQ) PacketParserUtils.parseStanza(reply);
con.addIQReply(discoReply);

View file

@ -50,7 +50,7 @@ public class DataFormTest {
@Test
public void test() throws Exception {
//Build a Form
// Build a Form.
DataForm df = new DataForm(DataForm.Type.submit);
String instruction = "InstructionTest1";
df.addInstruction(instruction);
@ -77,7 +77,7 @@ public class DataFormTest {
@Test
public void testLayout() throws Exception {
//Build a Form
// Build a Form.
DataForm df = new DataForm(DataForm.Type.submit);
String instruction = "InstructionTest1";
df.addInstruction(instruction);
@ -119,7 +119,7 @@ public class DataFormTest {
@Test
public void testValidation() throws Exception {
//Build a Form
// Build a Form.
DataForm df = new DataForm(DataForm.Type.submit);
String instruction = "InstructionTest1";
df.addInstruction(instruction);