/** * * Copyright 2013-2014 Georg Lukas * * 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.receipts; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.CopyOnWriteArraySet; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.ConnectionCreationListener; import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.XMPPConnectionRegistry; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.filter.PacketExtensionFilter; import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.filter.PacketTypeFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; /** * Manager for XEP-0184: Message Delivery Receipts. This class implements * the manager for {@link DeliveryReceipt} support, enabling and disabling of * automatic DeliveryReceipt transmission. * * @author Georg Lukas * @see XEP-0184: Message Delivery Receipts */ public class DeliveryReceiptManager extends Manager { private static final PacketFilter MESSAGES_WITH_DEVLIERY_RECEIPT_REQUEST = new AndFilter(PacketTypeFilter.MESSAGE, new PacketExtensionFilter(new DeliveryReceiptRequest())); private static final PacketFilter MESSAGES_WITH_DELIVERY_RECEIPT = new AndFilter(PacketTypeFilter.MESSAGE, new PacketExtensionFilter(DeliveryReceipt.ELEMENT, DeliveryReceipt.NAMESPACE)); private static Map instances = new WeakHashMap(); static { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { public void connectionCreated(XMPPConnection connection) { getInstanceFor(connection); } }); } private boolean auto_receipts_enabled = false; private final Set receiptReceivedListeners = new CopyOnWriteArraySet(); private DeliveryReceiptManager(XMPPConnection connection) { super(connection); ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); sdm.addFeature(DeliveryReceipt.NAMESPACE); // Add the packet listener to handling incoming delivery receipts connection.addAsyncPacketListener(new PacketListener() { @Override public void processPacket(Packet packet) throws NotConnectedException { DeliveryReceipt dr = DeliveryReceipt.from(packet); // notify listeners of incoming receipt for (ReceiptReceivedListener l : receiptReceivedListeners) { l.onReceiptReceived(packet.getFrom(), packet.getTo(), dr.getId(), packet); } } }, MESSAGES_WITH_DELIVERY_RECEIPT); // Add the packet listener to handle incoming delivery receipt requests connection.addAsyncPacketListener(new PacketListener() { @Override public void processPacket(Packet packet) throws NotConnectedException { // if enabled, automatically send a receipt if (!auto_receipts_enabled) { return; } Message ack = new Message(packet.getFrom(), Message.Type.normal); ack.addExtension(new DeliveryReceipt(packet.getPacketID())); connection().sendPacket(ack); } }, MESSAGES_WITH_DEVLIERY_RECEIPT_REQUEST); } /** * Obtain the DeliveryReceiptManager responsible for a connection. * * @param connection the connection object. * * @return the DeliveryReceiptManager instance for the given connection */ public static synchronized DeliveryReceiptManager getInstanceFor(XMPPConnection connection) { DeliveryReceiptManager receiptManager = instances.get(connection); if (receiptManager == null) { receiptManager = new DeliveryReceiptManager(connection); instances.put(connection, receiptManager); } return receiptManager; } /** * Returns true if Delivery Receipts are supported by a given JID * * @param jid * @return true if supported * @throws SmackException if there was no response from the server. * @throws XMPPException */ public boolean isSupported(String jid) throws SmackException, XMPPException { return ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(jid, DeliveryReceipt.NAMESPACE); } /** * Configure whether the {@link DeliveryReceiptManager} should automatically * reply to incoming {@link DeliveryReceipt}s. By default, this feature is off. * * @param new_state whether automatic transmission of * DeliveryReceipts should be enabled or disabled */ public void setAutoReceiptsEnabled(boolean new_state) { auto_receipts_enabled = new_state; } /** * Helper method to enable automatic DeliveryReceipt transmission. */ public void enableAutoReceipts() { setAutoReceiptsEnabled(true); } /** * 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; } /** * Get informed about incoming delivery receipts with a {@link ReceiptReceivedListener}. * * @param listener the listener to be informed about new receipts */ public void addReceiptReceivedListener(ReceiptReceivedListener listener) { receiptReceivedListeners.add(listener); } /** * Stop getting informed about incoming delivery receipts. * * @param listener the listener to be removed */ public void removeReceiptReceivedListener(ReceiptReceivedListener listener) { receiptReceivedListeners.remove(listener); } /** * Test if a message requires a delivery receipt. * * @param message Packet object to check for a DeliveryReceiptRequest * * @return true if a delivery receipt was requested */ public static boolean hasDeliveryReceiptRequest(Message message) { return (DeliveryReceiptRequest.from(message) != null); } /** * Add a delivery receipt request to an outgoing packet. * * Only message packets may contain receipt requests as of XEP-0184, * therefore only allow Message as the parameter type. * * @param m Message object to add a request to * @return the Message ID which will be used as receipt ID * @deprecated use {@link DeliveryReceiptRequest#addTo(Message)} */ @Deprecated public static String addDeliveryReceiptRequest(Message m) { return DeliveryReceiptRequest.addTo(m); } }