package org.ovirt.engine.core.bll.session;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.ovirt.engine.core.common.users.VdcUser;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.compat.StringHelper;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.utils.ThreadLocalParamsContainer;
import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation;
public class SessionDataContainer {
private ConcurrentMap<String, Map<String, Object>> oldContext =
new ConcurrentHashMap<String, Map<String, Object>>();
private ConcurrentMap<String, Map<String, Object>> newContext =
new ConcurrentHashMap<String, Map<String, Object>>();
private static SessionDataContainer dataProviderInstance = new SessionDataContainer();
private SessionDataContainer() {
}
public static SessionDataContainer getInstance() {
return dataProviderInstance;
}
/**
* Get data of session attached to current thread by key
*
* @param key
* - the internal key
* @return
*/
public final Object GetData(String key) {
String sessionId = ThreadLocalParamsContainer.getHttpSessionId();
if (sessionId == null) {
return null;
}
return GetData(sessionId, key);
}
/**
* This method will set user by session which is attached to thread
* @param key
* @param value
* @return At case when session is attached to thread will be return a true value
*/
public final boolean SetData(String key, Object value) {
String sessionId = ThreadLocalParamsContainer.getHttpSessionId();
if (StringHelper.isNullOrEmpty(sessionId)) {
return false;
}
SetData(sessionId, key, value);
return true;
}
/**
* Get data by session and internal key
*
* @param sessionId
* - id of session
* @param key
* - the internal key
* @return
*/
public final Object GetData(String sessionId, String key) {
return GetData(sessionId, key, true);
}
/**
* Get data by session and internal key
*
* @param sessionId
* - id of session
* @param key
* - the internal key
* @param refresh
* - if perform refresh of session
* @return
*/
public final Object GetData(String sessionId, String key, boolean refresh) {
Map<String, Object> currentContext = null;
if ((currentContext = newContext.get(sessionId)) != null) {
return currentContext.get(key);
}
if (refresh) {
if((currentContext = oldContext.remove(sessionId)) != null) {
newContext.put(sessionId, currentContext);
}
} else {
currentContext = oldContext.get(sessionId);
}
if (currentContext != null) {
return currentContext.get(key);
}
return null;
}
public final void SetData(String sessionId, String key, Object value) {
// Try to get value from new generation
Map<String, Object> context = newContext.get(sessionId);
if (context == null) {
// Try to get value from old generation
context = oldContext.get(sessionId);
if (context == null) {
context = new ConcurrentHashMap<String, Object>();
}
// Put a value to new generation , for case that other thread put
// value before current thread , his value will be used
Map<String, Object> oldSessionContext = newContext.putIfAbsent(sessionId, context);
if (oldSessionContext != null) {
context = oldSessionContext;
}
}
context.put(key, value);
}
/**
* This method will move all newGeneration to old generation and old
* generation will be cleaned automaticly
*
* @return
*/
private Map<String, Map<String, Object>> deleteOldGeneration() {
Map<String, Map<String, Object>> temp = oldContext;
oldContext = newContext;
newContext = new ConcurrentHashMap<String, Map<String, Object>>();
return temp;
}
/**
* Remove the cached data of session The sessionId is retrieved from
* ThreadLocal
*/
public final void removeSession() {
String sessionId = ThreadLocalParamsContainer.getHttpSessionId();
if (sessionId != null) {
removeSession(sessionId);
}
}
public boolean containsKey(String key) {
String sessionId = ThreadLocalParamsContainer.getHttpSessionId();
if (sessionId != null) {
return oldContext.containsKey(key) || newContext.containsKey(key);
}
return false;
}
/**
* Remove the cached data of current session
*
* @param sessionId
* - id of current session
*/
public final void removeSession(String sessionId) {
oldContext.remove(sessionId);
newContext.remove(sessionId);
}
/**
* Will run the process of cleaning expired sessions. At case when session
* connected to user, it will be also deleted from DB
*/
@OnTimerMethodAnnotation("cleanExpiredUsersSessions")
public final void cleanExpiredUsersSessions() {
Map<String, Map<String, Object>> map = getInstance().deleteOldGeneration();
if (map != null && !map.isEmpty()) {
Map<String, Guid> userSessionMap = new HashMap<String, Guid>();
for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) {
VdcUser user = (VdcUser) entry.getValue().get("VdcUser");
if (user != null) {
userSessionMap.put(entry.getKey(), user.getUserId());
}
}
if (!userSessionMap.isEmpty()) {
DbFacade.getInstance().getDbUserDAO().removeUserSessions(userSessionMap);
}
}
}
}