📄 conversation.java
字号:
/**
* $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 + -