package com.reucon.openfire.plugin.archive.impl;
import com.reucon.openfire.plugin.archive.ArchiveFactory;
import com.reucon.openfire.plugin.archive.ArchiveManager;
import com.reucon.openfire.plugin.archive.IndexManager;
import com.reucon.openfire.plugin.archive.PersistenceManager;
import com.reucon.openfire.plugin.archive.model.ArchivedMessage;
import com.reucon.openfire.plugin.archive.model.Conversation;
import com.reucon.openfire.plugin.archive.model.Participant;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.session.Session;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import java.util.ArrayList;
import java.util.Collection;
/**
* Default implementation of ArchiveManager.
*/
public class ArchiveManagerImpl implements ArchiveManager
{
private final PersistenceManager persistenceManager;
private final IndexManager indexManager;
private final Collection<Conversation> activeConversations;
private int conversationTimeout;
public ArchiveManagerImpl(PersistenceManager persistenceManager, IndexManager indexManager,
int conversationTimeout)
{
this.persistenceManager = persistenceManager;
this.indexManager = indexManager;
this.conversationTimeout = conversationTimeout;
activeConversations = persistenceManager.getActiveConversations(conversationTimeout);
}
public void archiveMessage(Session session, Message message, boolean incoming)
{
final XMPPServer server = XMPPServer.getInstance();
final ArchivedMessage.Direction direction;
final ArchivedMessage archivedMessage;
final Conversation conversation;
final JID ownerJid;
final JID withJid;
// TODO support groupchat
if (message.getType() != Message.Type.chat && message.getType() != Message.Type.normal)
{
return;
}
if (server.isLocal(message.getFrom()) && incoming)
{
ownerJid = message.getFrom();
withJid = message.getTo();
// sent by the owner => to
direction = ArchivedMessage.Direction.to;
}
else if (server.isLocal(message.getTo()) && ! incoming)
{
ownerJid = message.getTo();
withJid = message.getFrom();
// received by the owner => from
direction = ArchivedMessage.Direction.from;
}
else
{
return;
}
archivedMessage = ArchiveFactory.createArchivedMessage(session, message, direction, withJid);
if (archivedMessage.isEmpty())
{
return;
}
conversation = determineConversation(ownerJid, withJid, message.getSubject(), message.getThread(), archivedMessage);
archivedMessage.setConversation(conversation);
persistenceManager.createMessage(archivedMessage);
if (indexManager != null)
{
indexManager.indexObject(archivedMessage);
}
}
public void setConversationTimeout(int conversationTimeout)
{
this.conversationTimeout = conversationTimeout;
}
private Conversation determineConversation(JID ownerJid, JID withJid, String subject, String thread, ArchivedMessage archivedMessage)
{
Conversation conversation = null;
Collection<Conversation> staleConversations;
staleConversations = new ArrayList<Conversation>();
synchronized (activeConversations)
{
for (Conversation c : activeConversations)
{
if (c.isStale(conversationTimeout))
{
staleConversations.add(c);
continue;
}
if (matches(ownerJid, withJid, thread, c))
{
conversation = c;
break;
}
}
activeConversations.removeAll(staleConversations);
if (conversation == null)
{
final Participant p1;
final Participant p2;
conversation = new Conversation(archivedMessage.getTime(),
ownerJid.toBareJID(), ownerJid.getResource(), withJid.toBareJID(), withJid.getResource(),
subject, thread);
persistenceManager.createConversation(conversation);
p1 = new Participant(archivedMessage.getTime(), ownerJid.toBareJID());
conversation.addParticipant(p1);
persistenceManager.createParticipant(p1, conversation.getId());
p2 = new Participant(archivedMessage.getTime(), withJid.toBareJID());
conversation.addParticipant(p2);
persistenceManager.createParticipant(p2, conversation.getId());
activeConversations.add(conversation);
}
else
{
conversation.setEnd(archivedMessage.getTime());
persistenceManager.updateConversationEnd(conversation);
}
}
return conversation;
}
private boolean matches(JID ownerJid, JID withJid, String thread, Conversation c)
{
if (! ownerJid.toBareJID().equals(c.getOwnerJid()))
{
return false;
}
if (! withJid.toBareJID().equals(c.getWithJid()))
{
return false;
}
/*
if (ownerJid.getResource() != null)
{
if (! ownerJid.getResource().equals(c.getOwnerResource()))
{
return false;
}
}
else
{
if (c.getOwnerResource() != null)
{
return false;
}
}
if (withJid.getResource() != null)
{
if (! withJid.getResource().equals(c.getWithResource()))
{
return false;
}
}
else
{
if (c.getWithResource() != null)
{
return false;
}
}
*/
if (thread != null)
{
if (! thread.equals(c.getThread()))
{
return false;
}
}
else
{
if (c.getThread() != null)
{
return false;
}
}
return true;
}
}