package com.sqj.openfire.chat.logs;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID; import org.apache.commons.lang.StringUtils;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.jivesoftware.openfire.OfflineMessageStore;
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.session.Session;
import org.jivesoftware.openfire.user.UserManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence; import com.sqj.openfire.chat.logs.entity.Chat;
import com.sqj.openfire.chat.logs.entity.XmlToMap; /** <b>function:</b> 聊天记录插件
* @author shm
* @createDate 2016-3-14
* @version 1.0
*/
public class ChatLogsPlugin implements PacketInterceptor, Plugin {
private static final Logger log = LoggerFactory.getLogger(ChatLogsPlugin.class);
private static PluginManager pluginManager;
private static DbChatLogsManager logsManager;
private InterceptorManager interceptorManager; public ChatLogsPlugin()
{
this.interceptorManager = InterceptorManager.getInstance();
logsManager = DbChatLogsManager.getInstance();
} /**
* * <b>function:</b> 拦截消息核心方法,Packet就是拦截消息对象
* * @author shm
* * @createDate 2016-3-14
* */
@Override
public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed) throws PacketRejectedException {
if (session != null) {
//debug(packet, incoming, processed, session);
}
JID recipient = packet.getTo();
if (recipient != null) {
String username = recipient.getNode();
// 广播消息或是不存在/没注册的用户.
if (username == null || !UserManager.getInstance().isRegisteredUser(recipient)) {
return;
} else if (!XMPPServer.getInstance().getServerInfo().getXMPPDomain().equals(recipient.getDomain())) {
// 非当前openfire服务器信息
return;
} else if ("".equals(recipient.getResource())) {
}
}
this.doAction(packet, incoming, processed, session);
} /**
* <b>function:</b> 执行保存/分析聊天记录动作
* @author shm
* @createDate 2016-3-14
* @param packet 数据包
* @param incoming true表示发送方
* @param session 当前用户session
*/
private void doAction(Packet packet, boolean incoming, boolean processed, Session session) {
Packet copyPacket = packet.createCopy();
if (packet instanceof Message) {
Message message = (Message) copyPacket;
// 一对一聊天,单人模式
if (message.getType() == Message.Type.chat) {
log.info("单人聊天信息:{}", message.toXML());
//debug("单人聊天信息:" + message.toXML());
// 程序执行中;是否为结束或返回状态(是否是当前session用户发送消息)
if (processed || !incoming) {
return;
} java.sql.Timestamp date = new java.sql.Timestamp(new Date().getTime()); //在原有的扩展xml中添加发送日期子节点
Element chatInfoElement = message.getElement().element("chatinfo");
Element timeElement = DocumentFactory.getInstance().createDocument().addElement("sendtime");
timeElement.setText(String.valueOf(date.getTime()));
chatInfoElement.add(timeElement); //logsManager.add(this.get(packet, incoming, session));
logsManager.addByMap(this.getMsgInfo(packet, incoming, session, date)); //保存到离线消息表,客户端收到后调用删除离线消息功能,这样可确保即使网络突然掉线或不好的情况下消息丢失的问题
OfflineMessageStore offlineMessageStore = new OfflineMessageStore();
offlineMessageStore.addMessage(message); //消息回执
Message receiptMessage = new Message();
receiptMessage.setTo(message.getFrom());
receiptMessage.setType(Message.Type.normal);
Element received = receiptMessage.addChildElement("received", "urn:xmpp:receipts");
received.addAttribute("id", message.getID());
received.addAttribute("type", "normal");
log.info("回执内容:" + receiptMessage); // 判断接受者是否在线,2代表离线状态,1代表在线状态,0代表用戶不存在
//注意一定要修改Constant类中的url,否则url错误或导致消息发送很慢,因为url不对时查找用户是否在线会浪费很多时间
/*if (IsOnLineUtils.IsUserOnLine(message.getTo()) == 1) {
received.addAttribute("status", "1");
} else if (IsOnLineUtils.IsUserOnLine(message.getTo()) == 0) {
received.addAttribute("status", "0");
} else if (IsOnLineUtils.IsUserOnLine(message.getTo()) == 2) {
received.addAttribute("status", "2");
}*/ try {
XMPPServer.getInstance().getPacketDeliverer().deliver(receiptMessage);
log.info("服务端回执成功!");
} catch (Exception e) {
e.printStackTrace();
} // 群聊天,多人模式
} else if (message.getType() == Message.Type.groupchat) {
List<?> els = message.getElement().elements("x");
if (els != null && !els.isEmpty()) {
log.info("群聊天信息:{}", message.toXML());
debug("群聊天信息:" + message.toXML());
} else {
log.info("群系统信息:{}", message.toXML());
debug("群系统信息:" + message.toXML());
}
// 其他信息
}else {
log.info("其他信息:{}", message.toXML());
//debug("其他信息:" + message.toXML());
}
} else if (packet instanceof IQ) {
IQ iq = (IQ) copyPacket;
if (iq.getType() == IQ.Type.set && iq.getChildElement() != null && "session".equals(iq.getChildElement().getName())) {
log.info("用户登录成功:{}", iq.toXML());
//debug("用户登录成功:" + iq.toXML());
}
} else if (packet instanceof Presence) {
Presence presence = (Presence) copyPacket;
if (presence.getType() == Presence.Type.unavailable) {
log.info("用户退出服务器成功:{}", presence.toXML());
//debug("用户退出服务器成功:" + presence.toXML());
}
}
} /**
* <b>function:</b> 创建一个聊天记录实体对象,并设置相关数据
* @author shm
* @createDate 2016-3-14
* @param packet 数据包
* @param incoming 如果为ture就表明是发送者
* @param session 当前用户session
* @return 聊天实体
*/
@SuppressWarnings("unchecked")
private Chat get(Packet packet, boolean incoming, Session session) {
Message message = (Message) packet;
JID jid = session.getAddress(); Map<String, Object> map = XmlToMap.xmlToHashMap(message.toXML());
Chat chat = new Chat();
if(map.containsKey("zid") && !"null".equals(map.get("zid")) && !StringUtils.isEmpty(map.get("zid")+"")){
chat.setId(map.get("zid")+"");
}else{
chat.setId(UUID.randomUUID().toString().replace("-", ""));
}
chat.setCaseId(map.get("caseid")+"");
chat.setContent(message.getBody());
chat.setCreator(jid.getNode());
chat.setSender(jid.getNode());
chat.setModifier(jid.getNode());
chat.setSendee(message.getTo().getNode());
chat.setIdentity(map.get("identity")+"");
chat.setzType(map.get("ztype")+"");
chat.setSenderId(map.get("senderid")+"");
chat.setSendeeId(map.get("sendeeid")+""); if(map.get("msglength") != null && !"".equals(map.get("msglength")))
{
chat.setMsgLength(Integer.parseInt(map.get("msglength")+""));
}
return chat;
} @SuppressWarnings({ "unchecked", "rawtypes" })
private Map getMsgInfo(Packet packet, boolean incoming, Session session, java.sql.Timestamp date) {
Message message = (Message) packet;
Map<String, Object> map = XmlToMap.xmlToHashMap(message.toXML());
map.put("content", message.getBody());
map.put("sendtime", date);
log.info("tag:{}", map.get("tag"));
//debug("tag:" + map.get("tag"));
return map;
} /**
* * <b>function:</b> 调试信息
* @author shm
* @createDate 2016-3-14
* @param packet 数据包
* @param incoming 如果为ture就表明是发送者
* @param processed 执行
* @param session 当前用户session
*/
private void debug(Packet packet, boolean incoming, boolean processed, Session session) {
//String info = "[ packetID: " + packet.getID() + ", to: " + packet.getTo() + ", from: " + packet.getFrom() + ", incoming: " + incoming + ", processed: " + processed + " ]";
StringBuilder info = new StringBuilder();
info.append("[ packetID: ").append(packet.getID()).append(", to: ").append(packet.getTo()).append(", from: ").append(packet.getFrom()).append(", incoming: ").append(incoming).append(", processed: ").append(processed).append(" ]"); long timed = System.currentTimeMillis();
debug("################### start ###################" + timed);
debug("id:" + session.getStreamID() + ", address: " + session.getAddress());
debug("info: " + info); debug("xml: " + packet.toXML());
debug("################### end #####################" + timed);
log.info("id:" + session.getStreamID() + ", address: " + session.getAddress());
log.info("info: {}", info);
log.info("plugin Name: " + pluginManager.getName(this) + ", xml: " + packet.toXML());
} private void debug(Object message) {
if (true) {
System.out.println(message);
}
} @Override
public void destroyPlugin() {
interceptorManager.removeInterceptor(this);
debug("销毁聊天记录插件成功!");
} @Override
public void initializePlugin(PluginManager manager, File pluginDirectory) {
interceptorManager.addInterceptor(this);
pluginManager = manager;
debug("安装聊天记录插件成功!");
} /* // 判断接受者是否在线,2代表离线状态,1代表在线状态,0代表用戶不存在
if (IsOnLineUtils.IsUserOnLine(message.getTo()) == 2) {
// 离线時,向offline表写数据
OfflineMessageStore offlineMessageStore = new OfflineMessageStore();
offlineMessageStore.addMessage(message);
// 向客户端发回执
Message receiptMessage = new Message();
receiptMessage.setTo(message.getFrom());
receiptMessage.setType(Message.Type.normal);
Element received = receiptMessage.addChildElement("received", "urn:xmpp:receipts");
received.setAttributeValue("id", message.getID());
System.out.println("0000000000回执内容" + receiptMessage);
try {
XMPPServer.getInstance().getPacketDeliverer().deliver(receiptMessage);
System.out.println("服务端回执成功!");
} catch (Exception e) {
e.printStackTrace();
}
}*/
}

openfire聊天消息记录插件关键代码的更多相关文章

  1. 源码详解openfire保存消息记录_修改服务端方式

    实现openfire消息记录通常有两种方式,修改服务端和添加消息记录插件. 今天,简单的说明一下修改服务端方式实现消息记录保存功能. 实现思路 修改前: 默认的,openfire只提供保存离线记录至o ...

  2. 基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件[转]

    上一篇文章介绍到怎么在自己的Java环境中搭建openfire插件开发的环境,同时介绍到怎样一步步简单的开发openfire插件.一步步很详细的介绍到简单插件开发,带Servlet的插件的开发.带JS ...

  3. openfire:基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件

    基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件 上一篇文章介绍到怎么在自己的Java环境中搭建openfire插件开发的环境,同时介绍到怎样一步步简单的开发openfir ...

  4. 基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件

    原文:http://www.cnblogs.com/hoojo/archive/2013/03/29/openfire_plugin_chatlogs_plugin_.html 随笔-150  评论- ...

  5. spark结合 Openfire服务器,发送聊天消息

    1.下载OpenFire服务器,进行安装,参考http://www.cnblogs.com/hoojo/archive/2012/05/17/2506769.html 2.程序运行客户端:下载客户端代 ...

  6. Smack 结合 Openfire服务器,建立IM通信,发送聊天消息

    在文章开始,请你了解和熟悉openfire方面的相关知识,这样对你理解下面代码以及下面代码的用途有很好的了解.同时,你可能需要安装一个简单的CS聊天工具,来测试你的代码是否成功的在openfire服务 ...

  7. 七、Uniapp+vue+腾讯IM+腾讯音视频开发仿微信的IM聊天APP,支持各类消息收发,音视频通话,附vue实现源码(已开源)-聊天消息项的实现

    会话好友列表的实现 1.项目引言 2.腾讯云后台配置TXIM 3.配置项目并实现IM登录 4.会话好友列表的实现 5.聊天输入框的实现 6.聊天界面容器的实现 7.聊天消息项的实现 8.聊天输入框扩展 ...

  8. 微信iOS消息拦截插件教程-Tweak HelloWorld

    微信iOS消息拦截插件教程-Tweak HelloWorld 标签(空格分隔): 越狱开发教程 1.环境准备 准备一台越狱的手机,具体参照上一篇教程 搭建Theos越狱开发环境 2.开发过程 新建一个 ...

  9. 微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)

    1.点评 对于IM系统来说,如何做到IM聊天消息离线差异拉取(差异拉取是为了节省流量).消息多端同步.消息顺序保证等,是典型的IM技术难点. 就像即时通讯网整理的以下IM开发干货系列一样: <I ...

随机推荐

  1. freebsd|odoo - 为odoo报表 安装文泉译中文字体

    来源: Odoo8.0中使用文泉译中文字体         http://blog.csdn.net/vnsoft/article/details/40056935 FreeBSD wkhtmltop ...

  2. 001_从原理上搞定编码-- Base64编码

    开发者对 Base64编码肯定很熟悉,是否对它有很清晰的认识就不一定了.实际 上Base64已经简单到不能再简单了,如果对它的理解还是模棱两可实在不应该.大概介绍一下Base64的相关内容,花几分钟时 ...

  3. 使用Notepad++代替笨拙的Arduino IDE

    Arduino自带的IDE 太不好用了,下面是用强大,轻量级,免费,开源,丰富插件的的Notepad++编辑器来打造Arduino开发环境 . 配置过程对新生来说可能有些繁琐,但是我尽力写的很详细了, ...

  4. angularJ表单验证

    常用的表单验证指令 1. 必填项验证 某个表单输入是否已填写,只要在输入字段元素上添加HTML5标记required即可: <input type="text" requir ...

  5. ++i 与 i++ 区别

    i++返回原来的值 ++i 返回i+1的值   但是i++  i的值也会增加1 但是返回还是原来的值 int i = 1; i = i++; System.out.println(i); 输出 1 i ...

  6. asp获取文件名和扩展名的函数代码

    <% '获取文件名(不含扩展名) Function getFilename(text)text = Left(text,inStrRev(text,".")-1)getFil ...

  7. 说一下linux中shell的后台进程与前台进程

    环境: 操作系统:archlinux; 终端模拟器:rxvt-unicode(urxvt); shell:bash; 这里所说的后台进程是指在命令行后面加一个 ampersand(&),前台进 ...

  8. ReportDB数据库存储选型分析

    SQLServer关于reportDB的存储选型做如下分析: 网络存储两大主要类型: 1.NAS 支持的文件传输协议:NFS(unix/linux文件共享).SMB(windows).samba(li ...

  9. Git Permission denied (publickey).

    有可能, jenkins slave service or jenkins service的logon 账户没有设置好

  10. viewpager实现酷炫侧滑demo

    晚上叫外卖,打开饿了么,发现推了一个版本,更新以后,点开了个鸡腿,哇,交互炫炸了. 不过还是有槽点.我是无意中才发现可以左右滑动的.这...你不告诉我,我怎么知道左右可以滑. https://gith ...