package server;
import java.awt.datatransfer.StringSelection;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.LinkedBlockingQueue;
import org.apache.log4j.Logger;
import org.apache.mina.core.session.IoSession;
import org.hibernate.Session;
import observer.ObserverMessage;
import observer.ObserverMessage_Login;
import protocol.ProtoHead;
import protocol.Data.ChatData.ChatItem;
import protocol.Data.ChatData.ChatItem.ChatType;
import protocol.Msg.ReceiveChatMsg.ReceiveChatSync;
import protocol.Msg.SendChatMsg.SendChatReq;
import protocol.Msg.SendChatMsg.SendChatRsp;
import tools.Debug;
import model.Chatting;
import model.HibernateSessionFactory;
/**
* 网络逻辑层(微信消息模块)
*
* @author Feng
*/
public class ServerModel_Chatting {
public static final int SAVE_DATA_HOUR = 1;
public static final int INTERVAL_HOUR = 24 * 60 * 60;
public static final int DELETE_INTERVAL = 24 * 3 * 60 * 60;
private Logger logger = Logger.getLogger(this.getClass());
public Hashtable<String, LinkedBlockingQueue<Chatting>> chattingHashtable;
private ServerModel serverModel;
private ServerNetwork serverNetwork;
public ServerModel getServerModel() {
return serverModel;
}
public void setServerModel(ServerModel serverModel) {
this.serverModel = serverModel;
init();
}
public ServerNetwork getServerNetwork() {
return serverNetwork;
}
public void setServerNetwork(ServerNetwork serverNetwork) {
this.serverNetwork = serverNetwork;
}
public ServerModel_Chatting(){
}
/**
* 初始化
*
* @author Feng
*/
public void init() {
if (chattingHashtable != null)
return;
chattingHashtable = new Hashtable<String, LinkedBlockingQueue<Chatting>>();
// 监听用户登陆事件
serverModel.addObserver(new Observer() {
/**
* 检查是否有未接收的消息
*/
@Override
public void update(Observable o, Object arg) {
ObserverMessage om = (ObserverMessage) arg;
if (om.type == ObserverMessage.Type.Login) {
ObserverMessage_Login oml = (ObserverMessage_Login) om;
Debug.log(new String[] { "ServerModel_Chatting", "ServerModel_Chatting" }, "Catch User( " + oml.userId
+ ") 'LoginEvent'!");
ArrayList<Chatting> chattingList = getChattingNotReceive(oml.userId);
if (chattingList != null && chattingList.size() > 0) {
Debug.log(new String[] { "ServerModel_Chatting", "ServerModel_Chatting" }, "User(" + oml.userId + ") has "
+ chattingList.size() + " 'Chattings' doesn't be received,Start transmit!");
ReceiveChatSync.Builder receiveChatting = ReceiveChatSync.newBuilder();
// 加入所有未接收消息
for (Chatting chatting : chattingList)
receiveChatting.addChatData(chatting.createChatItem());
// 发送
serverNetwork.sendToClient(oml.ioSession, new PacketFromServer(
ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC_VALUE, receiveChatting.build().toByteArray()));
// byte[] messageWillSend =
// receiveChatting.build().toByteArray();
// 添加监听
// addListenReceiveChatting(oml.ioSession, chattingList,
// messageWillSend);
}
}
}
});
// 添加每日聊天记录存入数据库
// Date firstStartDate = new Date();
// firstStartDate.setDate(firstStartDate.getDate() + 1);
// firstStartDate.setHours(SAVE_DATA_HOUR);
// Timer timer = new Timer();
// timer.schedule(new SaveDataThread(), firstStartDate, INTERVAL_HOUR);
// test();
}
/**
* 发送一条聊天消息
*
* @param ioSession
* @param sendChattingBuilder
* @author Feng
*/
public void sendChatting(final Chatting chatting) {
sendChatting(new Chatting[] { chatting });
}
public void sendChatting(final Chatting[] chattings) {
if (chattings.length < 1)
return;
IoSession receiverIoSession;
ReceiveChatSync.Builder receiverChatObj;
ClientUser clientUser;
Chatting chatting;
// 获取接收者
for (int i=0; i<chattings.length; i++) {
chatting = chattings[i];
clientUser = serverModel.getClientUserByUserId(chattings[0].getReceiverUserId());
// 接受者不在线,存入内存
if (clientUser == null) {
logger.debug("ServerModel_Chatting : sendChatting : The Receiver(" + chattings[0].getReceiverUserId()
+ ") is offline, Chatting will be save in Server!");
addChatting(chatting);
return;
}
receiverIoSession = clientUser.ioSession;
// 创建要发送的消息包
receiverChatObj = ReceiveChatSync.newBuilder();
receiverChatObj.addChatData(chatting.createChatItem());
serverNetwork.sendToClient(new WaitClientResponse(receiverIoSession, new PacketFromServer(
ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC_VALUE, receiverChatObj.build().toByteArray()),
new SendChattingHandle(chatting)));
}
}
/**
* 发送微信消息失败处理
* @author Feng
*
*/
private class SendChattingHandle implements WaitClientResponseCallBack{
private Chatting chatting;
public SendChattingHandle(Chatting chatting) {
this.chatting = chatting;
}
@Override
public void beforeDelete() {
// 添加发送失败时删除前的回调
addChatting(chatting);
}
}
/**
* 往消息队列中添加一条未接收的消息
*
* @param chatting
* @author Feng
*/
public void addChatting(Chatting chatting) {
LinkedBlockingQueue<Chatting> chattingQueue;
if (!chattingHashtable.containsKey(chatting.getReceiverUserId())) {
chattingQueue = new LinkedBlockingQueue<Chatting>();
chattingHashtable.put(chatting.getReceiverUserId() + "", chattingQueue);
} else
chattingQueue = chattingHashtable.get(chatting.getReceiverUserId());
chattingQueue.add(chatting);
}
/**
* 获取未被接收的聊天消息
*
* @param receiveUserId
* @return
* @author Feng
*/
public ArrayList<Chatting> getChattingNotReceive(String receiveUserId) {
if (chattingHashtable.containsKey(receiveUserId)) {
LinkedBlockingQueue<Chatting> chattingQueue = chattingHashtable.get(receiveUserId);
ArrayList<Chatting> chattingList = new ArrayList<Chatting>();
while (!chattingQueue.isEmpty())
chattingList.add(chattingQueue.poll());
return chattingList;
}
return new ArrayList<Chatting>();
}
/**
* 将内存中所有聊天记录存入数据库
*
* @author Feng
*/
public class SaveDataThread extends TimerTask {
public void run() {
try {
Iterator iterator = chattingHashtable.keySet().iterator();
LinkedBlockingQueue<Chatting> queue;
// 删除过期消息
Calendar calendar = Calendar.getInstance();
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.YEAR) - 3);
Session session = HibernateSessionFactory.getSession();
String sql = "delete from " + Chatting.TABLE_NAME + " where time<" + calendar.getTimeInMillis() + ";";
session.createQuery(sql);
session = HibernateSessionFactory.getSession();
while (iterator.hasNext()) {
queue = (LinkedBlockingQueue<Chatting>) iterator.next();
// 读取哈希表,存入硬盘
for (Chatting chatting : queue) {
session.save(chatting);
}
}
HibernateSessionFactory.commitSession(session);
// 清空内存
chattingHashtable.clear();
} catch (Exception e) {
Debug.log(Debug.LogType.FAULT, new String[] { "ServerModel_Chatting", "SaveDataThread" },
"Save Chatting which were to long ago Fail!");
}
}
}
// public void test2() {
// Iterator iterator = chattingHashtable.keySet().iterator();
// LinkedBlockingQueue<Chatting> queue;
//
// // 删除过期消息
// Date date = new Date();
// date.setDate(date.getDate() - 3);
// // date.setDate(date.getDate() + 3);
// Session session = HibernateSessionFactory.getSession();
// String tableName = Chatting.TABLE_NAME;
// tableName = tableName.substring(0, 1).toUpperCase() + tableName.substring(2, tableName.length());
// String sql = "delete from " + Chatting.class.getName() + " where time<" + date.getTime();
// session.createQuery(sql);
//
// HibernateSessionFactory.commitSession(session);
// session = HibernateSessionFactory.getSession();
//
// session = HibernateSessionFactory.getSession();
// Chatting a = new Chatting("a3", "a4", ChatType.TEXT, "abcde", 20140526, false, 2);
// a.setId(1);
// session.save(a);
//
// while (iterator.hasNext()) {
// queue = chattingHashtable.get(iterator.next().toString());
//
// // 读取哈希表,存入硬盘
// for (Chatting chatting : queue) {
// Chatting c = new Chatting(chatting.getSenderUserId(), chatting.getReceiverUserId(), chatting.getChattingType(),
// chatting.getMessage(), Calendar.getInstance().getTimeInMillis());
// session.save(c);
// // session.save(chatting);
// }
// }
// HibernateSessionFactory.commitSession(session);
//
// // 清空内存
// chattingHashtable.clear();
// }
/**
* 测试用
*
* @param args
* @author Feng
*/
// private void test() {
// addChatting(new Chatting("a", "b", ChatType.TEXT, "Fuck", 0));
// addChatting(new Chatting("c", "d", ChatType.TEXT, "Fuck", 0));
// System.out.println("size: " + chattingHashtable.size());
//
// // Timer timer = new Timer();
// // timer.schedule(new SaveDataThread(), 0);
// // test2();
// // System.out.println("size: " + chattingHashtable.size());
// }
}