⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conversation.java

📁 openfire 服务器源码下载
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/**
 * $Revision: 3034 $
 * $Date: 2005-11-04 21:02:33 -0300 (Fri, 04 Nov 2005) $
 *
 * Copyright (C) 2008 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, or a commercial license
 * agreement with Jive.
 */

package org.jivesoftware.openfire.archive;

import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.database.JiveID;
import org.jivesoftware.database.SequenceManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.muc.MUCRole;
import org.jivesoftware.openfire.muc.MUCRoom;
import org.jivesoftware.openfire.user.UserNameManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.NotFoundException;
import org.jivesoftware.util.cache.ExternalizableUtil;
import org.xmpp.packet.JID;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import org.jivesoftware.openfire.plugin.MonitoringPlugin;

/**
 * Represents an IM conversation between two people. A conversation encompasses a
 * series of messages sent back and forth. It may cover a single topic or several.
 * The start of a conversation occurs when the first message between two users is
 * sent. It ends when either:
 * <ul>
 * <li>No messages are sent between the users for a certain period of time (default of 10
 * minutes). The default value can be overridden by setting the Openfire property
 * <tt>conversation.idleTime</tt>.</li>
 * <li>The total conversation time reaches a maximum value (default of 60 minutes).
 * The default value can be overridden by setting the Openfire property
 * <tt>conversation.maxTime</tt>. When the max time has been reached and additional
 * messages are sent between the users, a new conversation will simply be
 * started.</li>
 * </ul>
 * <p/>
 * Each conversation has a start time, date of the last message, and count of the
 * messages in the conversation. Conversations are specially marked if one of the
 * participants is on an external server. If archiving is enabled, the actual messages in
 * the conversation can be retrieved.
 *
 * @author Matt Tucker
 */
@JiveID(50)
public class Conversation implements Externalizable {

    private static final String INSERT_CONVERSATION =
            "INSERT INTO ofConversation(conversationID, room, isExternal, startDate, " +
                    "lastActivity, messageCount) VALUES (?,?,?,?,?,0)";
    private static final String INSERT_PARTICIPANT =
            "INSERT INTO ofConParticipant(conversationID, joinedDate, bareJID, jidResource, nickname) " +
                    "VALUES (?,?,?,?,?)";
    private static final String LOAD_CONVERSATION =
            "SELECT room, isExternal, startDate, lastActivity, messageCount " +
                    "FROM ofConversation WHERE conversationID=?";
    private static final String LOAD_PARTICIPANTS =
            "SELECT bareJID, jidResource, nickname, joinedDate, leftDate FROM ofConParticipant " +
                    "WHERE conversationID=? ORDER BY joinedDate";
    private static final String LOAD_MESSAGES =
            "SELECT fromJID, toJID, sentDate, body FROM ofMessageArchive WHERE conversationID=? " +
                    "ORDER BY sentDate";

    private transient ConversationManager conversationManager;

    private long conversationID = -1;
    private Map<String, UserParticipations> participants;
    private boolean external;
    private Date startDate;
    private Date lastActivity;
    private int messageCount;
    /**
     * Room where the group conversion is taking place. For one-to-one chats
     * there is no room so this variable will be null.
     */
    private JID room;

    /**
     * Do not use this constructor. It only exists for serialization purposes.
     */
    public Conversation() {
    }

    /**
     * Constructs a new one-to-one conversation.
     *
     * @param conversationManager the ConversationManager.
     * @param users               the two participants in the conversation.
     * @param external            true if the conversation includes a user on another server.
     * @param startDate           the starting date of the conversation.
     */
    public Conversation(ConversationManager conversationManager, Collection<JID> users,
                        boolean external, Date startDate) {
        if (users.size() != 2) {
            throw new IllegalArgumentException("Illegal number of participants: " + users.size());
        }
        this.conversationManager = conversationManager;
        this.participants = new HashMap<String, UserParticipations>(2);
        // Ensure that we're use the full JID of each participant.
        for (JID user : users) {
            UserParticipations userParticipations = new UserParticipations(false);
            userParticipations.addParticipation(new ConversationParticipation(startDate));
            participants.put(user.toString(), userParticipations);
        }
        this.external = external;
        this.startDate = startDate;
        this.lastActivity = startDate;
        // If archiving is enabled, insert the conversation into the database.
        if (conversationManager.isMetadataArchivingEnabled()) {
            try {
                insertIntoDb();
            }
            catch (Exception e) {
                Log.error(e);
            }
        }
    }

    /**
     * Constructs a new group chat conversation that is taking place in a room.
     *
     * @param conversationManager the ConversationManager.
     * @param room                the JID of the room where the conversation is taking place.
     * @param external            true if the conversation includes a user on another server.
     * @param startDate           the starting date of the conversation.
     */
    public Conversation(ConversationManager conversationManager, JID room, boolean external, Date startDate) {
        this.conversationManager = conversationManager;
        this.participants = new ConcurrentHashMap<String, UserParticipations>();
        // Add list of existing room occupants as participants of this conversation
        MUCRoom mucRoom = XMPPServer.getInstance().getMultiUserChatServer().getChatRoom(room.getNode());
        if (mucRoom != null) {
            for (MUCRole role : mucRoom.getOccupants()) {
                UserParticipations userParticipations = new UserParticipations(true);
                userParticipations.addParticipation(new ConversationParticipation(startDate, role.getNickname()));
                participants.put(role.getUserAddress().toString(), userParticipations);
            }
        }
        this.room = room;
        this.external = external;
        this.startDate = startDate;
        this.lastActivity = startDate;
        // If archiving is enabled, insert the conversation into the database.
        if (conversationManager.isMetadataArchivingEnabled()) {
            try {
                insertIntoDb();
            }
            catch (Exception e) {
                Log.error(e);
            }
        }
    }

    /**
     * Loads a conversation from the database.
     *
     * @param conversationManager the conversation manager.
     * @param conversationID      the ID of the conversation.
     * @throws NotFoundException if the conversation can't be loaded.
     */
    public Conversation(ConversationManager conversationManager, long conversationID)
            throws NotFoundException {
        this.conversationManager = conversationManager;
        this.conversationID = conversationID;
        loadFromDb();
    }

    /**
     * Returns the unique ID of the conversation. A unique ID is only meaningful when
     * conversation archiving is enabled. Therefore, this method returns <tt>-1</tt> if
     * archiving is not turned on.
     *
     * @return the unique ID of the conversation, or <tt>-1</tt> if conversation
     *         archiving is not enabled.
     */
    public long getConversationID() {
        return conversationID;
    }


    /**
     * Returns the JID of the room where the group conversation took place. If the conversation
     * was a one-to-one chat then a <tt>null</tt> value is returned.
     *
     * @return the JID of room or null if this was a one-to-one chat.
     */
    public JID getRoom() {
        return room;
    }

    /**
     * Returns the conversation participants.
     *
     * @return the two conversation participants. Returned JIDs are full JIDs.
     */
    public Collection<JID> getParticipants() {
        List<JID> users = new ArrayList<JID>();
        for (String key : participants.keySet()) {
            users.add(new JID(key));
        }
        return users;
    }

    /**
     * Returns the participations of the specified user (full JID) in this conversation. Each
     * participation will hold the time when the user joined and left the conversation and the
     * nickname if the room happened in a room.
     *
     * @param user the full JID of the user.
     * @return the participations of the specified user (full JID) in this conversation.
     */
    public Collection<ConversationParticipation> getParticipations(JID user) {
        UserParticipations userParticipations = participants.get(user.toString());
        if (userParticipations == null) {
            return Collections.emptyList();
        }
        return userParticipations.getParticipations();
    }

    /**
     * Returns true if one of the conversation participants is on an external server.
     *
     * @return true if one of the conversation participants is on an external server.
     */
    public boolean isExternal() {
        return external;
    }

    /**
     * Returns the starting timestamp of the conversation.
     *
     * @return the start date.
     */
    public Date getStartDate() {
        return startDate;
    }

    /**
     * Returns the timestamp the last message was receieved.
     *
     * @return the last activity.
     */
    public Date getLastActivity() {
        return lastActivity;
    }

    /**
     * Returns the number of messages that make up the conversation.
     *
     * @return the message count.
     */
    public int getMessageCount() {
        return messageCount;
    }

    /**
     * Returns the archived messages in the conversation. If message archiving is not
     * enabled, this method will always return an empty collection. This method will only
     * return messages that have already been batch-archived to the database; in other
     * words, it does not provide a real-time view of new messages.
     *
     * @return the archived messages in the conversation.
     */
    public List<ArchivedMessage> getMessages() {
        if (room == null && !conversationManager.isMessageArchivingEnabled()) {
            return Collections.emptyList();
        }
        else if (room != null && !conversationManager.isRoomArchivingEnabled()) {
            return Collections.emptyList();
        }

        List<ArchivedMessage> messages = new ArrayList<ArchivedMessage>();
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = DbConnectionManager.getConnection();
            pstmt = con.prepareStatement(LOAD_MESSAGES);
            pstmt.setLong(1, getConversationID());
            rs = pstmt.executeQuery();
            while (rs.next()) {
                JID fromJID = new JID(rs.getString(1));
                JID toJID = new JID(rs.getString(2));
                Date date = new Date(rs.getLong(3));
                String body = DbConnectionManager.getLargeTextField(rs, 4);
                messages.add(new ArchivedMessage(conversationID, fromJID, toJID, date, body, false));
            }
        }
        catch (SQLException sqle) {
            Log.error(sqle);
        }
        finally {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -