diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index 184d389b2..8d0a69c6d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -46,6 +46,7 @@ import org.jivesoftware.smack.SmackException.AlreadyConnectedException; import org.jivesoftware.smack.SmackException.AlreadyLoggedInException; import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotConnectedException; +import org.jivesoftware.smack.SmackException.NotLoggedInException; import org.jivesoftware.smack.SmackException.ResourceBindingNotOfferedException; import org.jivesoftware.smack.SmackException.SecurityRequiredByClientException; import org.jivesoftware.smack.SmackException.SecurityRequiredException; @@ -1527,7 +1528,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { final StanzaListener packetListener = new StanzaListener() { @Override - public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException { + public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException, NotLoggedInException { boolean removed = removeAsyncStanzaListener(this); if (!removed) { // We lost a race against the "no response" handling runnable. Avoid calling the callback, as the @@ -1591,7 +1592,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { public void addOneTimeSyncCallback(final StanzaListener callback, final StanzaFilter packetFilter) { final StanzaListener packetListener = new StanzaListener() { @Override - public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException { + public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException, NotLoggedInException { try { callback.processStanza(packet); } finally { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/StanzaListener.java b/smack-core/src/main/java/org/jivesoftware/smack/StanzaListener.java index fb9b1b283..c5e5eb1aa 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/StanzaListener.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/StanzaListener.java @@ -18,6 +18,7 @@ package org.jivesoftware.smack; import org.jivesoftware.smack.SmackException.NotConnectedException; +import org.jivesoftware.smack.SmackException.NotLoggedInException; import org.jivesoftware.smack.packet.Stanza; /** @@ -49,7 +50,8 @@ public interface StanzaListener { * @param packet the stanza(/packet) to process. * @throws NotConnectedException * @throws InterruptedException + * @throws NotLoggedInException */ - public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException; + public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException, NotLoggedInException; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/DataListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/DataListener.java index d266bcfd4..0c1bfa6d2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/DataListener.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/DataListener.java @@ -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; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java index 8b06f541f..79a5b29e8 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java @@ -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); } 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 3fc27d62f..a040ce291 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 @@ -249,9 +249,10 @@ public final class Roster extends Manager { connection.addSyncStanzaListener(presencePacketListener, PRESENCE_PACKET_FILTER); connection.addAsyncStanzaListener(new StanzaListener() { + @SuppressWarnings("fallthrough") @Override public void processStanza(Stanza stanza) throws NotConnectedException, - InterruptedException { + InterruptedException, NotLoggedInException { Presence presence = (Presence) stanza; Jid from = presence.getFrom(); SubscribeAnswer subscribeAnswer = null; @@ -277,13 +278,26 @@ public final class Roster extends Manager { break; } + if (subscribeAnswer == null) { + return; + } + Presence response; - if (subscribeAnswer == SubscribeAnswer.Approve) { + switch (subscribeAnswer) { + case ApproveAndAlsoRequestIfRequired: + BareJid bareFrom = from.asBareJid(); + RosterUtil.askForSubscriptionIfRequired(Roster.this, bareFrom); + // The fall through is intended. + case Approve: response = new Presence(Presence.Type.subscribed); - } - else { + break; + case Deny: response = new Presence(Presence.Type.unsubscribed); + break; + default: + throw new AssertionError(); } + response.setTo(presence.getFrom()); connection.sendStanza(response); } diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/SubscribeListener.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/SubscribeListener.java index 7c045aaaf..85abba6dd 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/SubscribeListener.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/SubscribeListener.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015 Florian Schmaus + * Copyright 2015-2017 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,13 +23,29 @@ import org.jxmpp.jid.Jid; /** - * Handle incoming requests to subscribe to our presence. + * Handle incoming requests to subscribe to our presence. The + * {@link #processSubscribe(Jid, Presence)} method may return a subscribe + * answer. If no subscribe answer is returned, the next listener will be + * notified and asked. If no listener returns an answer, then nothing happens. * */ public interface SubscribeListener { public enum SubscribeAnswer { + /** + * Approve the subscription request. + */ Approve, + + /** + * Approve the subscription request and also request subscription from the other party if not already subscribed. + * @since 4.2.2 + */ + ApproveAndAlsoRequestIfRequired, + + /** + * Deny the subscription request. + */ Deny, } diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java index 017af18a0..c604dc675 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java @@ -81,6 +81,7 @@ import org.jivesoftware.smack.SmackException.AlreadyLoggedInException; import org.jivesoftware.smack.SmackException.ConnectionException; import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotConnectedException; +import org.jivesoftware.smack.SmackException.NotLoggedInException; import org.jivesoftware.smack.SmackException.SecurityRequiredByServerException; import org.jivesoftware.smack.StanzaListener; import org.jivesoftware.smack.SynchronizationPoint; @@ -1887,7 +1888,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { try { listener.processStanza(ackedStanza); } - catch (InterruptedException | NotConnectedException e) { + catch (InterruptedException | NotConnectedException | NotLoggedInException e) { LOGGER.log(Level.FINER, "Received exception", e); } } @@ -1900,7 +1901,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { try { listener.processStanza(ackedStanza); } - catch (InterruptedException | NotConnectedException e) { + catch (InterruptedException | NotConnectedException | NotLoggedInException e) { LOGGER.log(Level.FINER, "Received exception", e); } }