mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-09-27 10:09:32 +02:00
34373e8710
Also make all 'test' tasks depend on the 'javadoc' task. Fixes SMACK-650.
702 lines
26 KiB
Java
702 lines
26 KiB
Java
/**
|
|
*
|
|
* Copyright © 2016-2017 Florian Schmaus, Fernando Ramirez
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package org.jivesoftware.smackx.mam;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.UUID;
|
|
import java.util.WeakHashMap;
|
|
|
|
import org.jivesoftware.smack.ConnectionCreationListener;
|
|
import org.jivesoftware.smack.Manager;
|
|
import org.jivesoftware.smack.SmackException.NoResponseException;
|
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
|
import org.jivesoftware.smack.SmackException.NotLoggedInException;
|
|
import org.jivesoftware.smack.StanzaCollector;
|
|
import org.jivesoftware.smack.XMPPConnection;
|
|
import org.jivesoftware.smack.XMPPConnectionRegistry;
|
|
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
|
import org.jivesoftware.smack.filter.IQReplyFilter;
|
|
import org.jivesoftware.smack.packet.IQ;
|
|
import org.jivesoftware.smack.packet.Message;
|
|
import org.jivesoftware.smack.util.Objects;
|
|
|
|
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
|
import org.jivesoftware.smackx.forward.packet.Forwarded;
|
|
import org.jivesoftware.smackx.mam.element.MamElements;
|
|
import org.jivesoftware.smackx.mam.element.MamFinIQ;
|
|
import org.jivesoftware.smackx.mam.element.MamPrefsIQ;
|
|
import org.jivesoftware.smackx.mam.element.MamPrefsIQ.DefaultBehavior;
|
|
import org.jivesoftware.smackx.mam.element.MamQueryIQ;
|
|
import org.jivesoftware.smackx.mam.filter.MamResultFilter;
|
|
import org.jivesoftware.smackx.rsm.packet.RSMSet;
|
|
import org.jivesoftware.smackx.xdata.FormField;
|
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
|
|
|
import org.jxmpp.jid.BareJid;
|
|
import org.jxmpp.jid.EntityBareJid;
|
|
import org.jxmpp.jid.EntityFullJid;
|
|
import org.jxmpp.jid.Jid;
|
|
import org.jxmpp.util.XmppDateTime;
|
|
|
|
/**
|
|
* A Manager for Message Archive Management (XEP-0313).
|
|
*
|
|
* @see <a href="http://xmpp.org/extensions/xep-0313.html">XEP-0313: Message
|
|
* Archive Management</a>
|
|
* @author Florian Schmaus
|
|
* @author Fernando Ramirez
|
|
*
|
|
*/
|
|
public final class MamManager extends Manager {
|
|
|
|
static {
|
|
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
|
|
@Override
|
|
public void connectionCreated(XMPPConnection connection) {
|
|
getInstanceFor(connection);
|
|
}
|
|
});
|
|
}
|
|
|
|
private static final Map<XMPPConnection, Map<Jid, MamManager>> INSTANCES = new WeakHashMap<>();
|
|
|
|
/**
|
|
* Get the singleton instance of MamManager.
|
|
*
|
|
* @param connection
|
|
* @return the instance of MamManager
|
|
*/
|
|
public static MamManager getInstanceFor(XMPPConnection connection) {
|
|
return getInstanceFor(connection, null);
|
|
}
|
|
|
|
public static synchronized MamManager getInstanceFor(XMPPConnection connection, Jid archiveAddress) {
|
|
Map<Jid, MamManager> managers = INSTANCES.get(connection);
|
|
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;
|
|
}
|
|
|
|
private final Jid archiveAddress;
|
|
|
|
private final ServiceDiscoveryManager serviceDiscoveryManager;
|
|
|
|
private MamManager(XMPPConnection connection, Jid archiveAddress) {
|
|
super(connection);
|
|
this.archiveAddress = archiveAddress;
|
|
serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
|
}
|
|
|
|
/**
|
|
* Query archive with a maximum amount of results.
|
|
*
|
|
* @param max
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult queryArchive(Integer max) throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
return queryArchive(null, max, null, null, null, null);
|
|
}
|
|
|
|
/**
|
|
* Query archive with a JID (only messages from/to the JID).
|
|
*
|
|
* @param withJid
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult queryArchive(Jid withJid) throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
return queryArchive(null, null, null, null, withJid, null);
|
|
}
|
|
|
|
/**
|
|
* Query archive filtering by start and/or end date. If start == null, the
|
|
* value of 'start' will be equal to the date/time of the earliest message
|
|
* stored in the archive. If end == null, the value of 'end' will be equal
|
|
* to the date/time of the most recent message stored in the archive.
|
|
*
|
|
* @param start
|
|
* @param end
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult queryArchive(Date start, Date end) throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
return queryArchive(null, null, start, end, null, null);
|
|
}
|
|
|
|
/**
|
|
* Query Archive adding filters with additional fields.
|
|
*
|
|
* @param additionalFields
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult queryArchive(List<FormField> additionalFields) throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
return queryArchive(null, null, null, null, null, additionalFields);
|
|
}
|
|
|
|
/**
|
|
* Query archive filtering by start date. The value of 'end' will be equal
|
|
* to the date/time of the most recent message stored in the archive.
|
|
*
|
|
* @param start
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult queryArchiveWithStartDate(Date start) throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
return queryArchive(null, null, start, null, null, null);
|
|
}
|
|
|
|
/**
|
|
* Query archive filtering by end date. The value of 'start' will be equal
|
|
* to the date/time of the earliest message stored in the archive.
|
|
*
|
|
* @param end
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult queryArchiveWithEndDate(Date end) throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
return queryArchive(null, null, null, end, null, null);
|
|
}
|
|
|
|
|
|
/**
|
|
* Query archive applying filters: max count, start date, end date, from/to
|
|
* JID and with additional fields.
|
|
*
|
|
* @param max
|
|
* @param start
|
|
* @param end
|
|
* @param withJid
|
|
* @param additionalFields
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult queryArchive(Integer max, Date start, Date end, Jid withJid, List<FormField> additionalFields)
|
|
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException,
|
|
NotLoggedInException {
|
|
return queryArchive(null, max, start, end, withJid, additionalFields);
|
|
}
|
|
|
|
|
|
/**
|
|
* Query an message archive like a MUC archive or a PubSub node archive, addressed by an archiveAddress, applying
|
|
* 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.
|
|
*
|
|
* @param node The PubSub node name, can be null
|
|
* @param max
|
|
* @param start
|
|
* @param end
|
|
* @param withJid
|
|
* @param additionalFields
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult queryArchive(String node, Integer max, Date start, Date end, Jid withJid,
|
|
List<FormField> additionalFields)
|
|
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException,
|
|
NotLoggedInException {
|
|
DataForm dataForm = null;
|
|
String queryId = UUID.randomUUID().toString();
|
|
|
|
if (start != null || end != null || withJid != null || additionalFields != null) {
|
|
dataForm = getNewMamForm();
|
|
addStart(start, dataForm);
|
|
addEnd(end, dataForm);
|
|
addWithJid(withJid, dataForm);
|
|
addAdditionalFields(additionalFields, dataForm);
|
|
}
|
|
|
|
MamQueryIQ mamQueryIQ = new MamQueryIQ(queryId, node, dataForm);
|
|
mamQueryIQ.setType(IQ.Type.set);
|
|
mamQueryIQ.setTo(archiveAddress);
|
|
|
|
addResultsLimit(max, mamQueryIQ);
|
|
return queryArchive(mamQueryIQ);
|
|
}
|
|
|
|
private static void addAdditionalFields(List<FormField> additionalFields, DataForm dataForm) {
|
|
if (additionalFields == null) {
|
|
return;
|
|
}
|
|
for (FormField formField : additionalFields) {
|
|
dataForm.addField(formField);
|
|
}
|
|
}
|
|
|
|
private static void addResultsLimit(Integer max, MamQueryIQ mamQueryIQ) {
|
|
if (max == null) {
|
|
return;
|
|
}
|
|
RSMSet rsmSet = new RSMSet(max);
|
|
mamQueryIQ.addExtension(rsmSet);
|
|
|
|
}
|
|
|
|
private static void addWithJid(Jid withJid, DataForm dataForm) {
|
|
if (withJid == null) {
|
|
return;
|
|
}
|
|
FormField formField = new FormField("with");
|
|
formField.addValue(withJid.toString());
|
|
dataForm.addField(formField);
|
|
}
|
|
|
|
private static void addEnd(Date end, DataForm dataForm) {
|
|
if (end == null) {
|
|
return;
|
|
}
|
|
FormField formField = new FormField("end");
|
|
formField.addValue(XmppDateTime.formatXEP0082Date(end));
|
|
dataForm.addField(formField);
|
|
}
|
|
|
|
private static void addStart(Date start, DataForm dataForm) {
|
|
if (start == null) {
|
|
return;
|
|
}
|
|
FormField formField = new FormField("start");
|
|
formField.addValue(XmppDateTime.formatXEP0082Date(start));
|
|
dataForm.addField(formField);
|
|
}
|
|
|
|
/**
|
|
* Returns a page of the archive.
|
|
*
|
|
* @param dataForm
|
|
* @param rsmSet
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult page(DataForm dataForm, RSMSet rsmSet) throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
|
|
return page(null, dataForm, rsmSet);
|
|
|
|
}
|
|
|
|
/**
|
|
* Returns a page of the archive.
|
|
*
|
|
* @param node The PubSub node name, can be null
|
|
* @param dataForm
|
|
* @param rsmSet
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult page(String node, DataForm dataForm, RSMSet rsmSet)
|
|
throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
MamQueryIQ mamQueryIQ = new MamQueryIQ(UUID.randomUUID().toString(), node, dataForm);
|
|
mamQueryIQ.setType(IQ.Type.set);
|
|
mamQueryIQ.setTo(archiveAddress);
|
|
mamQueryIQ.addExtension(rsmSet);
|
|
return queryArchive(mamQueryIQ);
|
|
}
|
|
|
|
/**
|
|
* Returns the next page of the archive.
|
|
*
|
|
* @param mamQueryResult
|
|
* is the previous query result
|
|
* @param count
|
|
* is the amount of messages that a page contains
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult pageNext(MamQueryResult mamQueryResult, int count) throws NoResponseException,
|
|
XMPPErrorException, NotConnectedException, InterruptedException, NotLoggedInException {
|
|
RSMSet previousResultRsmSet = mamQueryResult.mamFin.getRSMSet();
|
|
RSMSet requestRsmSet = new RSMSet(count, previousResultRsmSet.getLast(), RSMSet.PageDirection.after);
|
|
return page(mamQueryResult, requestRsmSet);
|
|
}
|
|
|
|
/**
|
|
* Returns the previous page of the archive.
|
|
*
|
|
* @param mamQueryResult
|
|
* is the previous query result
|
|
* @param count
|
|
* is the amount of messages that a page contains
|
|
* @return the MAM query result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamQueryResult pagePrevious(MamQueryResult mamQueryResult, int count) throws NoResponseException,
|
|
XMPPErrorException, NotConnectedException, InterruptedException, NotLoggedInException {
|
|
RSMSet previousResultRsmSet = mamQueryResult.mamFin.getRSMSet();
|
|
RSMSet requestRsmSet = new RSMSet(count, previousResultRsmSet.getFirst(), RSMSet.PageDirection.before);
|
|
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);
|
|
}
|
|
|
|
/**
|
|
* Obtain page before the first message saved (specific chat).
|
|
* <p>
|
|
* Note that the messageUid is the XEP-0313 UID and <b>not</b> the stanza ID of the message.
|
|
* </p>
|
|
*
|
|
* @param chatJid
|
|
* @param messageUid the UID of the message of which messages before should be received.
|
|
* @param max
|
|
* @return the MAM query result
|
|
* @throws XMPPErrorException
|
|
* @throws NotLoggedInException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NoResponseException
|
|
*/
|
|
public MamQueryResult pageBefore(Jid chatJid, String messageUid, int max) throws XMPPErrorException,
|
|
NotLoggedInException, NotConnectedException, InterruptedException, NoResponseException {
|
|
RSMSet rsmSet = new RSMSet(null, messageUid, -1, -1, null, max, null, -1);
|
|
DataForm dataForm = getNewMamForm();
|
|
addWithJid(chatJid, dataForm);
|
|
return page(null, dataForm, rsmSet);
|
|
}
|
|
|
|
/**
|
|
* Obtain page after the last message saved (specific chat).
|
|
* <p>
|
|
* Note that the messageUid is the XEP-0313 UID and <b>not</b> the stanza ID of the message.
|
|
* </p>
|
|
*
|
|
* @param chatJid
|
|
* @param messageUid the UID of the message of which messages after should be received.
|
|
* @param max
|
|
* @return the MAM query result
|
|
* @throws XMPPErrorException
|
|
* @throws NotLoggedInException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NoResponseException
|
|
*/
|
|
public MamQueryResult pageAfter(Jid chatJid, String messageUid, int max) throws XMPPErrorException,
|
|
NotLoggedInException, NotConnectedException, InterruptedException, NoResponseException {
|
|
RSMSet rsmSet = new RSMSet(messageUid, null, -1, -1, null, max, null, -1);
|
|
DataForm dataForm = getNewMamForm();
|
|
addWithJid(chatJid, dataForm);
|
|
return page(null, dataForm, rsmSet);
|
|
}
|
|
|
|
/**
|
|
* Obtain the most recent page of a chat.
|
|
*
|
|
* @param chatJid
|
|
* @param max
|
|
* @return the MAM query result
|
|
* @throws XMPPErrorException
|
|
* @throws NotLoggedInException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NoResponseException
|
|
*/
|
|
public MamQueryResult mostRecentPage(Jid chatJid, int max) throws XMPPErrorException, NotLoggedInException,
|
|
NotConnectedException, InterruptedException, NoResponseException {
|
|
return pageBefore(chatJid, "", max);
|
|
}
|
|
|
|
/**
|
|
* Get the form fields supported by the server.
|
|
*
|
|
* @return the list of form fields.
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public List<FormField> retrieveFormFields() throws NoResponseException, XMPPErrorException, NotConnectedException,
|
|
InterruptedException, NotLoggedInException {
|
|
return retrieveFormFields(null);
|
|
}
|
|
|
|
/**
|
|
* Get the form fields supported by the server.
|
|
*
|
|
* @param node The PubSub node name, can be null
|
|
* @return the list of form fields.
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public List<FormField> retrieveFormFields(String node)
|
|
throws NoResponseException, XMPPErrorException, NotConnectedException,
|
|
InterruptedException, NotLoggedInException {
|
|
String queryId = UUID.randomUUID().toString();
|
|
MamQueryIQ mamQueryIq = new MamQueryIQ(queryId, node, null);
|
|
mamQueryIq.setTo(archiveAddress);
|
|
|
|
MamQueryIQ mamResponseQueryIq = connection().createStanzaCollectorAndSend(mamQueryIq).nextResultOrThrow();
|
|
|
|
return mamResponseQueryIq.getDataForm().getFields();
|
|
}
|
|
|
|
private MamQueryResult queryArchive(MamQueryIQ mamQueryIq) throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
final XMPPConnection connection = getAuthenticatedConnectionOrThrow();
|
|
MamFinIQ mamFinIQ;
|
|
|
|
StanzaCollector mamFinIQCollector = connection.createStanzaCollector(new IQReplyFilter(mamQueryIq, connection));
|
|
|
|
StanzaCollector.Configuration resultCollectorConfiguration = StanzaCollector.newConfiguration()
|
|
.setStanzaFilter(new MamResultFilter(mamQueryIq)).setCollectorToReset(mamFinIQCollector);
|
|
StanzaCollector resultCollector = connection.createStanzaCollector(resultCollectorConfiguration);
|
|
|
|
try {
|
|
connection.sendStanza(mamQueryIq);
|
|
mamFinIQ = mamFinIQCollector.nextResultOrThrow();
|
|
} finally {
|
|
mamFinIQCollector.cancel();
|
|
resultCollector.cancel();
|
|
}
|
|
|
|
List<Forwarded> forwardedMessages = new ArrayList<>(resultCollector.getCollectedCount());
|
|
|
|
for (Message resultMessage = resultCollector
|
|
.pollResult(); resultMessage != null; resultMessage = resultCollector.pollResult()) {
|
|
MamElements.MamResultExtension mamResultExtension = MamElements.MamResultExtension.from(resultMessage);
|
|
forwardedMessages.add(mamResultExtension.getForwarded());
|
|
}
|
|
|
|
return new MamQueryResult(forwardedMessages, mamFinIQ, mamQueryIq.getNode(), DataForm.from(mamQueryIq));
|
|
}
|
|
|
|
/**
|
|
* MAM query result class.
|
|
*
|
|
*/
|
|
public final static class MamQueryResult {
|
|
public final List<Forwarded> forwardedMessages;
|
|
public final MamFinIQ mamFin;
|
|
private final String node;
|
|
private final DataForm form;
|
|
|
|
private MamQueryResult(List<Forwarded> forwardedMessages, MamFinIQ mamFin, String node, DataForm form) {
|
|
this.forwardedMessages = forwardedMessages;
|
|
this.mamFin = mamFin;
|
|
this.node = node;
|
|
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 + '\'');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if MAM is supported for the XMPP connection managed by this MamManager.
|
|
*
|
|
* @return true if MAM is supported for the XMPP connection, <code>false</code>otherwhise.
|
|
*
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @since 4.2.1
|
|
* @see <a href="https://xmpp.org/extensions/xep-0313.html#support">XEP-0313 § 7. Determining support</a>
|
|
*/
|
|
public boolean isSupported() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
|
BareJid myBareJid = connection().getUser().asBareJid();
|
|
return serviceDiscoveryManager.supportsFeature(myBareJid, MamElements.NAMESPACE);
|
|
}
|
|
|
|
/**
|
|
* Returns true if Message Archive Management is supported by the server.
|
|
*
|
|
* @return true if Message Archive Management is supported by the server.
|
|
* @throws NotConnectedException
|
|
* @throws XMPPErrorException
|
|
* @throws NoResponseException
|
|
* @throws InterruptedException
|
|
* @deprecated use {@link #isSupported()} instead.
|
|
*/
|
|
@Deprecated
|
|
// TODO Remove in Smack 4.3
|
|
public boolean isSupportedByServer()
|
|
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
|
return ServiceDiscoveryManager.getInstanceFor(connection()).serverSupportsFeature(MamElements.NAMESPACE);
|
|
}
|
|
|
|
private static DataForm getNewMamForm() {
|
|
FormField field = new FormField(FormField.FORM_TYPE);
|
|
field.setType(FormField.Type.hidden);
|
|
field.addValue(MamElements.NAMESPACE);
|
|
DataForm form = new DataForm(DataForm.Type.submit);
|
|
form.addField(field);
|
|
return form;
|
|
}
|
|
|
|
/**
|
|
* Get the preferences stored in the server.
|
|
*
|
|
* @return the MAM preferences result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamPrefsResult retrieveArchivingPreferences() throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
MamPrefsIQ mamPrefIQ = new MamPrefsIQ();
|
|
return queryMamPrefs(mamPrefIQ);
|
|
}
|
|
|
|
/**
|
|
* Update the preferences in the server.
|
|
*
|
|
* @param alwaysJids
|
|
* is the list of JIDs that should always have messages to/from
|
|
* archived in the user's store
|
|
* @param neverJids
|
|
* is the list of JIDs that should never have messages to/from
|
|
* archived in the user's store
|
|
* @param defaultBehavior
|
|
* can be "roster", "always", "never" (see XEP-0313)
|
|
* @return the MAM preferences result
|
|
* @throws NoResponseException
|
|
* @throws XMPPErrorException
|
|
* @throws NotConnectedException
|
|
* @throws InterruptedException
|
|
* @throws NotLoggedInException
|
|
*/
|
|
public MamPrefsResult updateArchivingPreferences(List<Jid> alwaysJids, List<Jid> neverJids, DefaultBehavior defaultBehavior)
|
|
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException,
|
|
NotLoggedInException {
|
|
Objects.requireNonNull(defaultBehavior, "Default behavior must be set");
|
|
MamPrefsIQ mamPrefIQ = new MamPrefsIQ(alwaysJids, neverJids, defaultBehavior);
|
|
return queryMamPrefs(mamPrefIQ);
|
|
}
|
|
|
|
/**
|
|
* MAM preferences result class.
|
|
*
|
|
*/
|
|
public final static class MamPrefsResult {
|
|
public final MamPrefsIQ mamPrefs;
|
|
public final DataForm form;
|
|
|
|
private MamPrefsResult(MamPrefsIQ mamPrefs, DataForm form) {
|
|
this.mamPrefs = mamPrefs;
|
|
this.form = form;
|
|
}
|
|
}
|
|
|
|
private MamPrefsResult queryMamPrefs(MamPrefsIQ mamPrefsIQ) throws NoResponseException, XMPPErrorException,
|
|
NotConnectedException, InterruptedException, NotLoggedInException {
|
|
final XMPPConnection connection = getAuthenticatedConnectionOrThrow();
|
|
|
|
MamPrefsIQ mamPrefsResultIQ = connection.createStanzaCollectorAndSend(mamPrefsIQ).nextResultOrThrow();
|
|
|
|
return new MamPrefsResult(mamPrefsResultIQ, DataForm.from(mamPrefsIQ));
|
|
}
|
|
|
|
}
|