Prevent multi-instancing of OfflineMessageManager

This commit is contained in:
Paul Schaub 2020-02-17 01:43:40 +01:00
parent 9d626bf787
commit 5ed594fe73
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
1 changed files with 28 additions and 15 deletions

View File

@ -19,9 +19,12 @@ package org.jivesoftware.smackx.offline;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.StanzaCollector; import org.jivesoftware.smack.StanzaCollector;
@ -58,19 +61,31 @@ import org.jivesoftware.smackx.xdata.Form;
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class OfflineMessageManager { public final class OfflineMessageManager extends Manager {
private static final Logger LOGGER = Logger.getLogger(OfflineMessageManager.class.getName()); private static final Logger LOGGER = Logger.getLogger(OfflineMessageManager.class.getName());
private static final String namespace = "http://jabber.org/protocol/offline"; private static final String namespace = "http://jabber.org/protocol/offline";
private final XMPPConnection connection; private static final Map<XMPPConnection, OfflineMessageManager> INSTANCES = new WeakHashMap<>();
private static final StanzaFilter PACKET_FILTER = new AndFilter(new StanzaExtensionFilter( private static final StanzaFilter PACKET_FILTER = new AndFilter(new StanzaExtensionFilter(
new OfflineMessageInfo()), StanzaTypeFilter.MESSAGE); new OfflineMessageInfo()), StanzaTypeFilter.MESSAGE);
public OfflineMessageManager(XMPPConnection connection) { private ServiceDiscoveryManager serviceDiscoveryManager;
this.connection = connection;
private OfflineMessageManager(XMPPConnection connection) {
super(connection);
this.serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
}
public static synchronized OfflineMessageManager getInstanceFor(XMPPConnection connection) {
OfflineMessageManager manager = INSTANCES.get(connection);
if (manager == null) {
manager = new OfflineMessageManager(connection);
INSTANCES.put(connection, manager);
}
return manager;
} }
/** /**
@ -85,7 +100,7 @@ public class OfflineMessageManager {
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
*/ */
public boolean supportsFlexibleRetrieval() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { public boolean supportsFlexibleRetrieval() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
return ServiceDiscoveryManager.getInstanceFor(connection).serverSupportsFeature(namespace); return serviceDiscoveryManager.serverSupportsFeature(namespace);
} }
/** /**
@ -99,8 +114,7 @@ public class OfflineMessageManager {
* @throws InterruptedException if the calling thread was interrupted. * @throws InterruptedException if the calling thread was interrupted.
*/ */
public int getMessageCount() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { public int getMessageCount() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(null, DiscoverInfo info = serviceDiscoveryManager.discoverInfo(null, namespace);
namespace);
Form extendedInfo = Form.getFormFrom(info); Form extendedInfo = Form.getFormFrom(info);
if (extendedInfo != null) { if (extendedInfo != null) {
String value = extendedInfo.getField("number_of_messages").getFirstValue(); String value = extendedInfo.getField("number_of_messages").getFirstValue();
@ -124,8 +138,7 @@ public class OfflineMessageManager {
*/ */
public List<OfflineMessageHeader> getHeaders() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { public List<OfflineMessageHeader> getHeaders() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
List<OfflineMessageHeader> answer = new ArrayList<>(); List<OfflineMessageHeader> answer = new ArrayList<>();
DiscoverItems items = ServiceDiscoveryManager.getInstanceFor(connection).discoverItems( DiscoverItems items = serviceDiscoveryManager.discoverItems(null, namespace);
null, namespace);
for (DiscoverItems.Item item : items.getItems()) { for (DiscoverItems.Item item : items.getItems()) {
answer.add(new OfflineMessageHeader(item)); answer.add(new OfflineMessageHeader(item));
} }
@ -165,8 +178,8 @@ public class OfflineMessageManager {
} }
}); });
int pendingNodes = nodes.size(); int pendingNodes = nodes.size();
try (StanzaCollector messageCollector = connection.createStanzaCollector(messageFilter)) { try (StanzaCollector messageCollector = connection().createStanzaCollector(messageFilter)) {
connection.createStanzaCollectorAndSend(request).nextResultOrThrow(); connection().createStanzaCollectorAndSend(request).nextResultOrThrow();
// Collect the received offline messages // Collect the received offline messages
Message message; Message message;
do { do {
@ -199,11 +212,11 @@ public class OfflineMessageManager {
OfflineMessageRequest request = new OfflineMessageRequest(); OfflineMessageRequest request = new OfflineMessageRequest();
request.setFetch(true); request.setFetch(true);
StanzaCollector resultCollector = connection.createStanzaCollectorAndSend(request); StanzaCollector resultCollector = connection().createStanzaCollectorAndSend(request);
StanzaCollector.Configuration messageCollectorConfiguration = StanzaCollector.newConfiguration().setStanzaFilter(PACKET_FILTER).setCollectorToReset(resultCollector); StanzaCollector.Configuration messageCollectorConfiguration = StanzaCollector.newConfiguration().setStanzaFilter(PACKET_FILTER).setCollectorToReset(resultCollector);
List<Message> messages; List<Message> messages;
try (StanzaCollector messageCollector = connection.createStanzaCollector(messageCollectorConfiguration)) { try (StanzaCollector messageCollector = connection().createStanzaCollector(messageCollectorConfiguration)) {
resultCollector.nextResultOrThrow(); resultCollector.nextResultOrThrow();
// Be extra safe, cancel the message collector right here so that it does not collector // Be extra safe, cancel the message collector right here so that it does not collector
// other messages that eventually match (although I've no idea how this could happen in // other messages that eventually match (although I've no idea how this could happen in
@ -237,7 +250,7 @@ public class OfflineMessageManager {
item.setAction("remove"); item.setAction("remove");
request.addItem(item); request.addItem(item);
} }
connection.createStanzaCollectorAndSend(request).nextResultOrThrow(); connection().createStanzaCollectorAndSend(request).nextResultOrThrow();
} }
/** /**
@ -253,6 +266,6 @@ public class OfflineMessageManager {
OfflineMessageRequest request = new OfflineMessageRequest(); OfflineMessageRequest request = new OfflineMessageRequest();
request.setType(IQ.Type.set); request.setType(IQ.Type.set);
request.setPurge(true); request.setPurge(true);
connection.createStanzaCollectorAndSend(request).nextResultOrThrow(); connection().createStanzaCollectorAndSend(request).nextResultOrThrow();
} }
} }