openfire在即时通讯中,双方都在线是添加好友是没有问题的,但是在线一方添加离线一方好友就会导致好友请求丢包,而添加好友openfire使用的是presence包,openfire自带的离线消息使用的message,我尝试了一下不行,因此自己建立了一个数据库,保存离线好友请求并在好友上线是推送过去。本插件借鉴了另一篇文章关于保存消息记录的插件为基础进行修改聊天记录插件
1.数据库:我使用的是mysql数据库;
CREATE TABLE `offriendslogs` (
`sender` varchar(255) DEFAULT NULL,
`state` int(255) DEFAULT NULL,
`length` int(11) DEFAULT NULL,
`detail` varchar(2555) DEFAULT NULL,
`createDate` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`receiver` varchar(255) DEFAULT NULL,
`sessionJID` varchar(255) DEFAULT NULL,
`messageId` bigint(20) NOT NULL,
PRIMARY KEY (`messageId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.创建离线消息实体类
package com.syj.newsfriend;
import java.sql.Timestamp;
import org.jivesoftware.util.JiveConstants;
/**
* <b>function:</b> 聊天记录对象实体
*
* @author hoojo
* @createDate 2012-9-19 下午08:28:03
* @file ChatLogs.java
* @package com.hoo.openfire.chat.logs.entity
* @project OpenfirePlugin
* @blog http://blog.csdn.net/IBM_hoojo
* @email hoojo_@126.com
* @version 1.0
*/
public class ChatLogs {
private long messageId;
private String sessionJID;
private String sender;
private String receiver;
private Timestamp createDate;
private String detail;
private int length;
private int state; // 1 表示删除
public interface LogState {
int show = 0;
int remove = 1;
}
/**
* <b>function:</b> 自增id序列管理器,类型变量
*
* @author hoojo
* @createDate 2012-9-20 下午02:38:52
* @file ChatLogs.java
* @package com.hoo.openfire.chat.logs.entity
* @project OpenfirePlugin
* @blog http://blog.csdn.net/IBM_hoojo
* @email hoojo_@126.com
* @version 1.0
*/
public class ChatLogsConstants extends JiveConstants {
// 日志表id自增对应类型
public static final int CHAT_LOGS = 52;
// 用户在线统计id自增对应类型
public static final int USER_ONLINE_STATE = 53;
}
public ChatLogs() {
}
public ChatLogs(String sessionJID, Timestamp createDate, String detail, int length) {
super();
this.sessionJID = sessionJID;
this.createDate = createDate;
this.detail = detail;
this.length = length;
}
public ChatLogs(long messageId, String sessionJID, Timestamp createDate, String detail, int length,
int state) {
super();
this.messageId = messageId;
this.sessionJID = sessionJID;
this.createDate = createDate;
this.detail = detail;
this.length = length;
this.state = state;
}
public long getMessageId() {
return messageId;
}
public void setMessageId(long messageId) {
this.messageId = messageId;
}
public String getSessionJID() {
return sessionJID;
}
public void setSessionJID(String sessionJID) {
this.sessionJID = sessionJID;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getReceiver() {
return receiver;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public Timestamp getCreateDate() {
return createDate;
}
public void setCreateDate(Timestamp createDate) {
this.createDate = createDate;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
}
由于自己也还在学习阶段,很多东西(类名和属性)套用别人的都没改,将就看一下了……
3.数据库管理类
package com.syj.newsfriend;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.jivesoftware.database.DbConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <b>function:</b> 聊天记录db操作类
* @author hoojo
* @createDate 2012-9-19 下午04:15:43
* @file DbChatLogsManager.java
* @package com.iflashbuy.openfire.chat.logs
* @project OpenfirePlugin
* @blog http://blog.csdn.net/IBM_hoojo
* @email hoojo_@126.com
* @version 1.0
*/
public class DbChatLogsManager {
private static final Logger Log = LoggerFactory.getLogger(DbChatLogsManager.class);
private static final DbChatLogsManager CHAT_LOGS_MANAGER = new DbChatLogsManager();
private DbChatLogsManager() {
}
public static DbChatLogsManager getInstance() {
return CHAT_LOGS_MANAGER;
}
private static final String LOGS_COUNT = "SELECT count(1) FROM offriendsLogs";
private static final String LOGS_LAST_MESSAGE_ID = "SELECT max(messageId) FROM offriendsLogs";
private static final String LOGS_FIND_BY_ID = "SELECT messageId, sessionJID, sender, receiver, createDate, length, content FROM offriendsLogs where messageId = ?";
private static final String LOGS_REMOVE = "UPDATE offriendsLogs set state = 1 where messageId = ?";
private static final String FRIENDSLOGS_DELETE="DELETE FROM offriendsLogs WHERE messageId = ?";
private static final String FRIENDSLOGS_QUERY="SELECT messageId, sessionJID, sender, receiver, createDate, length, detail FROM offriendsLogs where receiver = ";
private static final String LOGS_INSERT = "INSERT INTO offriendsLogs(messageId, sessionJID, sender, receiver, createDate, length,detail, state) VALUES(?,?,?,?,?,?,?,?)";
private static final String LOGS_QUERY = "SELECT messageId, sessionJID, sender, receiver, createDate, length FROM offriendsLogs where state = 0";
private static final String LOGS_SEARCH = "SELECT * FROM offriendsLogs where state = 0";
private static final String LOGS_LAST_CONTACT = "SELECT distinct receiver FROM offriendsLogs where state = 0 and sender = ?";
private static final String LOGS_ALL_CONTACT = "SELECT distinct sessionJID FROM offriendsLogs where state = 0";
/**
* <b>function:</b> 获取最后一个id
* @author hoojo
* @createDate 2012-9-19 下午08:13:33
* @return 最后一个记录id
*/
public int getLastId() {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
int count = -1;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOGS_LAST_MESSAGE_ID);
rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
} else {
count = 0;
}
} catch (SQLException sqle) {
Log.error(sqle.getMessage(), sqle);
return 0;
} finally {
DbConnectionManager.closeConnection(pstmt, con);
}
return count;
}
/**
* <b>function:</b> 获取总数量
* @author hoojo
* @createDate 2012-9-19 下午08:14:59
* @return 总数量
*/
public int getCount() {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
int count = -1;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOGS_COUNT);
rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
} else {
count = 0;
}
} catch (SQLException sqle) {
Log.error(sqle.getMessage(), sqle);
return 0;
} finally {
DbConnectionManager.closeConnection(pstmt, con);
}
return count;
}
/**
* <b>function:</b> 删除聊天记录信息
* @author hoojo
* @createDate 2012-9-19 下午08:25:48
* @param id 聊天信息id
* @return
*/
public boolean remove(Long id) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(FRIENDSLOGS_DELETE);
pstmt.setLong(1, id);
return pstmt.execute();
} catch (SQLException sqle) {
Log.error("chatLogs remove exception: {}", sqle);
return false;
} finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* <b>function:</b> 添加聊天记录信息
* @author hoojo
* @createDate 2012-9-19 下午08:37:52
* @param logs ChatLogs 聊天记录对象
* @return 是否添加成功
*/
public boolean add(ChatLogs logs) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOGS_INSERT);
int i = 1;
pstmt.setLong(i++, logs.getMessageId());
pstmt.setString(i++, logs.getSessionJID());
pstmt.setString(i++, logs.getSender());
pstmt.setString(i++, logs.getReceiver());
pstmt.setTimestamp(i++, logs.getCreateDate());
pstmt.setInt(i++, logs.getLength());
pstmt.setString(i++, logs.getDetail());
pstmt.setInt(i++, 0);
return pstmt.execute();
} catch (SQLException sqle) {
Log.error("chatLogs add exception: {}", sqle);
return false;
} finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* <b>function:</b> 通过id查询聊天记录信息
* @author hoojo
* @createDate 2012-9-19 下午09:32:19
* @param id 消息id
* @return ChatLogs
*/
public ChatLogs find(int id) {
Connection con = null;
PreparedStatement pstmt = null;
ChatLogs logs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOGS_FIND_BY_ID);
pstmt.setInt(1, id);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
logs = new ChatLogs();
logs.setMessageId(rs.getInt("messageId"));
logs.setCreateDate(rs.getTimestamp("createDate"));
logs.setLength(rs.getInt("length"));
logs.setSessionJID(rs.getString("sessionJID"));
logs.setSender(rs.getString("sender"));
logs.setReceiver(rs.getString("receiver"));
}
return logs;
} catch (SQLException sqle) {
Log.error("chatLogs find exception: {}", sqle);
return logs;
} finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* <b>function:</b> 多条件搜索查询,返回List<ChatLogs>集合
* @author hoojo
* @createDate 2012-9-19 下午09:34:45
* @param entity ChatLogs
* @return 返回List<ChatLogs>集合
*/
public List<ChatLogs> query(String reciver) {
Connection con = null;
Statement pstmt = null;
ChatLogs logs = null;
List<ChatLogs> result = new ArrayList<ChatLogs>();
try {
con = DbConnectionManager.getConnection();
pstmt = con.createStatement();
String sql = FRIENDSLOGS_QUERY;
sql+="'"+reciver+"'";
sql += " order by createDate asc";
System.out.println(sql);
ResultSet rs = pstmt.executeQuery(sql);
while (rs.next()) {
logs = new ChatLogs();
logs.setMessageId(rs.getInt("messageId"));
logs.setCreateDate(rs.getTimestamp("createDate"));
logs.setLength(rs.getInt("length"));
logs.setSessionJID(rs.getString("sessionJID"));
logs.setSender(rs.getString("sender"));
logs.setReceiver(rs.getString("receiver"));
logs.setDetail(rs.getString("detail"));
result.add(logs);
}
return result;
} catch (SQLException sqle) {
Log.error("chatLogs search exception: {}", sqle);
return result;
} finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* <b>function:</b> 多条件搜索查询,返回List<Map>集合
* @author hoojo
* @createDate 2012-9-19 下午09:33:28
* @param entity ChatLogs
* @return List<HashMap<String, Object>>
*/
public List<HashMap<String, Object>> search(ChatLogs entity) {
Connection con = null;
Statement pstmt = null;
List<HashMap<String, Object>> result = new ArrayList<HashMap<String, Object>>();
try {
con = DbConnectionManager.getConnection();
pstmt = con.createStatement();
String sql = LOGS_SEARCH;
if (entity != null) {
if (!StringUtils.isEmpty(entity.getSender()) && !StringUtils.isEmpty(entity.getReceiver())) {
sql += " and (sender = '" + entity.getSender() + "' and receiver = '" + entity.getReceiver() + "')";
sql += " or (receiver = '" + entity.getSender() + "' and sender = '" + entity.getReceiver() + "')";
} else {
if (!StringUtils.isEmpty(entity.getSender())) {
sql += " and sender = '" + entity.getSender() + "'";
}
if (!StringUtils.isEmpty(entity.getReceiver())) {
sql += " and receiver = '" + entity.getReceiver() + "'";
}
}
if (entity.getCreateDate() != null) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String crateatDate = df.format(new Date(entity.getCreateDate().getTime()));
sql += " and to_char(createDate, 'yyyy-mm-dd') = '" + crateatDate + "'";
}
}
sql += " order by createDate asc";
ResultSet rs = pstmt.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
/** 获取结果集的列数*/
int columnCount = rsmd.getColumnCount();
while (rs.next()) {
HashMap<String, Object> map = new HashMap<String, Object>();
/** 把每一行以(key, value)存入HashMap, 列名做为key,列值做为value */
for (int i = 1; i <= columnCount; ++i) {
String columnVal = rs.getString(i);
if (columnVal == null) {
columnVal = "";
}
map.put(rsmd.getColumnName(i), columnVal);
}
/** 把装有一行数据的HashMap存入list */
result.add(map);
}
return result;
} catch (SQLException sqle) {
Log.error("chatLogs search exception: {}", sqle);
return result;
} finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* <b>function:</b> 最近联系人
* @author hoojo
* @createDate 2013-3-24 下午4:38:51
* @param entity 聊天记录实体
* @return 最近联系人集合
*/
public List<String> findLastContact(ChatLogs entity) {
Connection con = null;
PreparedStatement pstmt = null;
List<String> result = new ArrayList<String>();
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOGS_LAST_CONTACT);
pstmt.setString(1, entity.getSender());
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
result.add(rs.getString("receiver"));
}
return result;
} catch (SQLException sqle) {
Log.error("chatLogs find exception: {}", sqle);
return result;
} finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* <b>function:</b> 查找所有聊天用户
* @author hoojo
* @createDate 2013-3-24 下午4:37:40
* @return 所有聊天用户sessionJID集合
*/
public List<String> findAllContact() {
Connection con = null;
PreparedStatement pstmt = null;
List<String> result = new ArrayList<String>();
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOGS_ALL_CONTACT);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
result.add(rs.getString("sessionJID"));
}
return result;
} catch (SQLException sqle) {
Log.error("chatLogs find exception: {}", sqle);
return result;
} finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
}
4.插件操作类
package com.syj.newsfriend;
import java.io.File;
import java.io.StringReader;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.jivesoftware.database.SequenceManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.interceptor.InterceptorManager;
import org.jivesoftware.openfire.interceptor.PacketInterceptor;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.PresencePlugin;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
import com.syj.newsfriend.ChatLogs.ChatLogsConstants;
/**
* 用来处理用户不在线,添加好友的请求
*
* @author Administrator
*
*/
public class OfflineFriendsPlugins implements Plugin, PacketInterceptor {
private PresencePlugin plugin;
private InterceptorManager interceptorManager;
private static DbChatLogsManager logsManager;
public OfflineFriendsPlugins() {
super();
// TODO Auto-generated constructor stub
interceptorManager = InterceptorManager.getInstance();
logsManager=DbChatLogsManager.getInstance();
}
@Override
public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed)
throws PacketRejectedException {
// TODO Auto-generated method stub
SAXReader xmlReader = new SAXReader();
try {
if(packet instanceof Presence){
Presence presence2 = (Presence) packet.createCopy();
if(presence2.getType()==Presence.Type.subscribe&&incoming&&processed){
if (packet.getFrom()!=null) {
String sender = packet.getFrom().toString();
List<ChatLogs> logs = logsManager.query(sender.split("/")[0]);
if(logs!=null){
for (ChatLogs chatLogs : logs) {
System.out.println(chatLogs.getDetail());
Presence presence = new Presence(xmlReader
.read(new StringReader(
chatLogs.getDetail().replaceAll("\"", "\'")))
.getRootElement());
session.process(presence);
System.out.println("處理了");
logsManager.remove(chatLogs.getMessageId());
}
}
}
// sessionManager.
}
}
//判断是否为添加好友的请求,如过好友不在线,存储
if(packet instanceof Presence){
Presence presence = (Presence) packet.createCopy();
if(presence.getType()==Presence.Type.subscribe&&incoming&&processed){
JID reciver = presence.getTo();
try {
if(reciver!=null&&!reciver.toString().contains("conference")){
plugin = (PresencePlugin) XMPPServer.getInstance().getPluginManager().getPlugin("presence");
Presence onlineReciver = plugin.getPresence(null, reciver.toBareJID());
//用戶不在線情況
if(onlineReciver==null){
ChatLogs chatLogs = new ChatLogs();
chatLogs.setCreateDate(new Timestamp( new Date().getTime()));
chatLogs.setDetail(presence.toXML());
chatLogs.setLength(presence.toXML().length());
long messageID = SequenceManager.nextID(ChatLogsConstants.CHAT_LOGS);
chatLogs.setMessageId(messageID);
chatLogs.setReceiver(presence.getTo().toString());
chatLogs.setSender(presence.getFrom().toString());
chatLogs.setSessionJID(presence.getID());
logsManager.add(chatLogs);
}}
} catch (UserNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
// ClientSession session = sessionManager.getSession(packet.getFrom());
}
@Override
public void initializePlugin(PluginManager manager, File pluginDirectory) {
// TODO Auto-generated method stub
System.out.println("这个插件已经用上了");
interceptorManager.addInterceptor(this);
}
@Override
public void destroyPlugin() {
// TODO Auto-generated method stub
interceptorManager.removeInterceptor(this);
}
}
注意:由于此插件判断好友是否在线调用了presence插件中的plugin.getPresence(null, reciver.toBareJID());
方法,由于加入相应的jar包也不正确,我比较蛮横不讲理的复制了presence插件的/openfire/src/plugins/offlinefriend/src/java/org/jivesoftware/openfire/plugin/PresencePlugin.java这个类,代码如下:
“`
public class PresencePlugin implements Plugin, Component {
private static final Logger Log = LoggerFactory.getLogger(PresencePlugin.class);
private static final String subdomain = "presence";
private UserManager userManager;
private PresenceManager presenceManager;
private PluginManager pluginManager;
private ComponentManager componentManager;
private String hostname;
private Map<String, Presence> probedPresence;
private JID componentJID;
public void initializePlugin(PluginManager manager, File pluginDirectory) {
pluginManager = manager;
XMPPServer server = XMPPServer.getInstance();
userManager = server.getUserManager();
presenceManager = server.getPresenceManager();
hostname = server.getServerInfo().getXMPPDomain();
probedPresence = new ConcurrentHashMap<String, Presence>();
componentJID = new JID(subdomain + "." + hostname);
// Register new component
componentManager = ComponentManagerFactory.getComponentManager();
try {
componentManager.addComponent(subdomain, this);
}
catch (Exception e) {
Log.error(e.getMessage(), e);
}
}
public void destroyPlugin() {
userManager = null;
presenceManager = null;
// Remove presence plugin component
try {
componentManager.removeComponent(subdomain);
componentManager = null;
}
catch (Exception e) {
Log.error(e.getMessage(), e);
}
}
public String getName() {
return pluginManager.getName(this);
}
public String getDescription() {
return pluginManager.getDescription(this);
}
public void initialize(JID jid, ComponentManager componentManager) {
}
public void start() {
}
public void shutdown() {
}
public void processPacket(Packet packet) {
// Check that we are getting an answer to a presence probe
if (packet instanceof Presence) {
Presence presence = (Presence) packet;
if (presence.isAvailable() || presence.getType() == Presence.Type.unavailable ||
presence.getType() == Presence.Type.error) {
// Store answer of presence probes
probedPresence.put(presence.getFrom().toString(), presence);
}
}
}
/**
* Returns true if anyone is allowed to see the presence of other users. False means that
* only the users that are subscribed to a user presence will be able to get information
* about the user. By default, presence information is not publicly available.
*
* @return true if anyone is allowed to see the presence of other users.
*/
public boolean isPresencePublic() {
return JiveGlobals.getBooleanProperty("plugin.presence.public", false);
}
/**
* Sets if anyone is allowed to see the presence of other users. A false value means that
* only the users that are subscribed to a user presence will be able to get information
* about the user. By default, presence information is not publicly available.
*
* @param presencesPublic if anyone is allowed to see the presence of other users.
*/
public void setPresencePublic(boolean presencesPublic) {
JiveGlobals.setProperty("plugin.presence.public", presencesPublic ? "true" : "false");
}
/**
* Returns the status message for the unavailable presence. This setting allows
* a different string to be used for the status on this presence which is
* "Unavailable" by default.
*
* @return the status message for the unavailable presence.
*/
public String getUnavailableStatus() {
return JiveGlobals.getProperty("plugin.presence.unavailable.status", "Unavailable");
}
/**
* Sets the status message for the unavailable presence. This setting allows
* a different string to be used for the status on this presence which is
* "Unavailable" by default.
*
* @param statusMessage the status message for the unavailable presence.
*/
public void setUnavailableStatus(String statusMessage) {
JiveGlobals.setProperty("plugin.presence.unavailable.status", statusMessage);
}
/**
* Returns the presence of the requested user or <tt>null</tt> if the user is offline. If
* presences are not public then the user presence will be returned if and only if the sender
* of the request is subscribed to the user presence.
*
* @param sender the bare JID of the user making the request.
* @param jid the bare JID of the entity whose presence is being probed.
* @return the presence of the requested user.
* @throws UserNotFoundException If presences are not public and the sender is null or the
* sender cannot probe the presence of the requested user. Or if the requested user
* does not exist in the local server.
*/
public Presence getPresence(String sender, String jid) throws UserNotFoundException {
if (jid == null) {
throw new UserNotFoundException("Target JID not found in request");
}
JID targetJID = new JID(jid);
// Check that the sender is not requesting information of a remote server entity
if (targetJID.getDomain() == null || XMPPServer.getInstance().isRemote(targetJID)) {
throw new UserNotFoundException("Domain does not matches local server domain");
}
if (!hostname.equals(targetJID.getDomain())) {
// Sender is requesting information about component presence, so we send a
// presence probe to the component.
presenceManager.probePresence(componentJID, targetJID);
// Wait 30 seconds until we get the probe presence result
int count = 0;
Presence presence = probedPresence.get(jid);
while (presence == null) {
if (count > 300) {
// After 30 seconds, timeout
throw new UserNotFoundException(
"Request for component presence has timed-out.");
}
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
// don't care!
}
presence = probedPresence.get(jid);
count++;
}
// Clean-up probe presence result
probedPresence.remove(jid);
// Return component presence
return presence;
}
if (targetJID.getNode() == null ||
!UserManager.getInstance().isRegisteredUser(targetJID.getNode())) {
// Sender is requesting presence information of an anonymous user
throw new UserNotFoundException("Username is null");
}
if (!isPresencePublic()) {
if (sender == null) {
throw new UserNotFoundException("Sender is null");
}
else {
// If sender is same as target, then we can see ourselves
JID senderJID = new JID(sender);
if (!senderJID.getNode().equals(targetJID.getNode()) &&
!presenceManager.canProbePresence(new JID(sender), targetJID.getNode())) {
throw new UserNotFoundException("Sender is not allowed to probe this user");
}
}
}
User user = userManager.getUser(targetJID.getNode());
return presenceManager.getPresence(user);
}
}
该插件参考了聊天记录插件的上线离线包的区别,因此才能知道好友是否上线和离线。