Commit d5f35db6 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gaston

Initial version. JM-8


git-svn-id: http://svn.igniterealtime.org/svn/repos/messenger/trunk@1694 b35dd754-fafc-0310-a699-88a17e54d16e
parent c3110209
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger;
import org.xmpp.packet.Message;
import org.dom4j.Element;
import java.util.Date;
/**
* Subclass of Message that keeps the date when the offline message was stored in the database.
* The creation date and the user may be used as a unique identifier of the offline message.
*
* @author Gaston Dombiak
*/
public class OfflineMessage extends Message {
private Date creationDate;
public OfflineMessage(Date creationDate, Element element) {
super(element);
this.creationDate = creationDate;
}
/**
* Returns the data when the offline message was stored in the database.
*
* @return
*/
public Date getCreationDate() {
return creationDate;
}
}
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.messenger.handler;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jivesoftware.messenger.*;
import org.jivesoftware.messenger.auth.UnauthorizedException;
import org.jivesoftware.messenger.disco.*;
import org.jivesoftware.messenger.forms.DataForm;
import org.jivesoftware.messenger.forms.FormField;
import org.jivesoftware.messenger.forms.spi.XDataFormImpl;
import org.jivesoftware.messenger.forms.spi.XFormFieldImpl;
import org.jivesoftware.util.Log;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.*;
/**
* Implements JEP-0013: Flexible Offline Message Retrieval. Allows users to request number of
* messages, request message headers, retrieve specific messages, remove specific messages,
* retrieve all messages and remove all messages.
*
* @author Gaston Dombiak
*/
public class IQOfflineMessagesHandler extends IQHandler implements ServerFeaturesProvider,
DiscoInfoProvider, DiscoItemsProvider {
private static final String NAMESPACE = "http://jabber.org/protocol/offline";
private SimpleDateFormat dateFormat;
private IQHandlerInfo info;
private IQDiscoInfoHandler infoHandler;
private IQDiscoItemsHandler itemsHandler;
private SessionManager sessionManager;
private OfflineMessageStore messageStore;
public IQOfflineMessagesHandler() {
super("Flexible Offline Message Retrieval Handler");
info = new IQHandlerInfo("offline", NAMESPACE);
dateFormat = new SimpleDateFormat("yyyy-MM-DD'T'hh:mm:ss.SSS'Z'");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
public IQ handleIQ(IQ packet) throws UnauthorizedException {
IQ reply = IQ.createResultIQ(packet);
Element offlineRequest = packet.getChildElement();
if (offlineRequest.element("purge") != null) {
// User requested to delete all offline messages
messageStore.deleteMessages(packet.getFrom().getNode());
}
else if (offlineRequest.element("fetch") != null) {
// Mark that offline messages shouldn't be sent when the user becomes available
stopOfflineFlooding(packet.getFrom());
ClientSession session = sessionManager.getSession(packet.getFrom());
// User requested to receive all offline messages
for (OfflineMessage offlineMessage : messageStore.getMessages(
packet.getFrom().getNode(), false)) {
sendOfflineMessage(offlineMessage, session);
}
}
else {
for (Iterator it = offlineRequest.elementIterator("item"); it.hasNext();) {
Element item = (Element) it.next();
Date creationDate = null;
synchronized (dateFormat) {
try {
creationDate = dateFormat.parse(item.attributeValue("node"));
}
catch (ParseException e) {
Log.error("Error parsing date", e);
}
}
if ("view".equals(item.attributeValue("action"))) {
// User requested to receive specific message
OfflineMessage offlineMsg = messageStore.getMessage(packet.getFrom().getNode(),
creationDate);
if (offlineMsg != null) {
ClientSession session = sessionManager.getSession(packet.getFrom());
sendOfflineMessage(offlineMsg, session);
}
}
else if ("remove".equals(item.attributeValue("action"))) {
// User requested to delete specific message
messageStore.deleteMessage(packet.getFrom().getNode(), creationDate);
}
}
}
return reply;
}
private void sendOfflineMessage(OfflineMessage offlineMessage, ClientSession session) {
Element offlineInfo = offlineMessage.addChildElement("offline", NAMESPACE);
synchronized (dateFormat) {
offlineInfo.addElement("item").addAttribute("node",
dateFormat.format(offlineMessage.getCreationDate()));
}
session.process(offlineMessage);
}
public IQHandlerInfo getInfo() {
return info;
}
public Iterator getFeatures() {
ArrayList features = new ArrayList();
features.add(NAMESPACE);
return features.iterator();
}
public Iterator<Element> getIdentities(String name, String node, JID senderJID) {
ArrayList<Element> identities = new ArrayList<Element>();
Element identity = DocumentHelper.createElement("identity");
identity.addAttribute("category", "automation");
identity.addAttribute("type", "message-list");
identities.add(identity);
return identities.iterator();
}
public Iterator<String> getFeatures(String name, String node, JID senderJID) {
return Arrays.asList(NAMESPACE).iterator();
}
public XDataFormImpl getExtendedInfo(String name, String node, JID senderJID) {
// Mark that offline messages shouldn't be sent when the user becomes available
stopOfflineFlooding(senderJID);
XDataFormImpl dataForm = new XDataFormImpl(DataForm.TYPE_RESULT);
XFormFieldImpl field = new XFormFieldImpl("FORM_TYPE");
field.setType(FormField.TYPE_HIDDEN);
field.addValue(NAMESPACE);
dataForm.addField(field);
field = new XFormFieldImpl("number_of_messages");
field.addValue(String.valueOf(messageStore.getMessages(senderJID.getNode(), false).size()));
dataForm.addField(field);
return dataForm;
}
public boolean hasInfo(String name, String node, JID senderJID) {
return NAMESPACE.equals(node) && senderJID.getNode() != null;
}
public Iterator<Element> getItems(String name, String node, JID senderJID) {
// Mark that offline messages shouldn't be sent when the user becomes available
stopOfflineFlooding(senderJID);
List<Element> answer = new ArrayList<Element>();
Element item;
for (OfflineMessage offlineMessage : messageStore.getMessages(senderJID.getNode(), false)) {
item = DocumentHelper.createElement("item");
item.addAttribute("jid", senderJID.toBareJID());
item.addAttribute("name", offlineMessage.getFrom().toString());
synchronized (dateFormat) {
item.addAttribute("node", dateFormat.format(offlineMessage.getCreationDate()));
}
answer.add(item);
}
return answer.iterator();
}
public void initialize(XMPPServer server) {
super.initialize(server);
infoHandler = server.getIQDiscoInfoHandler();
itemsHandler = server.getIQDiscoItemsHandler();
messageStore = server.getOfflineMessageStore();
sessionManager = server.getSessionManager();
}
public void start() throws IllegalStateException {
super.start();
infoHandler.setServerNodeInfoProvider(NAMESPACE, this);
itemsHandler.setServerNodeInfoProvider(NAMESPACE, this);
}
public void stop() {
super.stop();
infoHandler.removeServerNodeInfoProvider(NAMESPACE);
itemsHandler.removeServerNodeInfoProvider(NAMESPACE);
}
private void stopOfflineFlooding(JID senderJID) {
ClientSession session = sessionManager.getSession(senderJID);
if (session != null) {
session.setOfflineFloodStopped(true);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment