| /** |
| * Copyright 2013 Georg Lukas |
| * |
| * All rights reserved. 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.Collections; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.WeakHashMap; |
| |
| import org.jivesoftware.smack.Connection; |
| import org.jivesoftware.smack.ConnectionCreationListener; |
| import org.jivesoftware.smack.PacketListener; |
| import org.jivesoftware.smack.XMPPException; |
| import org.jivesoftware.smack.filter.PacketExtensionFilter; |
| import org.jivesoftware.smack.packet.Message; |
| import org.jivesoftware.smack.packet.Packet; |
| import org.jivesoftware.smackx.ServiceDiscoveryManager; |
| import org.jivesoftware.smackx.packet.DiscoverInfo; |
| |
| /** |
| * 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 |
| */ |
| public class DeliveryReceiptManager implements PacketListener { |
| |
| private static Map<Connection, DeliveryReceiptManager> instances = |
| Collections.synchronizedMap(new WeakHashMap<Connection, DeliveryReceiptManager>()); |
| |
| static { |
| Connection.addConnectionCreationListener(new ConnectionCreationListener() { |
| public void connectionCreated(Connection connection) { |
| new DeliveryReceiptManager(connection); |
| } |
| }); |
| } |
| |
| private Connection connection; |
| private boolean auto_receipts_enabled = false; |
| private Set<ReceiptReceivedListener> receiptReceivedListeners = Collections |
| .synchronizedSet(new HashSet<ReceiptReceivedListener>()); |
| |
| private DeliveryReceiptManager(Connection connection) { |
| ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); |
| sdm.addFeature(DeliveryReceipt.NAMESPACE); |
| this.connection = connection; |
| instances.put(connection, this); |
| |
| // register listener for delivery receipts and requests |
| connection.addPacketListener(this, new PacketExtensionFilter(DeliveryReceipt.NAMESPACE)); |
| } |
| |
| /** |
| * Obtain the DeliveryReceiptManager responsible for a connection. |
| * |
| * @param connection the connection object. |
| * |
| * @return the DeliveryReceiptManager instance for the given connection |
| */ |
| synchronized public static DeliveryReceiptManager getInstanceFor(Connection connection) { |
| DeliveryReceiptManager receiptManager = instances.get(connection); |
| |
| if (receiptManager == null) { |
| receiptManager = new DeliveryReceiptManager(connection); |
| } |
| |
| return receiptManager; |
| } |
| |
| /** |
| * Returns true if Delivery Receipts are supported by a given JID |
| * |
| * @param jid |
| * @return true if supported |
| */ |
| public boolean isSupported(String jid) { |
| try { |
| DiscoverInfo result = |
| ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(jid); |
| return result.containsFeature(DeliveryReceipt.NAMESPACE); |
| } |
| catch (XMPPException e) { |
| return false; |
| } |
| } |
| |
| // handle incoming receipts and receipt requests |
| @Override |
| public void processPacket(Packet packet) { |
| DeliveryReceipt dr = (DeliveryReceipt)packet.getExtension( |
| DeliveryReceipt.ELEMENT, DeliveryReceipt.NAMESPACE); |
| if (dr != null) { |
| // notify listeners of incoming receipt |
| for (ReceiptReceivedListener l : receiptReceivedListeners) { |
| l.onReceiptReceived(packet.getFrom(), packet.getTo(), dr.getId()); |
| } |
| |
| } |
| |
| // if enabled, automatically send a receipt |
| if (auto_receipts_enabled) { |
| DeliveryReceiptRequest drr = (DeliveryReceiptRequest)packet.getExtension( |
| DeliveryReceiptRequest.ELEMENT, DeliveryReceipt.NAMESPACE); |
| if (drr != null) { |
| Message ack = new Message(packet.getFrom(), Message.Type.normal); |
| ack.addExtension(new DeliveryReceipt(packet.getPacketID())); |
| connection.sendPacket(ack); |
| } |
| } |
| } |
| |
| /** |
| * 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 packet requires a delivery receipt. |
| * |
| * @param p Packet object to check for a DeliveryReceiptRequest |
| * |
| * @return true if a delivery receipt was requested |
| */ |
| public static boolean hasDeliveryReceiptRequest(Packet p) { |
| return (p.getExtension(DeliveryReceiptRequest.ELEMENT, |
| DeliveryReceipt.NAMESPACE) != 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 |
| */ |
| public static void addDeliveryReceiptRequest(Message m) { |
| m.addExtension(new DeliveryReceiptRequest()); |
| } |
| } |