aboutsummaryrefslogtreecommitdiff
path: root/src/org/jivesoftware/smackx/OfflineMessageManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/jivesoftware/smackx/OfflineMessageManager.java')
-rw-r--r--src/org/jivesoftware/smackx/OfflineMessageManager.java284
1 files changed, 284 insertions, 0 deletions
diff --git a/src/org/jivesoftware/smackx/OfflineMessageManager.java b/src/org/jivesoftware/smackx/OfflineMessageManager.java
new file mode 100644
index 0000000..dbe889d
--- /dev/null
+++ b/src/org/jivesoftware/smackx/OfflineMessageManager.java
@@ -0,0 +1,284 @@
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2003-2007 Jive Software.
+ *
+ * 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;
+
+import org.jivesoftware.smack.PacketCollector;
+import org.jivesoftware.smack.SmackConfiguration;
+import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.filter.*;
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.Message;
+import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smackx.packet.DiscoverInfo;
+import org.jivesoftware.smackx.packet.DiscoverItems;
+import org.jivesoftware.smackx.packet.OfflineMessageInfo;
+import org.jivesoftware.smackx.packet.OfflineMessageRequest;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * The OfflineMessageManager helps manage offline messages even before the user has sent an
+ * available presence. When a user asks for his offline messages before sending an available
+ * presence then the server will not send a flood with all the offline messages when the user
+ * becomes online. The server will not send a flood with all the offline messages to the session
+ * that made the offline messages request or to any other session used by the user that becomes
+ * online.<p>
+ *
+ * Once the session that made the offline messages request has been closed and the user becomes
+ * offline in all the resources then the server will resume storing the messages offline and will
+ * send all the offline messages to the user when he becomes online. Therefore, the server will
+ * flood the user when he becomes online unless the user uses this class to manage his offline
+ * messages.
+ *
+ * @author Gaston Dombiak
+ */
+public class OfflineMessageManager {
+
+ private final static String namespace = "http://jabber.org/protocol/offline";
+
+ private Connection connection;
+
+ private PacketFilter packetFilter;
+
+ public OfflineMessageManager(Connection connection) {
+ this.connection = connection;
+ packetFilter =
+ new AndFilter(new PacketExtensionFilter("offline", namespace),
+ new PacketTypeFilter(Message.class));
+ }
+
+ /**
+ * Returns true if the server supports Flexible Offline Message Retrieval. When the server
+ * supports Flexible Offline Message Retrieval it is possible to get the header of the offline
+ * messages, get specific messages, delete specific messages, etc.
+ *
+ * @return a boolean indicating if the server supports Flexible Offline Message Retrieval.
+ * @throws XMPPException If the user is not allowed to make this request.
+ */
+ public boolean supportsFlexibleRetrieval() throws XMPPException {
+ DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(connection.getServiceName());
+ return info.containsFeature(namespace);
+ }
+
+ /**
+ * Returns the number of offline messages for the user of the connection.
+ *
+ * @return the number of offline messages for the user of the connection.
+ * @throws XMPPException If the user is not allowed to make this request or the server does
+ * not support offline message retrieval.
+ */
+ public int getMessageCount() throws XMPPException {
+ DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(null,
+ namespace);
+ Form extendedInfo = Form.getFormFrom(info);
+ if (extendedInfo != null) {
+ String value = extendedInfo.getField("number_of_messages").getValues().next();
+ return Integer.parseInt(value);
+ }
+ return 0;
+ }
+
+ /**
+ * Returns an iterator on <tt>OfflineMessageHeader</tt> that keep information about the
+ * offline message. The OfflineMessageHeader includes a stamp that could be used to retrieve
+ * the complete message or delete the specific message.
+ *
+ * @return an iterator on <tt>OfflineMessageHeader</tt> that keep information about the offline
+ * message.
+ * @throws XMPPException If the user is not allowed to make this request or the server does
+ * not support offline message retrieval.
+ */
+ public Iterator<OfflineMessageHeader> getHeaders() throws XMPPException {
+ List<OfflineMessageHeader> answer = new ArrayList<OfflineMessageHeader>();
+ DiscoverItems items = ServiceDiscoveryManager.getInstanceFor(connection).discoverItems(
+ null, namespace);
+ for (Iterator<DiscoverItems.Item> it = items.getItems(); it.hasNext();) {
+ DiscoverItems.Item item = it.next();
+ answer.add(new OfflineMessageHeader(item));
+ }
+ return answer.iterator();
+ }
+
+ /**
+ * Returns an Iterator with the offline <tt>Messages</tt> whose stamp matches the specified
+ * request. The request will include the list of stamps that uniquely identifies
+ * the offline messages to retrieve. The returned offline messages will not be deleted
+ * from the server. Use {@link #deleteMessages(java.util.List)} to delete the messages.
+ *
+ * @param nodes the list of stamps that uniquely identifies offline message.
+ * @return an Iterator with the offline <tt>Messages</tt> that were received as part of
+ * this request.
+ * @throws XMPPException If the user is not allowed to make this request or the server does
+ * not support offline message retrieval.
+ */
+ public Iterator<Message> getMessages(final List<String> nodes) throws XMPPException {
+ List<Message> messages = new ArrayList<Message>();
+ OfflineMessageRequest request = new OfflineMessageRequest();
+ for (String node : nodes) {
+ OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
+ item.setAction("view");
+ request.addItem(item);
+ }
+ // Filter packets looking for an answer from the server.
+ PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
+ PacketCollector response = connection.createPacketCollector(responseFilter);
+ // Filter offline messages that were requested by this request
+ PacketFilter messageFilter = new AndFilter(packetFilter, new PacketFilter() {
+ public boolean accept(Packet packet) {
+ OfflineMessageInfo info = (OfflineMessageInfo) packet.getExtension("offline",
+ namespace);
+ return nodes.contains(info.getNode());
+ }
+ });
+ PacketCollector messageCollector = connection.createPacketCollector(messageFilter);
+ // Send the retrieval request to the server.
+ connection.sendPacket(request);
+ // Wait up to a certain number of seconds for a reply.
+ IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ // Stop queuing results
+ response.cancel();
+
+ if (answer == null) {
+ throw new XMPPException("No response from server.");
+ } else if (answer.getError() != null) {
+ throw new XMPPException(answer.getError());
+ }
+
+ // Collect the received offline messages
+ Message message = (Message) messageCollector.nextResult(
+ SmackConfiguration.getPacketReplyTimeout());
+ while (message != null) {
+ messages.add(message);
+ message =
+ (Message) messageCollector.nextResult(
+ SmackConfiguration.getPacketReplyTimeout());
+ }
+ // Stop queuing offline messages
+ messageCollector.cancel();
+ return messages.iterator();
+ }
+
+ /**
+ * Returns an Iterator with all the offline <tt>Messages</tt> of the user. The returned offline
+ * messages will not be deleted from the server. Use {@link #deleteMessages(java.util.List)}
+ * to delete the messages.
+ *
+ * @return an Iterator with all the offline <tt>Messages</tt> of the user.
+ * @throws XMPPException If the user is not allowed to make this request or the server does
+ * not support offline message retrieval.
+ */
+ public Iterator<Message> getMessages() throws XMPPException {
+ List<Message> messages = new ArrayList<Message>();
+ OfflineMessageRequest request = new OfflineMessageRequest();
+ request.setFetch(true);
+ // Filter packets looking for an answer from the server.
+ PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
+ PacketCollector response = connection.createPacketCollector(responseFilter);
+ // Filter offline messages that were requested by this request
+ PacketCollector messageCollector = connection.createPacketCollector(packetFilter);
+ // Send the retrieval request to the server.
+ connection.sendPacket(request);
+ // Wait up to a certain number of seconds for a reply.
+ IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ // Stop queuing results
+ response.cancel();
+
+ if (answer == null) {
+ throw new XMPPException("No response from server.");
+ } else if (answer.getError() != null) {
+ throw new XMPPException(answer.getError());
+ }
+
+ // Collect the received offline messages
+ Message message = (Message) messageCollector.nextResult(
+ SmackConfiguration.getPacketReplyTimeout());
+ while (message != null) {
+ messages.add(message);
+ message =
+ (Message) messageCollector.nextResult(
+ SmackConfiguration.getPacketReplyTimeout());
+ }
+ // Stop queuing offline messages
+ messageCollector.cancel();
+ return messages.iterator();
+ }
+
+ /**
+ * Deletes the specified list of offline messages. The request will include the list of
+ * stamps that uniquely identifies the offline messages to delete.
+ *
+ * @param nodes the list of stamps that uniquely identifies offline message.
+ * @throws XMPPException If the user is not allowed to make this request or the server does
+ * not support offline message retrieval.
+ */
+ public void deleteMessages(List<String> nodes) throws XMPPException {
+ OfflineMessageRequest request = new OfflineMessageRequest();
+ for (String node : nodes) {
+ OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
+ item.setAction("remove");
+ request.addItem(item);
+ }
+ // Filter packets looking for an answer from the server.
+ PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
+ PacketCollector response = connection.createPacketCollector(responseFilter);
+ // Send the deletion request to the server.
+ connection.sendPacket(request);
+ // Wait up to a certain number of seconds for a reply.
+ IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ // Stop queuing results
+ response.cancel();
+
+ if (answer == null) {
+ throw new XMPPException("No response from server.");
+ } else if (answer.getError() != null) {
+ throw new XMPPException(answer.getError());
+ }
+ }
+
+ /**
+ * Deletes all offline messages of the user.
+ *
+ * @throws XMPPException If the user is not allowed to make this request or the server does
+ * not support offline message retrieval.
+ */
+ public void deleteMessages() throws XMPPException {
+ OfflineMessageRequest request = new OfflineMessageRequest();
+ request.setPurge(true);
+ // Filter packets looking for an answer from the server.
+ PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
+ PacketCollector response = connection.createPacketCollector(responseFilter);
+ // Send the deletion request to the server.
+ connection.sendPacket(request);
+ // Wait up to a certain number of seconds for a reply.
+ IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ // Stop queuing results
+ response.cancel();
+
+ if (answer == null) {
+ throw new XMPPException("No response from server.");
+ } else if (answer.getError() != null) {
+ throw new XMPPException(answer.getError());
+ }
+ }
+}