Sync MAM API with PubSub API: One MamManager per MAM archive address

This commit is contained in:
Florian Schmaus 2017-02-24 19:33:11 +01:00
parent 00005d87be
commit 32fd52ea8e
1 changed files with 71 additions and 32 deletions

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2016 Florian Schmaus and Fernando Ramirez * Copyright © 2016-2017 Florian Schmaus, Fernando Ramirez
* *
* 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,6 +18,7 @@ package org.jivesoftware.smackx.mam;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -47,6 +48,8 @@ import org.jivesoftware.smackx.mam.filter.MamResultFilter;
import org.jivesoftware.smackx.rsm.packet.RSMSet; import org.jivesoftware.smackx.rsm.packet.RSMSet;
import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.FormField;
import org.jivesoftware.smackx.xdata.packet.DataForm; import org.jivesoftware.smackx.xdata.packet.DataForm;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.Jid; import org.jxmpp.jid.Jid;
import org.jxmpp.util.XmppDateTime; import org.jxmpp.util.XmppDateTime;
@ -70,7 +73,7 @@ public final class MamManager extends Manager {
}); });
} }
private static final Map<XMPPConnection, MamManager> INSTANCES = new WeakHashMap<>(); private static final Map<XMPPConnection, Map<Jid, MamManager>> INSTANCES = new WeakHashMap<>();
/** /**
* Get the singleton instance of MamManager. * Get the singleton instance of MamManager.
@ -78,19 +81,29 @@ public final class MamManager extends Manager {
* @param connection * @param connection
* @return the instance of MamManager * @return the instance of MamManager
*/ */
public static synchronized MamManager getInstanceFor(XMPPConnection connection) { public static MamManager getInstanceFor(XMPPConnection connection) {
MamManager mamManager = INSTANCES.get(connection); return getInstanceFor(connection, null);
}
if (mamManager == null) { public static synchronized MamManager getInstanceFor(XMPPConnection connection, Jid archiveAddress) {
mamManager = new MamManager(connection); Map<Jid, MamManager> managers = INSTANCES.get(connection);
INSTANCES.put(connection, mamManager); if (managers == null) {
managers = new HashMap<>();
INSTANCES.put(connection, managers);
}
MamManager mamManager = managers.get(archiveAddress);
if (mamManager == null) {
mamManager = new MamManager(connection, archiveAddress);
managers.put(archiveAddress, mamManager);
} }
return mamManager; return mamManager;
} }
private MamManager(XMPPConnection connection) { private final Jid archiveAddress;
private MamManager(XMPPConnection connection, Jid archiveAddress) {
super(connection); super(connection);
this.archiveAddress = archiveAddress;
} }
/** /**
@ -106,7 +119,7 @@ public final class MamManager extends Manager {
*/ */
public MamQueryResult queryArchive(Integer max) throws NoResponseException, XMPPErrorException, public MamQueryResult queryArchive(Integer max) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException, NotLoggedInException { NotConnectedException, InterruptedException, NotLoggedInException {
return queryArchive(null, null, max, null, null, null, null); return queryArchive(null, max, null, null, null, null);
} }
/** /**
@ -122,7 +135,7 @@ public final class MamManager extends Manager {
*/ */
public MamQueryResult queryArchive(Jid withJid) throws NoResponseException, XMPPErrorException, public MamQueryResult queryArchive(Jid withJid) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException, NotLoggedInException { NotConnectedException, InterruptedException, NotLoggedInException {
return queryArchive(null, null, null, null, null, withJid, null); return queryArchive(null, null, null, null, withJid, null);
} }
/** /**
@ -142,7 +155,7 @@ public final class MamManager extends Manager {
*/ */
public MamQueryResult queryArchive(Date start, Date end) throws NoResponseException, XMPPErrorException, public MamQueryResult queryArchive(Date start, Date end) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException, NotLoggedInException { NotConnectedException, InterruptedException, NotLoggedInException {
return queryArchive(null, null, null, start, end, null, null); return queryArchive(null, null, start, end, null, null);
} }
/** /**
@ -158,7 +171,7 @@ public final class MamManager extends Manager {
*/ */
public MamQueryResult queryArchive(List<FormField> additionalFields) throws NoResponseException, XMPPErrorException, public MamQueryResult queryArchive(List<FormField> additionalFields) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException, NotLoggedInException { NotConnectedException, InterruptedException, NotLoggedInException {
return queryArchive(null, null, null, null, null, null, additionalFields); return queryArchive(null, null, null, null, null, additionalFields);
} }
/** /**
@ -175,7 +188,7 @@ public final class MamManager extends Manager {
*/ */
public MamQueryResult queryArchiveWithStartDate(Date start) throws NoResponseException, XMPPErrorException, public MamQueryResult queryArchiveWithStartDate(Date start) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException, NotLoggedInException { NotConnectedException, InterruptedException, NotLoggedInException {
return queryArchive(null, null, null, start, null, null, null); return queryArchive(null, null, start, null, null, null);
} }
/** /**
@ -192,7 +205,7 @@ public final class MamManager extends Manager {
*/ */
public MamQueryResult queryArchiveWithEndDate(Date end) throws NoResponseException, XMPPErrorException, public MamQueryResult queryArchiveWithEndDate(Date end) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException, NotLoggedInException { NotConnectedException, InterruptedException, NotLoggedInException {
return queryArchive(null, null, null, null, end, null, null); return queryArchive(null, null, null, end, null, null);
} }
@ -215,7 +228,7 @@ public final class MamManager extends Manager {
public MamQueryResult queryArchive(Integer max, Date start, Date end, Jid withJid, List<FormField> additionalFields) public MamQueryResult queryArchive(Integer max, Date start, Date end, Jid withJid, List<FormField> additionalFields)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException,
NotLoggedInException { NotLoggedInException {
return queryArchive(null, null, max, start, end, withJid, additionalFields); return queryArchive(null, max, start, end, withJid, additionalFields);
} }
@ -224,7 +237,6 @@ public final class MamManager extends Manager {
* filters: max count, start date, end date, from/to JID and with additional fields. When archiveAddress is null the * filters: max count, start date, end date, from/to JID and with additional fields. When archiveAddress is null the
* default, the server will be requested. * default, the server will be requested.
* *
* @param archiveAddress can be null
* @param node The Pubsub node name, can be null * @param node The Pubsub node name, can be null
* @param max * @param max
* @param start * @param start
@ -238,7 +250,7 @@ public final class MamManager extends Manager {
* @throws InterruptedException * @throws InterruptedException
* @throws NotLoggedInException * @throws NotLoggedInException
*/ */
public MamQueryResult queryArchive(Jid archiveAddress, String node, Integer max, Date start, Date end, Jid withJid, public MamQueryResult queryArchive(String node, Integer max, Date start, Date end, Jid withJid,
List<FormField> additionalFields) List<FormField> additionalFields)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException,
NotLoggedInException { NotLoggedInException {
@ -321,14 +333,13 @@ public final class MamManager extends Manager {
public MamQueryResult page(DataForm dataForm, RSMSet rsmSet) throws NoResponseException, XMPPErrorException, public MamQueryResult page(DataForm dataForm, RSMSet rsmSet) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException, NotLoggedInException { NotConnectedException, InterruptedException, NotLoggedInException {
return page(null, null, dataForm, rsmSet); return page(null, dataForm, rsmSet);
} }
/** /**
* Returns a page of the archive. * Returns a page of the archive.
* *
* @param archiveAddress can be null
* @param node The Pubsub node name, can be null * @param node The Pubsub node name, can be null
* @param dataForm * @param dataForm
* @param rsmSet * @param rsmSet
@ -339,7 +350,7 @@ public final class MamManager extends Manager {
* @throws InterruptedException * @throws InterruptedException
* @throws NotLoggedInException * @throws NotLoggedInException
*/ */
public MamQueryResult page(Jid archiveAddress, String node, DataForm dataForm, RSMSet rsmSet) public MamQueryResult page(String node, DataForm dataForm, RSMSet rsmSet)
throws NoResponseException, XMPPErrorException, throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException, NotLoggedInException { NotConnectedException, InterruptedException, NotLoggedInException {
MamQueryIQ mamQueryIQ = new MamQueryIQ(UUID.randomUUID().toString(), node, dataForm); MamQueryIQ mamQueryIQ = new MamQueryIQ(UUID.randomUUID().toString(), node, dataForm);
@ -367,7 +378,7 @@ public final class MamManager extends Manager {
XMPPErrorException, NotConnectedException, InterruptedException, NotLoggedInException { XMPPErrorException, NotConnectedException, InterruptedException, NotLoggedInException {
RSMSet previousResultRsmSet = mamQueryResult.mamFin.getRSMSet(); RSMSet previousResultRsmSet = mamQueryResult.mamFin.getRSMSet();
RSMSet requestRsmSet = new RSMSet(count, previousResultRsmSet.getLast(), RSMSet.PageDirection.after); RSMSet requestRsmSet = new RSMSet(count, previousResultRsmSet.getLast(), RSMSet.PageDirection.after);
return page(mamQueryResult.to, mamQueryResult.node, mamQueryResult.form, requestRsmSet); return page(mamQueryResult, requestRsmSet);
} }
/** /**
@ -388,7 +399,14 @@ public final class MamManager extends Manager {
XMPPErrorException, NotConnectedException, InterruptedException, NotLoggedInException { XMPPErrorException, NotConnectedException, InterruptedException, NotLoggedInException {
RSMSet previousResultRsmSet = mamQueryResult.mamFin.getRSMSet(); RSMSet previousResultRsmSet = mamQueryResult.mamFin.getRSMSet();
RSMSet requestRsmSet = new RSMSet(count, previousResultRsmSet.getFirst(), RSMSet.PageDirection.before); RSMSet requestRsmSet = new RSMSet(count, previousResultRsmSet.getFirst(), RSMSet.PageDirection.before);
return page(mamQueryResult.to, mamQueryResult.node, mamQueryResult.form, requestRsmSet); return page(mamQueryResult, requestRsmSet);
}
private MamQueryResult page(MamQueryResult mamQueryResult, RSMSet requestRsmSet) throws NoResponseException,
XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException {
ensureMamQueryResultMatchesThisManager(mamQueryResult);
return page(mamQueryResult.node, mamQueryResult.form, requestRsmSet);
} }
/** /**
@ -409,7 +427,7 @@ public final class MamManager extends Manager {
RSMSet rsmSet = new RSMSet(null, firstMessageId, -1, -1, null, max, null, -1); RSMSet rsmSet = new RSMSet(null, firstMessageId, -1, -1, null, max, null, -1);
DataForm dataForm = getNewMamForm(); DataForm dataForm = getNewMamForm();
addWithJid(chatJid, dataForm); addWithJid(chatJid, dataForm);
return page(null, null, dataForm, rsmSet); return page(null, dataForm, rsmSet);
} }
/** /**
@ -430,7 +448,7 @@ public final class MamManager extends Manager {
RSMSet rsmSet = new RSMSet(lastMessageId, null, -1, -1, null, max, null, -1); RSMSet rsmSet = new RSMSet(lastMessageId, null, -1, -1, null, max, null, -1);
DataForm dataForm = getNewMamForm(); DataForm dataForm = getNewMamForm();
addWithJid(chatJid, dataForm); addWithJid(chatJid, dataForm);
return page(null, null, dataForm, rsmSet); return page(null, dataForm, rsmSet);
} }
/** /**
@ -462,13 +480,12 @@ public final class MamManager extends Manager {
*/ */
public List<FormField> retrieveFormFields() throws NoResponseException, XMPPErrorException, NotConnectedException, public List<FormField> retrieveFormFields() throws NoResponseException, XMPPErrorException, NotConnectedException,
InterruptedException, NotLoggedInException { InterruptedException, NotLoggedInException {
return retrieveFormFields(null, null); return retrieveFormFields(null);
} }
/** /**
* Get the form fields supported by the server. * Get the form fields supported by the server.
* *
* @param archiveAddress can be null
* @param node The Pubsub node name, can be null * @param node The Pubsub node name, can be null
* @return the list of form fields. * @return the list of form fields.
* @throws NoResponseException * @throws NoResponseException
@ -477,7 +494,7 @@ public final class MamManager extends Manager {
* @throws InterruptedException * @throws InterruptedException
* @throws NotLoggedInException * @throws NotLoggedInException
*/ */
public List<FormField> retrieveFormFields(Jid archiveAddress, String node) public List<FormField> retrieveFormFields(String node)
throws NoResponseException, XMPPErrorException, NotConnectedException, throws NoResponseException, XMPPErrorException, NotConnectedException,
InterruptedException, NotLoggedInException { InterruptedException, NotLoggedInException {
String queryId = UUID.randomUUID().toString(); String queryId = UUID.randomUUID().toString();
@ -516,7 +533,7 @@ public final class MamManager extends Manager {
forwardedMessages.add(mamResultExtension.getForwarded()); forwardedMessages.add(mamResultExtension.getForwarded());
} }
return new MamQueryResult(forwardedMessages, mamFinIQ, mamQueryIq.getTo(), mamQueryIq.getNode(), DataForm.from(mamQueryIq)); return new MamQueryResult(forwardedMessages, mamFinIQ, mamQueryIq.getNode(), DataForm.from(mamQueryIq));
} }
/** /**
@ -526,19 +543,41 @@ public final class MamManager extends Manager {
public final static class MamQueryResult { public final static class MamQueryResult {
public final List<Forwarded> forwardedMessages; public final List<Forwarded> forwardedMessages;
public final MamFinIQ mamFin; public final MamFinIQ mamFin;
private final Jid to;
private final String node; private final String node;
private final DataForm form; private final DataForm form;
private MamQueryResult(List<Forwarded> forwardedMessages, MamFinIQ mamFin, Jid to, String node, DataForm form) { private MamQueryResult(List<Forwarded> forwardedMessages, MamFinIQ mamFin, String node, DataForm form) {
this.forwardedMessages = forwardedMessages; this.forwardedMessages = forwardedMessages;
this.mamFin = mamFin; this.mamFin = mamFin;
this.to = to;
this.node = node; this.node = node;
this.form = form; this.form = form;
} }
} }
private void ensureMamQueryResultMatchesThisManager(MamQueryResult mamQueryResult) {
EntityFullJid localAddress = connection().getUser();
EntityBareJid localBareAddress = null;
if (localAddress != null) {
localBareAddress = localAddress.asEntityBareJid();
}
boolean isLocalUserArchive = archiveAddress == null || archiveAddress.equals(localBareAddress);
Jid finIqFrom = mamQueryResult.mamFin.getFrom();
if (finIqFrom != null) {
if (finIqFrom.equals(archiveAddress) || (isLocalUserArchive && finIqFrom.equals(localBareAddress))) {
return;
}
throw new IllegalArgumentException("The given MamQueryResult is from the MAM archive '" + finIqFrom
+ "' whereas this MamManager is responsible for '" + archiveAddress + '\'');
}
else if (!isLocalUserArchive) {
throw new IllegalArgumentException(
"The given MamQueryResult is from the local entity (user) MAM archive, whereas this MamManager is responsible for '"
+ archiveAddress + '\'');
}
}
/** /**
* Returns true if Message Archive Management is supported by the server. * Returns true if Message Archive Management is supported by the server.
* *