All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.s1.web.session.SessionScope Maven / Gradle / Ivy

There is a newer version: 0.1.3
Show newest version
package org.s1.web.session;

import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Session level scope.
 * 
* Scales horizontally with Hazelcast (http://hazelcast.org) *
* Should be initialized with Hazelcast instance (make it in {@link org.s1.web.ApplicationFilter}). * * @author Grigory Pykhov */ public class SessionScope { private static final Logger LOG = LoggerFactory.getLogger(SessionScope.class); private SessionScope() { } /** * Hazelcast IMap name */ public static final String SESSION_MAP = "S1-Web::SessionMap"; /** * Cookie name for storing session id */ public static final String COOKIE = "S1_ID"; private static IMap sessionMap; private static final ThreadLocal idLocal = new ThreadLocal(); private static HazelcastInstance hazelcastInstance; private static long TTL = 0; /** * Initialize Session scope, call it from {@link org.s1.web.ApplicationFilter} * * @param hazelcastInstance Hazelcast instance * @param TTL Max time while session can stay inactive (lastUsed in Context) */ public static void initialize(HazelcastInstance hazelcastInstance, long TTL) { SessionScope.hazelcastInstance = hazelcastInstance; if (TTL < 0) { TTL = 0; } SessionScope.TTL = TTL; } /** * Reset and clean all scopes */ public static void reset() { synchronized (SessionScope.class) { sessionMap = null; } } /** * Start new session scope (if already in scope - NOP) * * @param id Session id * @return Same id if new session scope started or null if already in session scope */ public static String start(String id) { if (idLocal.get() != null) { return null; } else { MDC.put("sessionId", id); idLocal.set(id); return id; } } /** * Finish session scope * * @param id Session id (if null or empty - NOP) */ public static void finish(String id) { if (id != null && !id.isEmpty()) { MDC.remove("sessionId"); idLocal.remove(); } } /** * Get current context * * @return Context (null if not in session scope) */ public static Context getContext() { String id = idLocal.get(); if (id == null) return null; Context s = getSessionMap().get(id); //check TTL if (s != null && (System.currentTimeMillis() - s.lastUsed) > TTL) { if (LOG.isDebugEnabled()) LOG.debug("Discarding session " + id + " with lifetime=" + (System.currentTimeMillis() - s.lastUsed) + "ms (TTL is " + TTL + "ms)"); s = null; } //new session if (s == null) s = new Context(); s.lastUsed = System.currentTimeMillis(); updateContext(s); s.id = id; return s; } /** * Retrieves session id from request, if it is empty - puts it back to response * * @param req Request * @param resp Response * @return Session id */ public static String retrieveSessionIdFromRequest(HttpServletRequest req, HttpServletResponse resp) { String id = null; if (req.getCookies() != null) { for (Cookie it : req.getCookies()) { if (COOKIE.equals(it.getName())) id = it.getValue(); } } if (id == null) { id = UUID.randomUUID().toString(); Cookie cookie = new Cookie(COOKIE, id); cookie.setPath("/"); resp.addCookie(cookie); } return id; } private static HazelcastInstance getHazelcastInstance() { if (hazelcastInstance == null) { throw new IllegalStateException("You`ve forget to call SessionScope#initialize(), hazelcastInstance is null"); } return hazelcastInstance; } private static IMap getSessionMap() { if (sessionMap == null) { synchronized (SessionScope.class) { if (sessionMap == null) { sessionMap = getHazelcastInstance().getMap(SESSION_MAP); } } } return sessionMap; } private static void updateContext(Context s) { String id = idLocal.get(); if (id == null) return; getSessionMap().put(id, s); } /** * Session */ public static class Context implements Serializable { private String id; private long created = System.currentTimeMillis(); private long lastUsed = System.currentTimeMillis(); private final Map data = new HashMap(); /** * Session id * * @return Id */ public String getId() { return id; } /** * Create timestamp * * @return milliseconds */ public long getCreated() { return created; } /** * Last used timestamp * * @return milliseconds */ public long getLastUsed() { return lastUsed; } /** * Get session parameter * * @param key Key * @param Type * @return Value (or null if not found) */ public T get(String key) { return get(key, null); } /** * Get session parameter * * @param key Key * @param def Default (if !data.containsKey) * @param Type * @return Value */ public T get(String key, T def) { if (!data.containsKey(key)) return def; return (T) data.get(key); } /** * Set session parameter * * @param key Key * @param val Value * @return Context */ public Context set(String key, Object val) { data.put(key, val); updateContext(this); return this; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy