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

com.vtence.molecule.session.SessionPool Maven / Gradle / Ivy

package com.vtence.molecule.session;

import java.time.Clock;
import java.time.Instant;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class SessionPool implements SessionStore, SessionHouse {

    private final Map sessions = new ConcurrentHashMap<>();
    private final SessionIdentifierPolicy policy;

    private Clock clock = Clock.systemDefaultZone();
    private SessionPoolListener listener = SessionPoolListener.NONE;
    private int idleTimeout;
    private int timeToLive;
    private boolean renew;

    public static SessionPool secure() {
        return new SessionPool(new SecureIdentifierPolicy());
    }

    public SessionPool(SessionIdentifierPolicy policy) {
        this.policy = policy;
    }

    public SessionPool usingClock(Clock clock) {
        this.clock = clock;
        return this;
    }

    public SessionPool sessionListener(SessionPoolListener listener) {
        this.listener = listener;
        return this;
    }

    public SessionPool renewIds() {
        this.renew = true;
        return this;
    }

    public SessionPool idleTimeout(int seconds) {
        this.idleTimeout = seconds;
        return this;
    }

    public SessionPool timeToLive(int seconds) {
        this.timeToLive = seconds;
        return this;
    }

    public int size() {
        return sessions.size();
    }

    public Session load(String id) {
        Session session = sessions.get(id);
        if (session == null || !validate(session)) return null;
        Session data = makeSession(id, session);
        listener.sessionLoaded(id);
        return data;
    }

    public String save(Session data) {
        if (data.invalid()) throw new IllegalStateException("Session invalidated");
        if (shouldRenew(data)) destroy(data.id());

        String sid = sessionId(data);
        Session session = makeSession(sid, data);
        Instant now = now();
        session.updatedAt(now);
        sessions.put(sid, session);
        if (sid.equals(data.id())) {
            listener.sessionSaved(sid);
        } else {
            session.createdAt(now);
            listener.sessionCreated(sid);
        }
        return sid;
    }

    private boolean shouldRenew(Session data) {
        return !data.fresh() && renew;
    }

    public void destroy(String sid) {
        if (sessions.remove(sid) != null) listener.sessionDropped(sid);
    }

    public void clear() {
        sessions.clear();
    }

    public void houseKeeping() {
        sessions.values().stream().filter(session -> !validate(session)).forEach(session -> destroy(session.id()));
    }

    private String sessionId(Session data) {
        return data.fresh() || renew ? policy.generateId(data) : data.id();
    }

    private Session makeSession(String sid, Session data) {
        Session session = new Session(sid);
        session.merge(data);
        session.maxAge(data.maxAge());
        session.updatedAt(data.updatedAt());
        session.createdAt(data.createdAt());
        return session;
    }

    private boolean validate(Session session) {
        if (expired(session) || stale(session) || tooOld(session)) session.invalidate();
        return !session.invalid();
    }

    private boolean expired(Session session) {
        return session.expires() && session.expired(now());
    }

    private boolean stale(Session session) {
        return !session.expires() && idleTimeout > 0 && !now().isBefore(staleTime(session));
    }

    private boolean tooOld(Session session) {
        return timeToLive > 0 && !now().isBefore(endOfLifeTime(session));
    }

    private Instant staleTime(Session session) {
        return session.updatedAt().plusSeconds(idleTimeout);
    }

    private Instant endOfLifeTime(Session session) {
        return session.updatedAt().plusSeconds(timeToLive);
    }

    private Instant now() {
        return clock.instant();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy