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

com.github.lontime.extpac4j.impl.LocalSimpleJEESessionStore Maven / Gradle / Ivy

The newest version!
package com.github.lontime.extpac4j.impl;

import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.github.lontime.base.logging.GLogger;
import com.github.lontime.shaded.com.github.benmanes.caffeine.cache.Cache;
import com.github.lontime.shaded.com.github.benmanes.caffeine.cache.Caffeine;
import org.pac4j.core.context.JEEContext;
import org.pac4j.core.context.session.JEESessionStore;
import org.pac4j.core.context.session.SessionStore;

/**
 * LocalJEESessionStore.
 * @author lontime
 * @since 1.0
 */
public class LocalSimpleJEESessionStore implements SessionStore {

    public static final LocalSimpleJEESessionStore INSTANCE = new LocalSimpleJEESessionStore();

    private static final int MAP_SIZE = 16;

    protected JEESessionStore delegate;

    protected Cache> cache;

    public LocalSimpleJEESessionStore() {
        this.delegate = new JEESessionStore();
        this.cache = Caffeine.newBuilder().expireAfterAccess(Duration.ofMinutes(5)).build();
    }

    protected boolean check(JEEContext context) {
        return false;
    }

    @Override
    public String getOrCreateSessionId(JEEContext context) {
        return delegate.getOrCreateSessionId(context);
    }

    @Override
    public Optional get(JEEContext context, String key) {
        if (check(context)) {
            return Optional.empty();
        }
        final String id = getSessionId(context);
        final Map map = cache.getIfPresent(id);
        if (map != null && map.containsKey(key)) {
            return Optional.of(map.get(key));
        }
        final Optional optional = delegate.get(context, key);
        if (optional.isPresent()) {
            cache.get(getSessionId(context), k -> new HashMap<>(MAP_SIZE)).put(key, optional.get());
            return optional;
        }
        return Optional.empty();
    }

    @Override
    public void set(JEEContext context, String key, Object value) {
        if (check(context)) {
            return;
        }
        delegate.set(context, key, value);
        cache.get(getSessionId(context), k -> new HashMap<>(MAP_SIZE)).put(key, value);
    }

    @Override
    public boolean destroySession(JEEContext context) {
        if (check(context)) {
            return true;
        }
        final String id = getSessionId(context);
        if (delegate.destroySession(context)) {
            cache.invalidate(id);
            cleanup(id);
            return true;
        }
        return false;
    }

    @Override
    public Optional getTrackableSession(JEEContext context) {
        if (check(context)) {
            return Optional.empty();
        }
        return delegate.getTrackableSession(context);
    }

    @Override
    public Optional> buildFromTrackableSession(JEEContext context, Object trackableSession) {
        if (check(context)) {
            return Optional.empty();
        }
        return delegate.buildFromTrackableSession(context, trackableSession);
    }

    @Override
    public boolean renewSession(JEEContext context) {
        if (check(context)) {
            return false;
        }
        final HttpServletRequest request = context.getNativeRequest();
        final HttpSession session = request.getSession();
        GLogger.defaults().debugv("Discard old session: {0}", session.getId());
        final Map attributes = Collections.list(session.getAttributeNames())
                .stream()
                .collect(Collectors.toMap(k -> k, session::getAttribute, (a, b) -> b));
        session.invalidate();
        final HttpSession newSession = request.getSession(true);
        GLogger.defaults().debugv("And copy all data to the new one: {0}", newSession.getId());
        attributes.forEach((k, v) -> newSession.setAttribute(k, v));

        cache.invalidate(session.getId());
        cache.get(newSession.getId(), k -> new HashMap<>(MAP_SIZE)).putAll(attributes);
        return true;
    }

    protected String getSessionId(JEEContext context) {
        final HttpServletRequest request = context.getNativeRequest();
        final HttpSession session = request.getSession();
        return session.getId();
    }

    protected void cleanup(String id) {

    }

}