mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-26 08:12:05 +01:00
Improve Message Delivery Receipt (XEP-184) API
add a new AutoReceiptMode enum that specifies how delivery receipt requests are handled. Default is to send receipts if the requstor is subscribed to the user's presence. Also make sure that messages contain an id if a receipt request is added to it.
This commit is contained in:
parent
293f90c6c6
commit
1bc3e10cff
6 changed files with 130 additions and 33 deletions
|
@ -35,6 +35,8 @@ public class MessageTypeFilter extends FlexiblePacketTypeFilter<Message> {
|
||||||
public static final PacketFilter HEADLINE = new MessageTypeFilter(Type.headline);
|
public static final PacketFilter HEADLINE = new MessageTypeFilter(Type.headline);
|
||||||
public static final PacketFilter ERROR = new MessageTypeFilter(Type.error);
|
public static final PacketFilter ERROR = new MessageTypeFilter(Type.error);
|
||||||
public static final PacketFilter NORMAL_OR_CHAT = new OrFilter(NORMAL, CHAT);
|
public static final PacketFilter NORMAL_OR_CHAT = new OrFilter(NORMAL, CHAT);
|
||||||
|
public static final PacketFilter NORMAL_OR_CHAT_OR_HEADLINE = new OrFilter(NORMAL_OR_CHAT,
|
||||||
|
HEADLINE);
|
||||||
|
|
||||||
private final Message.Type type;
|
private final Message.Type type;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Map;
|
||||||
import org.jivesoftware.smack.packet.Packet;
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
import org.jivesoftware.smack.packet.PacketExtension;
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
import org.jivesoftware.smack.provider.EmbeddedExtensionProvider;
|
import org.jivesoftware.smack.provider.EmbeddedExtensionProvider;
|
||||||
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a <b>message delivery receipt</b> entry as specified by
|
* Represents a <b>message delivery receipt</b> entry as specified by
|
||||||
|
@ -34,7 +35,10 @@ public class DeliveryReceipt implements PacketExtension
|
||||||
public static final String NAMESPACE = "urn:xmpp:receipts";
|
public static final String NAMESPACE = "urn:xmpp:receipts";
|
||||||
public static final String ELEMENT = "received";
|
public static final String ELEMENT = "received";
|
||||||
|
|
||||||
private String id; /// original ID of the delivered message
|
/**
|
||||||
|
* original ID of the delivered message
|
||||||
|
*/
|
||||||
|
private final String id;
|
||||||
|
|
||||||
public DeliveryReceipt(String id)
|
public DeliveryReceipt(String id)
|
||||||
{
|
{
|
||||||
|
@ -59,9 +63,12 @@ public class DeliveryReceipt implements PacketExtension
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toXML()
|
public XmlStringBuilder toXML()
|
||||||
{
|
{
|
||||||
return "<received xmlns='" + NAMESPACE + "' id='" + id + "'/>";
|
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||||
|
xml.attribute("id", id);
|
||||||
|
xml.closeEmptyElement();
|
||||||
|
return xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2013-2014 Georg Lukas
|
* Copyright 2013-2014 Georg Lukas, 2015 Florian Schmaus
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
|
@ -30,6 +30,7 @@ import org.jivesoftware.smack.PacketListener;
|
||||||
import org.jivesoftware.smack.XMPPConnectionRegistry;
|
import org.jivesoftware.smack.XMPPConnectionRegistry;
|
||||||
import org.jivesoftware.smack.XMPPException;
|
import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smack.filter.AndFilter;
|
import org.jivesoftware.smack.filter.AndFilter;
|
||||||
|
import org.jivesoftware.smack.filter.MessageTypeFilter;
|
||||||
import org.jivesoftware.smack.filter.PacketExtensionFilter;
|
import org.jivesoftware.smack.filter.PacketExtensionFilter;
|
||||||
import org.jivesoftware.smack.filter.PacketFilter;
|
import org.jivesoftware.smack.filter.PacketFilter;
|
||||||
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
||||||
|
@ -42,6 +43,24 @@ import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
* the manager for {@link DeliveryReceipt} support, enabling and disabling of
|
* the manager for {@link DeliveryReceipt} support, enabling and disabling of
|
||||||
* automatic DeliveryReceipt transmission.
|
* automatic DeliveryReceipt transmission.
|
||||||
*
|
*
|
||||||
|
* <p>
|
||||||
|
* You can send delivery receipt requests and listen for incoming delivery receipts as shown in this example:
|
||||||
|
* </p>
|
||||||
|
* <pre>
|
||||||
|
* deliveryReceiptManager.addReceiptReceivedListener(new ReceiptReceivedListener() {
|
||||||
|
* void onReceiptReceived(String fromJid, String toJid, String receiptId, Packet receipt) {
|
||||||
|
* // If the receiving entity does not support delivery receipts,
|
||||||
|
* // then the receipt received listener may not get invoked.
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* Message message = …
|
||||||
|
* DeliveryReceiptRequest.addTo(message);
|
||||||
|
* connection.sendPacket(message);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* DeliveryReceiptManager can be configured to automatically add delivery receipt requests to every
|
||||||
|
* message with {@link #autoAddDeliveryReceiptRequests()}.
|
||||||
|
*
|
||||||
* @author Georg Lukas
|
* @author Georg Lukas
|
||||||
* @see <a href="http://xmpp.org/extensions/xep-0184.html">XEP-0184: Message Delivery Receipts</a>
|
* @see <a href="http://xmpp.org/extensions/xep-0184.html">XEP-0184: Message Delivery Receipts</a>
|
||||||
*/
|
*/
|
||||||
|
@ -62,7 +81,43 @@ public class DeliveryReceiptManager extends Manager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean auto_receipts_enabled = false;
|
/**
|
||||||
|
* Specifies when incoming message delivery receipt requests should be automatically
|
||||||
|
* acknowledged with an receipt.
|
||||||
|
*/
|
||||||
|
public enum AutoReceiptMode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Never send deliver receipts
|
||||||
|
*/
|
||||||
|
disabled,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only send delivery receipts if the requester is subscribed to our presence.
|
||||||
|
*/
|
||||||
|
ifIsSubscribed,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always send delivery receipts. <b>Warning:</b> this may causes presence leaks. See <a
|
||||||
|
* href="http://xmpp.org/extensions/xep-0184.html#security">XEP-0184: Message Delivery
|
||||||
|
* Receipts § 8. Security Considerations</a>
|
||||||
|
*/
|
||||||
|
always,
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AutoReceiptMode defaultAutoReceiptMode = AutoReceiptMode.ifIsSubscribed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default automatic receipt mode for new connections.
|
||||||
|
*
|
||||||
|
* @param autoReceiptMode the default automatic receipt mode.
|
||||||
|
*/
|
||||||
|
public static void setDefaultAutoReceiptMode(AutoReceiptMode autoReceiptMode) {
|
||||||
|
defaultAutoReceiptMode = autoReceiptMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AutoReceiptMode autoReceiptMode = defaultAutoReceiptMode;
|
||||||
|
|
||||||
private final Set<ReceiptReceivedListener> receiptReceivedListeners = new CopyOnWriteArraySet<ReceiptReceivedListener>();
|
private final Set<ReceiptReceivedListener> receiptReceivedListeners = new CopyOnWriteArraySet<ReceiptReceivedListener>();
|
||||||
|
|
||||||
private DeliveryReceiptManager(XMPPConnection connection) {
|
private DeliveryReceiptManager(XMPPConnection connection) {
|
||||||
|
@ -86,13 +141,23 @@ public class DeliveryReceiptManager extends Manager {
|
||||||
connection.addAsyncPacketListener(new PacketListener() {
|
connection.addAsyncPacketListener(new PacketListener() {
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Packet packet) throws NotConnectedException {
|
public void processPacket(Packet packet) throws NotConnectedException {
|
||||||
// if enabled, automatically send a receipt
|
final String from = packet.getFrom();
|
||||||
if (!auto_receipts_enabled) {
|
final XMPPConnection connection = connection();
|
||||||
|
switch (autoReceiptMode) {
|
||||||
|
case disabled:
|
||||||
return;
|
return;
|
||||||
|
case ifIsSubscribed:
|
||||||
|
if (!connection.getRoster().isSubscribedToMyPresence(from)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case always:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
Message ack = new Message(packet.getFrom(), Message.Type.normal);
|
|
||||||
|
Message ack = new Message(from, Message.Type.normal);
|
||||||
ack.addExtension(new DeliveryReceipt(packet.getPacketID()));
|
ack.addExtension(new DeliveryReceipt(packet.getPacketID()));
|
||||||
connection().sendPacket(ack);
|
connection.sendPacket(ack);
|
||||||
}
|
}
|
||||||
}, MESSAGES_WITH_DEVLIERY_RECEIPT_REQUEST);
|
}, MESSAGES_WITH_DEVLIERY_RECEIPT_REQUEST);
|
||||||
}
|
}
|
||||||
|
@ -130,34 +195,22 @@ public class DeliveryReceiptManager extends Manager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure whether the {@link DeliveryReceiptManager} should automatically
|
* Configure whether the {@link DeliveryReceiptManager} should automatically
|
||||||
* reply to incoming {@link DeliveryReceipt}s. By default, this feature is off.
|
* reply to incoming {@link DeliveryReceipt}s.
|
||||||
*
|
*
|
||||||
* @param new_state whether automatic transmission of
|
* @param autoReceiptMode the new auto receipt mode.
|
||||||
* DeliveryReceipts should be enabled or disabled
|
* @see AutoReceiptMode
|
||||||
*/
|
*/
|
||||||
public void setAutoReceiptsEnabled(boolean new_state) {
|
public void setAutoReceiptMode(AutoReceiptMode autoReceiptMode) {
|
||||||
auto_receipts_enabled = new_state;
|
this.autoReceiptMode = autoReceiptMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to enable automatic DeliveryReceipt transmission.
|
* Get the currently active auto receipt mode.
|
||||||
|
*
|
||||||
|
* @return the currently active auto receipt mode.
|
||||||
*/
|
*/
|
||||||
public void enableAutoReceipts() {
|
public AutoReceiptMode getAutoReceiptMode() {
|
||||||
setAutoReceiptsEnabled(true);
|
return autoReceiptMode;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method to disable automatic DeliveryReceipt transmission.
|
|
||||||
*/
|
|
||||||
public void disableAutoReceipts() {
|
|
||||||
setAutoReceiptsEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if AutoReceipts are enabled on this connection.
|
|
||||||
*/
|
|
||||||
public boolean getAutoReceiptsEnabled() {
|
|
||||||
return this.auto_receipts_enabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,6 +231,35 @@ public class DeliveryReceiptManager extends Manager {
|
||||||
receiptReceivedListeners.remove(listener);
|
receiptReceivedListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final PacketListener AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER = new PacketListener() {
|
||||||
|
@Override
|
||||||
|
public void processPacket(Packet packet) throws NotConnectedException {
|
||||||
|
Message message = (Message) packet;
|
||||||
|
DeliveryReceiptRequest.addTo(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables automatic requests of delivery receipts for outgoing messages of type 'normal', 'chat' or 'headline.
|
||||||
|
*
|
||||||
|
* @since 4.1
|
||||||
|
* @see #dontAutoAddDeliveryReceiptRequests()
|
||||||
|
*/
|
||||||
|
public void autoAddDeliveryReceiptRequests() {
|
||||||
|
connection().addPacketSendingListener(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER,
|
||||||
|
MessageTypeFilter.NORMAL_OR_CHAT_OR_HEADLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables automatically requests of delivery receipts for outgoing messages.
|
||||||
|
*
|
||||||
|
* @since 4.1
|
||||||
|
* @see #autoAddDeliveryReceiptRequests()
|
||||||
|
*/
|
||||||
|
public void dontAutoAddDeliveryReceiptRequests() {
|
||||||
|
connection().removePacketSendingListener(AUTO_ADD_DELIVERY_RECEIPT_REQUESTS_LISTENER);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if a message requires a delivery receipt.
|
* Test if a message requires a delivery receipt.
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smack.packet.Packet;
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
import org.jivesoftware.smack.packet.PacketExtension;
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smack.packet.id.StanzaIdUtil;
|
||||||
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
@ -82,6 +83,9 @@ public class DeliveryReceiptRequest implements PacketExtension
|
||||||
* @return the Message ID which will be used as receipt ID
|
* @return the Message ID which will be used as receipt ID
|
||||||
*/
|
*/
|
||||||
public static String addTo(Message message) {
|
public static String addTo(Message message) {
|
||||||
|
if (message.getPacketID() == null) {
|
||||||
|
message.setPacketID(StanzaIdUtil.newStanzaId());
|
||||||
|
}
|
||||||
message.addExtension(new DeliveryReceiptRequest());
|
message.addExtension(new DeliveryReceiptRequest());
|
||||||
return message.getPacketID();
|
return message.getPacketID();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,6 @@
|
||||||
<className>org.jivesoftware.smackx.xdata.XDataManager</className>
|
<className>org.jivesoftware.smackx.xdata.XDataManager</className>
|
||||||
<className>org.jivesoftware.smackx.xdatalayout.XDataLayoutManager</className>
|
<className>org.jivesoftware.smackx.xdatalayout.XDataLayoutManager</className>
|
||||||
<className>org.jivesoftware.smackx.xdatavalidation.XDataValidationManager</className>
|
<className>org.jivesoftware.smackx.xdatavalidation.XDataValidationManager</className>
|
||||||
|
<className>org.jivesoftware.smackx.receipts.DeliveryReceiptManager</className>
|
||||||
</startupClasses>
|
</startupClasses>
|
||||||
</smack>
|
</smack>
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.jivesoftware.smack.packet.Packet;
|
||||||
import org.jivesoftware.smack.test.util.WaitForPacketListener;
|
import org.jivesoftware.smack.test.util.WaitForPacketListener;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
import org.jivesoftware.smackx.InitExtensions;
|
import org.jivesoftware.smackx.InitExtensions;
|
||||||
|
import org.jivesoftware.smackx.receipts.DeliveryReceiptManager.AutoReceiptMode;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
@ -101,8 +102,8 @@ public class DeliveryReceiptTest extends InitExtensions {
|
||||||
c.connect();
|
c.connect();
|
||||||
DeliveryReceiptManager drm = DeliveryReceiptManager.getInstanceFor(c);
|
DeliveryReceiptManager drm = DeliveryReceiptManager.getInstanceFor(c);
|
||||||
|
|
||||||
drm.enableAutoReceipts();
|
drm.setAutoReceiptMode(AutoReceiptMode.always);
|
||||||
assertTrue(drm.getAutoReceiptsEnabled());
|
assertEquals(AutoReceiptMode.always, drm.getAutoReceiptMode());
|
||||||
|
|
||||||
// test auto-receipts
|
// test auto-receipts
|
||||||
Message m = new Message("julia@capulet.com", Message.Type.normal);
|
Message m = new Message("julia@capulet.com", Message.Type.normal);
|
||||||
|
|
Loading…
Reference in a new issue