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();
}
}*/
}
05-02 06:12