package me.test.redis;
import java.util.Calendar;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
import me.test.MySessionFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
@SuppressWarnings("deprecation")
public class MySession implements HttpSession {
private Logger logger = LoggerFactory.getLogger(MySession.class);
private MySessionManager sessionManager;
private RedisTemplate<String, Object> redisTemplate;
private String redisHashKey;
private final String id;
private boolean isNew = true;
private static final HttpSessionContext NULL_SESSION_CONTEXT = new HttpSessionContext() {
public HttpSession getSession(String sessionId) {
return null;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public Enumeration getIds() {
return Collections.enumeration(Collections.EMPTY_LIST);
}
};
public MySession(String id, MySessionManager sessionManager) {
this.id = id;
this.isNew = true;
this.sessionManager = sessionManager;
this.redisTemplate = sessionManager.getRedisTemplate();
this.redisHashKey = sessionManager.getRedisHashKey(id);
}
private void checkAttributeValid(String name) {
if (name == null) {
throw new NullPointerException("Session attribute name can not be null");
}
if (MEATDATA_KEY_CREATE_TIME.equals(name)
|| MEATDATA_KEY_LAST_ACCESS_TIME.equals(name)
|| MEATDATA_KEY_MAX_INACTIVE_INTERVAL.equals(name)) {
throw new IllegalArgumentException("attribute name \"" + name + "\" is reverse for internal useage.");
}
}
// //////////////////////////////////////////////////////////////////
public static final String PREFIX = MySession.class.getName();
public static final String MEATDATA_KEY_CREATE_TIME = PREFIX + ".CREATE_TIME";
public static final String MEATDATA_KEY_LAST_ACCESS_TIME = PREFIX + ".LAST_ACCESS_TIME";
public static final String MEATDATA_KEY_MAX_INACTIVE_INTERVAL = PREFIX + ".MAX_INACTIVE_INTERVAL";
public long getCreationTime() {
return (Long) redisTemplate.opsForHash().get(redisHashKey, MEATDATA_KEY_CREATE_TIME);
}
public String getId() {
return id;
}
private void checkValid() {
if (!sessionManager.isSessionValid(getId())) {
throw new IllegalStateException();
}
}
public long getLastAccessedTime() {
checkValid();
Long lastAccessedTime = (Long) redisTemplate.opsForHash().get(redisHashKey, MEATDATA_KEY_LAST_ACCESS_TIME);
return lastAccessedTime != null ? lastAccessedTime : 0;
}
protected void access() {
long curTimeMillis = System.currentTimeMillis();
redisTemplate.opsForHash().put(redisHashKey, MEATDATA_KEY_LAST_ACCESS_TIME, curTimeMillis);
Calendar expireTime = Calendar.getInstance();
expireTime.setTimeInMillis(curTimeMillis);
expireTime.add(Calendar.SECOND, this.getMaxInactiveInterval());
redisTemplate.expireAt(redisHashKey, expireTime.getTime());
}
public ServletContext getServletContext() {
return MySessionFilter.servletContextHolder.get();
}
public void setMaxInactiveInterval(int interval) {
long createTime = this.getCreationTime();
Calendar expireTime = Calendar.getInstance();
expireTime.setTimeInMillis(createTime);
expireTime.add(Calendar.SECOND, interval);
redisTemplate.opsForHash().put(redisHashKey, MEATDATA_KEY_MAX_INACTIVE_INTERVAL, interval);
redisTemplate.expireAt(redisHashKey, expireTime.getTime());
}
public int getMaxInactiveInterval() {
Integer interval = (Integer) redisTemplate.opsForHash().get(redisHashKey, MEATDATA_KEY_MAX_INACTIVE_INTERVAL);
return interval != null ? interval : 0;
}
public HttpSessionContext getSessionContext() {
checkValid();
return NULL_SESSION_CONTEXT;
}
public Object getAttribute(String name) {
checkAttributeValid(name);
checkValid();
return sessionManager.getRedisTemplate().opsForHash().get(redisHashKey, name);
}
public Object getValue(String name) {
return getAttribute(name);
}
@SuppressWarnings("rawtypes")
public Enumeration getAttributeNames() {
checkValid();
HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
Set<String> attrNameSet = hashOps.keys(redisHashKey);
attrNameSet.remove(MEATDATA_KEY_CREATE_TIME);
attrNameSet.remove(MEATDATA_KEY_LAST_ACCESS_TIME);
attrNameSet.remove(MEATDATA_KEY_MAX_INACTIVE_INTERVAL);
List<String> attrNameList = new LinkedList<String>(attrNameSet);
Collections.sort(attrNameList);
return Collections.enumeration(attrNameList);
}
public String[] getValueNames() {
checkValid();
return (String[]) redisTemplate.opsForHash().keys(redisHashKey).toArray();
}
public void setAttribute(String name, Object value) {
checkAttributeValid(name);
checkValid();
redisTemplate.opsForHash().put(redisHashKey, name, value);
}
public void putValue(String name, Object value) {
setAttribute(name, value);
}
public void removeAttribute(String name) {
checkAttributeValid(name);
checkValid();
redisTemplate.opsForHash().delete(redisHashKey, name);
}
public void removeValue(String name) {
removeAttribute(name);
}
public void invalidate() {
checkValid();
redisTemplate.delete(redisHashKey);
}
public String getRedisHashKey() {
return redisHashKey;
}
public boolean isNew() {
checkValid();
return this.isNew;
}
}