/*******************************************************************************
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* hangum - initial API and implementation
******************************************************************************/
package com.hangum.tadpole.engine.utils;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import com.hangum.tadpole.session.manager.SessionManager;
/**
* 사용자 session 을 저장하고 관리하는 유틸 클래스이다.
*
* @author hangum
*
*/
public class HttpSessionCollectorUtil {
private static final Logger logger = Logger.getLogger(HttpSessionCollectorListener.class);
private static HttpSessionCollectorUtil sessionCollector = null;//new HttpSessionCollectorUtil();
public static enum COLLECT_KEY {SESSION, TIMEOUT};
/** id, httpsession */
private final Map<String, Map<String, Object>> mapSession = new ConcurrentHashMap<String, Map<String, Object>>();
private HttpSessionCollectorUtil() {};
/**
* get instance
*
* @return
*/
public static HttpSessionCollectorUtil getInstance() {
if(sessionCollector == null) {
sessionCollector = new HttpSessionCollectorUtil();
Thread httpSessionChecker = new Thread(new SessionLiveChecker(), "Tadpole_HttpSessionChecker");
httpSessionChecker.start();
}
return sessionCollector;
}
/**
* session created
*
* @param id
* @param session
* @param intMinuteTimeOut
*/
public void sessionCreated(String id, HttpSession session, int intMinuteTimeOut) {
if(logger.isDebugEnabled()) logger.debug(String.format("---> [login]%s->%s", id, session.getId()));
Map<String, Object> mapUserData = new HashMap<String, Object>();
mapUserData.put(COLLECT_KEY.SESSION.name(), session);
mapUserData.put(COLLECT_KEY.TIMEOUT.name(), intMinuteTimeOut);
mapSession.put(id, mapUserData);
}
/**
* session destoryed
*
* @param id
*/
public void sessionDestroyed(final String strEmail) {
Map<String, Object> mapUserData = mapSession.remove(strEmail);
try {
HttpSession httpSesssion = (HttpSession)mapUserData.get(COLLECT_KEY.SESSION.name());
httpSesssion.invalidate();
} catch(Throwable e) {
logger.error(String.format("System invalidate user %s, messages %s", strEmail, e.getMessage()));
} finally {
if(logger.isDebugEnabled()) logger.debug("========= remove connection start " + strEmail);
SessionManager.removeConnection(strEmail);
if(logger.isDebugEnabled()) logger.debug("========= remove connection end ");
}
}
/**
* get all session
*
* @return
*/
public Map<String, Map<String, Object>> getSessions() {
return mapSession;
}
/**
* find id to session
*
* @param id
* @return
*/
public Map<String, Object> find(String strEmail) {
return mapSession.get(strEmail);
}
/**
* find session
*
* @param strEmail
* @return
*/
public HttpSession findSession(String strEmail) {
Map<String, Object> mapUserData = find(strEmail);
if(mapUserData != null) {
return (HttpSession)mapUserData.get(COLLECT_KEY.SESSION.name());
}
return null;
}
}
/**
* HttpSession live checker
* @author hangum
*
*/
class SessionLiveChecker implements Runnable {
private static final Logger logger = Logger.getLogger(HttpSessionCollectorListener.class);
public SessionLiveChecker() {
}
@Override
public void run() {
while(true) {
// // 10 분에 한번씩 Thread 검사.
// try { Thread.sleep((60 * 1000) * 1); } catch(Exception e) {};
Map<String, Map<String, Object>> allUserSession = HttpSessionCollectorUtil.getInstance().getSessions();
Set<String> keys = allUserSession.keySet();
for(String id : keys) {
Map<String, Object> mapUserData = allUserSession.get(id);
HttpSession httpSession = (HttpSession)mapUserData.get(HttpSessionCollectorUtil.COLLECT_KEY.SESSION.name());
Integer intTimeOut = (Integer)mapUserData.get(HttpSessionCollectorUtil.COLLECT_KEY.TIMEOUT.name());
long userTime = intTimeOut * 60 * 1000;
try {
long gapTime = System.currentTimeMillis() - httpSession.getLastAccessedTime();
if(logger.isDebugEnabled()) {
logger.debug("=========== session live checker ===============");
logger.debug(String.format("[session user] id=%s", id));
logger.debug(String.format("[userTime]%s[gapTime]%s", userTime, gapTime));
logger.debug("=========== session live checker ===============");
}
if(gapTime > userTime) {
if(logger.isDebugEnabled()) logger.debug("[session invalidate is ]" + id);
HttpSessionCollectorUtil.getInstance().sessionDestroyed(id);
}
// session 이 만료되어서 시간을 가져 올수 없는 상태이므로 세션과 커넥션을 처리합니다.
} catch(IllegalStateException e) {
if(logger.isDebugEnabled()) logger.debug("[ise][session invalidate is ]" + id);
HttpSessionCollectorUtil.getInstance().sessionDestroyed(id);
}
}
// 엔진의 설정 정보를 디비에서 가져와서 동기화(?)
// TDDO 여기서 해야하나도 싶고요.(hangum)
// final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
// shell.getDisplay().syncExec(new Runnable() {
// @Override
// public void run() {
// try{
// TadpoleApplicationContextManager.initAdminSystemSetting();
// } catch(Exception e) {
// logger.error("re initialize system setting", e);
// }
// }
// });
// 10 분에 한번씩 Thread 검사.
try { Thread.sleep((60 * 1000) * 10); } catch(Exception e) {};
} // while
}
}