1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2003-2007 Jive Software.
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License.
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *     http://www.apache.org/licenses/LICENSE-2.0
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS,
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License.
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smackx;
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.PacketCollector;
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.SmackConfiguration;
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.Connection;
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.XMPPException;
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.*;
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.IQ;
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Message;
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Packet;
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.DiscoverInfo;
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.DiscoverItems;
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.OfflineMessageInfo;
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.OfflineMessageRequest;
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.ArrayList;
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Iterator;
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.List;
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The OfflineMessageManager helps manage offline messages even before the user has sent an
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * available presence. When a user asks for his offline messages before sending an available
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * presence then the server will not send a flood with all the offline messages when the user
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * becomes online. The server will not send a flood with all the offline messages to the session
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that made the offline messages request or to any other session used by the user that becomes
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * online.<p>
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Once the session that made the offline messages request has been closed and the user becomes
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * offline in all the resources then the server will resume storing the messages offline and will
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * send all the offline messages to the user when he becomes online. Therefore, the server will
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * flood the user when he becomes online unless the user uses this class to manage his offline
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * messages.
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Gaston Dombiak
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class OfflineMessageManager {
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final static String namespace = "http://jabber.org/protocol/offline";
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private Connection connection;
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private PacketFilter packetFilter;
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public OfflineMessageManager(Connection connection) {
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.connection = connection;
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        packetFilter =
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                new AndFilter(new PacketExtensionFilter("offline", namespace),
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        new PacketTypeFilter(Message.class));
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns true if the server supports Flexible Offline Message Retrieval. When the server
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * supports Flexible Offline Message Retrieval it is possible to get the header of the offline
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * messages, get specific messages, delete specific messages, etc.
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return a boolean indicating if the server supports Flexible Offline Message Retrieval.
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException If the user is not allowed to make this request.
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public boolean supportsFlexibleRetrieval() throws XMPPException {
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(connection.getServiceName());
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return info.containsFeature(namespace);
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the number of offline messages for the user of the connection.
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the number of offline messages for the user of the connection.
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException If the user is not allowed to make this request or the server does
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *                       not support offline message retrieval.
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public int getMessageCount() throws XMPPException {
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(null,
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                namespace);
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        Form extendedInfo = Form.getFormFrom(info);
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (extendedInfo != null) {
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            String value = extendedInfo.getField("number_of_messages").getValues().next();
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return Integer.parseInt(value);
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return 0;
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns an iterator on <tt>OfflineMessageHeader</tt> that keep information about the
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * offline message. The OfflineMessageHeader includes a stamp that could be used to retrieve
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the complete message or delete the specific message.
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return an iterator on <tt>OfflineMessageHeader</tt> that keep information about the offline
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *         message.
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException If the user is not allowed to make this request or the server does
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *                       not support offline message retrieval.
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public Iterator<OfflineMessageHeader> getHeaders() throws XMPPException {
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        List<OfflineMessageHeader> answer = new ArrayList<OfflineMessageHeader>();
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        DiscoverItems items = ServiceDiscoveryManager.getInstanceFor(connection).discoverItems(
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                null, namespace);
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        for (Iterator<DiscoverItems.Item> it = items.getItems(); it.hasNext();) {
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            DiscoverItems.Item item = it.next();
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            answer.add(new OfflineMessageHeader(item));
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return answer.iterator();
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns an Iterator with the offline <tt>Messages</tt> whose stamp matches the specified
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * request. The request will include the list of stamps that uniquely identifies
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the offline messages to retrieve. The returned offline messages will not be deleted
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * from the server. Use {@link #deleteMessages(java.util.List)} to delete the messages.
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param nodes the list of stamps that uniquely identifies offline message.
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return an Iterator with the offline <tt>Messages</tt> that were received as part of
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *         this request.
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException If the user is not allowed to make this request or the server does
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *                       not support offline message retrieval.
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public Iterator<Message> getMessages(final List<String> nodes) throws XMPPException {
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        List<Message> messages = new ArrayList<Message>();
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        OfflineMessageRequest request = new OfflineMessageRequest();
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        for (String node : nodes) {
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            item.setAction("view");
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            request.addItem(item);
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Filter packets looking for an answer from the server.
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketCollector response = connection.createPacketCollector(responseFilter);
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Filter offline messages that were requested by this request
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketFilter messageFilter = new AndFilter(packetFilter, new PacketFilter() {
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            public boolean accept(Packet packet) {
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                OfflineMessageInfo info = (OfflineMessageInfo) packet.getExtension("offline",
150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        namespace);
151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                return nodes.contains(info.getNode());
152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        });
154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketCollector messageCollector = connection.createPacketCollector(messageFilter);
155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Send the retrieval request to the server.
156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        connection.sendPacket(request);
157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Wait up to a certain number of seconds for a reply.
158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Stop queuing results
160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        response.cancel();
161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (answer == null) {
163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new XMPPException("No response from server.");
164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        } else if (answer.getError() != null) {
165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new XMPPException(answer.getError());
166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Collect the received offline messages
169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        Message message = (Message) messageCollector.nextResult(
170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                SmackConfiguration.getPacketReplyTimeout());
171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        while (message != null) {
172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            messages.add(message);
173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            message =
174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    (Message) messageCollector.nextResult(
175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            SmackConfiguration.getPacketReplyTimeout());
176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Stop queuing offline messages
178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        messageCollector.cancel();
179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return messages.iterator();
180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns an Iterator with all the offline <tt>Messages</tt> of the user. The returned offline
184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * messages will not be deleted from the server. Use {@link #deleteMessages(java.util.List)}
185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * to delete the messages.
186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return an Iterator with all the offline <tt>Messages</tt> of the user.
188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException If the user is not allowed to make this request or the server does
189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *                       not support offline message retrieval.
190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public Iterator<Message> getMessages() throws XMPPException {
192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        List<Message> messages = new ArrayList<Message>();
193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        OfflineMessageRequest request = new OfflineMessageRequest();
194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        request.setFetch(true);
195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Filter packets looking for an answer from the server.
196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketCollector response = connection.createPacketCollector(responseFilter);
198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Filter offline messages that were requested by this request
199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketCollector messageCollector = connection.createPacketCollector(packetFilter);
200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Send the retrieval request to the server.
201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        connection.sendPacket(request);
202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Wait up to a certain number of seconds for a reply.
203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Stop queuing results
205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        response.cancel();
206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (answer == null) {
208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new XMPPException("No response from server.");
209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        } else if (answer.getError() != null) {
210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new XMPPException(answer.getError());
211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Collect the received offline messages
214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        Message message = (Message) messageCollector.nextResult(
215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                SmackConfiguration.getPacketReplyTimeout());
216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        while (message != null) {
217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            messages.add(message);
218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            message =
219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    (Message) messageCollector.nextResult(
220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            SmackConfiguration.getPacketReplyTimeout());
221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Stop queuing offline messages
223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        messageCollector.cancel();
224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return messages.iterator();
225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Deletes the specified list of offline messages. The request will include the list of
229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * stamps that uniquely identifies the offline messages to delete.
230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param nodes the list of stamps that uniquely identifies offline message.
232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException If the user is not allowed to make this request or the server does
233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *                       not support offline message retrieval.
234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void deleteMessages(List<String> nodes) throws XMPPException {
236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        OfflineMessageRequest request = new OfflineMessageRequest();
237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        for (String node : nodes) {
238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            item.setAction("remove");
240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            request.addItem(item);
241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Filter packets looking for an answer from the server.
243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketCollector response = connection.createPacketCollector(responseFilter);
245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Send the deletion request to the server.
246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        connection.sendPacket(request);
247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Wait up to a certain number of seconds for a reply.
248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Stop queuing results
250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        response.cancel();
251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (answer == null) {
253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new XMPPException("No response from server.");
254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        } else if (answer.getError() != null) {
255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new XMPPException(answer.getError());
256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Deletes all offline messages of the user.
261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException If the user is not allowed to make this request or the server does
263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *                       not support offline message retrieval.
264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void deleteMessages() throws XMPPException {
266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        OfflineMessageRequest request = new OfflineMessageRequest();
267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        request.setPurge(true);
268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Filter packets looking for an answer from the server.
269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketCollector response = connection.createPacketCollector(responseFilter);
271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Send the deletion request to the server.
272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        connection.sendPacket(request);
273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Wait up to a certain number of seconds for a reply.
274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Stop queuing results
276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        response.cancel();
277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (answer == null) {
279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new XMPPException("No response from server.");
280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        } else if (answer.getError() != null) {
281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new XMPPException(answer.getError());
282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
285