2005-07-26 06:57:36 +02:00
|
|
|
/**
|
|
|
|
*
|
2007-02-12 01:59:05 +01:00
|
|
|
* Copyright 2003-2007 Jive Software.
|
2005-07-26 06:57:36 +02:00
|
|
|
*
|
2014-02-17 18:57:38 +01:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
2005-07-26 06:57:36 +02:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2014-02-15 11:35:08 +01:00
|
|
|
package org.jivesoftware.smackx.offline;
|
2005-07-26 06:57:36 +02:00
|
|
|
|
|
|
|
import org.jivesoftware.smack.PacketCollector;
|
2014-03-12 11:50:05 +01:00
|
|
|
import org.jivesoftware.smack.SmackException.NoResponseException;
|
2014-03-19 14:22:20 +01:00
|
|
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
2014-03-10 09:45:50 +01:00
|
|
|
import org.jivesoftware.smack.XMPPConnection;
|
2014-03-12 11:50:05 +01:00
|
|
|
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
2014-02-18 15:05:19 +01:00
|
|
|
import org.jivesoftware.smack.filter.AndFilter;
|
|
|
|
import org.jivesoftware.smack.filter.PacketExtensionFilter;
|
|
|
|
import org.jivesoftware.smack.filter.PacketFilter;
|
|
|
|
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
2005-07-26 06:57:36 +02:00
|
|
|
import org.jivesoftware.smack.packet.Message;
|
|
|
|
import org.jivesoftware.smack.packet.Packet;
|
2014-02-15 11:35:08 +01:00
|
|
|
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
|
|
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
|
|
|
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
|
|
|
|
import org.jivesoftware.smackx.offline.packet.OfflineMessageInfo;
|
|
|
|
import org.jivesoftware.smackx.offline.packet.OfflineMessageRequest;
|
|
|
|
import org.jivesoftware.smackx.xdata.Form;
|
2005-07-26 06:57:36 +02:00
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
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";
|
|
|
|
|
2014-06-10 18:54:53 +02:00
|
|
|
private final XMPPConnection connection;
|
2005-07-26 06:57:36 +02:00
|
|
|
|
2014-06-10 18:54:53 +02:00
|
|
|
private static final PacketFilter PACKET_FILTER = new AndFilter(new PacketExtensionFilter(
|
2014-11-09 11:02:49 +01:00
|
|
|
new OfflineMessageInfo()), new PacketTypeFilter(Message.class));
|
2005-07-26 06:57:36 +02:00
|
|
|
|
2014-03-10 09:45:50 +01:00
|
|
|
public OfflineMessageManager(XMPPConnection connection) {
|
2005-07-26 06:57:36 +02:00
|
|
|
this.connection = connection;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws XMPPErrorException If the user is not allowed to make this request.
|
|
|
|
* @throws NoResponseException if there was no response from the server.
|
2014-03-19 14:22:20 +01:00
|
|
|
* @throws NotConnectedException
|
2005-07-26 06:57:36 +02:00
|
|
|
*/
|
2014-03-19 14:22:20 +01:00
|
|
|
public boolean supportsFlexibleRetrieval() throws NoResponseException, XMPPErrorException, NotConnectedException {
|
2014-03-12 11:50:05 +01:00
|
|
|
return ServiceDiscoveryManager.getInstanceFor(connection).supportsFeature(connection.getServiceName(), namespace);
|
2005-07-26 06:57:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the number of offline messages for the user of the connection.
|
|
|
|
*
|
|
|
|
* @return the number of offline messages for the user of the connection.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws XMPPErrorException If the user is not allowed to make this request or the server does
|
2005-07-26 06:57:36 +02:00
|
|
|
* not support offline message retrieval.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws NoResponseException if there was no response from the server.
|
2014-03-19 14:22:20 +01:00
|
|
|
* @throws NotConnectedException
|
2005-07-26 06:57:36 +02:00
|
|
|
*/
|
2014-03-19 14:22:20 +01:00
|
|
|
public int getMessageCount() throws NoResponseException, XMPPErrorException, NotConnectedException {
|
2005-07-26 06:57:36 +02:00
|
|
|
DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(null,
|
|
|
|
namespace);
|
|
|
|
Form extendedInfo = Form.getFormFrom(info);
|
|
|
|
if (extendedInfo != null) {
|
2014-04-09 08:26:28 +02:00
|
|
|
String value = extendedInfo.getField("number_of_messages").getValues().get(0);
|
2005-07-26 06:57:36 +02:00
|
|
|
return Integer.parseInt(value);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-04-09 08:26:28 +02:00
|
|
|
* Returns a List of <tt>OfflineMessageHeader</tt> that keep information about the
|
2005-07-26 06:57:36 +02:00
|
|
|
* offline message. The OfflineMessageHeader includes a stamp that could be used to retrieve
|
|
|
|
* the complete message or delete the specific message.
|
|
|
|
*
|
2014-04-09 08:26:28 +02:00
|
|
|
* @return a List of <tt>OfflineMessageHeader</tt> that keep information about the offline
|
2005-07-26 06:57:36 +02:00
|
|
|
* message.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws XMPPErrorException If the user is not allowed to make this request or the server does
|
2005-07-26 06:57:36 +02:00
|
|
|
* not support offline message retrieval.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws NoResponseException if there was no response from the server.
|
2014-03-19 14:22:20 +01:00
|
|
|
* @throws NotConnectedException
|
2005-07-26 06:57:36 +02:00
|
|
|
*/
|
2014-04-09 08:26:28 +02:00
|
|
|
public List<OfflineMessageHeader> getHeaders() throws NoResponseException, XMPPErrorException, NotConnectedException {
|
2006-07-18 07:14:33 +02:00
|
|
|
List<OfflineMessageHeader> answer = new ArrayList<OfflineMessageHeader>();
|
2005-07-26 06:57:36 +02:00
|
|
|
DiscoverItems items = ServiceDiscoveryManager.getInstanceFor(connection).discoverItems(
|
|
|
|
null, namespace);
|
2014-03-24 22:31:42 +01:00
|
|
|
for (DiscoverItems.Item item : items.getItems()) {
|
2005-07-26 06:57:36 +02:00
|
|
|
answer.add(new OfflineMessageHeader(item));
|
|
|
|
}
|
2014-04-09 08:26:28 +02:00
|
|
|
return answer;
|
2005-07-26 06:57:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-04-09 08:26:28 +02:00
|
|
|
* Returns a List of the offline <tt>Messages</tt> whose stamp matches the specified
|
2005-07-26 06:57:36 +02:00
|
|
|
* 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.
|
2014-04-09 08:26:28 +02:00
|
|
|
* @return a List with the offline <tt>Messages</tt> that were received as part of
|
2005-07-26 06:57:36 +02:00
|
|
|
* this request.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws XMPPErrorException If the user is not allowed to make this request or the server does
|
2005-07-26 06:57:36 +02:00
|
|
|
* not support offline message retrieval.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws NoResponseException if there was no response from the server.
|
2014-03-19 14:22:20 +01:00
|
|
|
* @throws NotConnectedException
|
2005-07-26 06:57:36 +02:00
|
|
|
*/
|
2014-04-09 08:26:28 +02:00
|
|
|
public List<Message> getMessages(final List<String> nodes) throws NoResponseException, XMPPErrorException, NotConnectedException {
|
2006-07-18 07:14:33 +02:00
|
|
|
List<Message> messages = new ArrayList<Message>();
|
2005-07-26 06:57:36 +02:00
|
|
|
OfflineMessageRequest request = new OfflineMessageRequest();
|
2006-07-18 07:14:33 +02:00
|
|
|
for (String node : nodes) {
|
|
|
|
OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
|
2005-07-26 06:57:36 +02:00
|
|
|
item.setAction("view");
|
|
|
|
request.addItem(item);
|
|
|
|
}
|
|
|
|
// Filter offline messages that were requested by this request
|
2014-06-10 18:54:53 +02:00
|
|
|
PacketFilter messageFilter = new AndFilter(PACKET_FILTER, new PacketFilter() {
|
2005-07-26 06:57:36 +02:00
|
|
|
public boolean accept(Packet packet) {
|
|
|
|
OfflineMessageInfo info = (OfflineMessageInfo) packet.getExtension("offline",
|
|
|
|
namespace);
|
|
|
|
return nodes.contains(info.getNode());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
PacketCollector messageCollector = connection.createPacketCollector(messageFilter);
|
2014-08-04 12:19:58 +02:00
|
|
|
try {
|
|
|
|
connection.createPacketCollectorAndSend(request).nextResultOrThrow();
|
|
|
|
// Collect the received offline messages
|
2014-08-15 10:49:05 +02:00
|
|
|
Message message = messageCollector.nextResult();
|
2014-08-04 12:19:58 +02:00
|
|
|
while (message != null) {
|
|
|
|
messages.add(message);
|
2014-08-15 10:49:05 +02:00
|
|
|
message = messageCollector.nextResult();
|
2014-08-04 12:19:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
finally {
|
|
|
|
// Stop queuing offline messages
|
|
|
|
messageCollector.cancel();
|
2005-07-26 06:57:36 +02:00
|
|
|
}
|
2014-04-09 08:26:28 +02:00
|
|
|
return messages;
|
2005-07-26 06:57:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-08-04 12:19:58 +02:00
|
|
|
* Returns a List of Messages with all the offline <tt>Messages</tt> of the user. The returned offline
|
2005-07-26 06:57:36 +02:00
|
|
|
* messages will not be deleted from the server. Use {@link #deleteMessages(java.util.List)}
|
|
|
|
* to delete the messages.
|
|
|
|
*
|
2014-04-09 08:26:28 +02:00
|
|
|
* @return a List with all the offline <tt>Messages</tt> of the user.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws XMPPErrorException If the user is not allowed to make this request or the server does
|
2005-07-26 06:57:36 +02:00
|
|
|
* not support offline message retrieval.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws NoResponseException if there was no response from the server.
|
2014-03-19 14:22:20 +01:00
|
|
|
* @throws NotConnectedException
|
2005-07-26 06:57:36 +02:00
|
|
|
*/
|
2014-04-09 08:26:28 +02:00
|
|
|
public List<Message> getMessages() throws NoResponseException, XMPPErrorException, NotConnectedException {
|
2006-07-18 07:14:33 +02:00
|
|
|
List<Message> messages = new ArrayList<Message>();
|
2005-07-26 06:57:36 +02:00
|
|
|
OfflineMessageRequest request = new OfflineMessageRequest();
|
|
|
|
request.setFetch(true);
|
|
|
|
|
2014-06-10 18:54:53 +02:00
|
|
|
PacketCollector messageCollector = connection.createPacketCollector(PACKET_FILTER);
|
2014-08-07 16:51:03 +02:00
|
|
|
PacketCollector resultCollector = connection.createPacketCollectorAndSend(request);
|
2014-08-04 12:19:58 +02:00
|
|
|
|
2014-08-07 16:51:03 +02:00
|
|
|
try {
|
2014-08-04 12:19:58 +02:00
|
|
|
// Collect the received offline messages
|
2014-08-15 10:49:05 +02:00
|
|
|
Message message = messageCollector.nextResult();
|
2014-08-04 12:19:58 +02:00
|
|
|
while (message != null) {
|
|
|
|
messages.add(message);
|
2014-12-07 23:41:17 +01:00
|
|
|
// It is important that we query the resultCollector before the messageCollector
|
|
|
|
Packet result = resultCollector.pollResultOrThrow();
|
|
|
|
message = messageCollector.pollResult();
|
|
|
|
if (message == null && result != null) {
|
|
|
|
// No new messages, but we have a non-error IQ response, we are done
|
|
|
|
return messages;
|
|
|
|
} else if (message != null) {
|
|
|
|
// We have received a message without waiting, great, continue to add this message and proceed with
|
|
|
|
// the loop
|
|
|
|
continue;
|
|
|
|
}
|
2014-08-15 10:49:05 +02:00
|
|
|
message = messageCollector.nextResult();
|
2014-08-04 12:19:58 +02:00
|
|
|
}
|
2014-08-07 16:51:03 +02:00
|
|
|
resultCollector.nextResultOrThrow();
|
2014-08-04 12:19:58 +02:00
|
|
|
}
|
|
|
|
finally {
|
|
|
|
messageCollector.cancel();
|
2014-08-07 16:51:03 +02:00
|
|
|
resultCollector.cancel();
|
2005-07-26 06:57:36 +02:00
|
|
|
}
|
2014-04-09 08:26:28 +02:00
|
|
|
return messages;
|
2005-07-26 06:57:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws XMPPErrorException If the user is not allowed to make this request or the server does
|
2005-07-26 06:57:36 +02:00
|
|
|
* not support offline message retrieval.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws NoResponseException if there was no response from the server.
|
2014-03-19 14:22:20 +01:00
|
|
|
* @throws NotConnectedException
|
2005-07-26 06:57:36 +02:00
|
|
|
*/
|
2014-03-19 14:22:20 +01:00
|
|
|
public void deleteMessages(List<String> nodes) throws NoResponseException, XMPPErrorException, NotConnectedException {
|
2005-07-26 06:57:36 +02:00
|
|
|
OfflineMessageRequest request = new OfflineMessageRequest();
|
2006-07-18 07:14:33 +02:00
|
|
|
for (String node : nodes) {
|
|
|
|
OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
|
2005-07-26 06:57:36 +02:00
|
|
|
item.setAction("remove");
|
|
|
|
request.addItem(item);
|
|
|
|
}
|
2014-02-18 15:05:19 +01:00
|
|
|
connection.createPacketCollectorAndSend(request).nextResultOrThrow();
|
2005-07-26 06:57:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deletes all offline messages of the user.
|
|
|
|
*
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws XMPPErrorException If the user is not allowed to make this request or the server does
|
2005-07-26 06:57:36 +02:00
|
|
|
* not support offline message retrieval.
|
2014-03-12 11:50:05 +01:00
|
|
|
* @throws NoResponseException if there was no response from the server.
|
2014-03-19 14:22:20 +01:00
|
|
|
* @throws NotConnectedException
|
2005-07-26 06:57:36 +02:00
|
|
|
*/
|
2014-03-19 14:22:20 +01:00
|
|
|
public void deleteMessages() throws NoResponseException, XMPPErrorException, NotConnectedException {
|
2005-07-26 06:57:36 +02:00
|
|
|
OfflineMessageRequest request = new OfflineMessageRequest();
|
|
|
|
request.setPurge(true);
|
2014-02-18 15:05:19 +01:00
|
|
|
connection.createPacketCollectorAndSend(request).nextResultOrThrow();
|
2005-07-26 06:57:36 +02:00
|
|
|
}
|
|
|
|
}
|