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

org.jgrapes.http.InMemorySessionManager Maven / Gradle / Ivy

The newest version!
/*
 * JGrapes Event Driven Framework
 * Copyright (C) 2017-2018 Michael N. Lipp
 * 
 * This program is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Affero General Public License as published by 
 * the Free Software Foundation; either version 3 of the License, or 
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
 * for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License along 
 * with this program; if not, see .
 */

package org.jgrapes.http;

import java.time.Duration;
import java.time.Instant;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import org.jgrapes.core.Channel;
import org.jgrapes.http.events.DiscardSession;
import org.jgrapes.http.events.Request;

/**
 * A in memory session manager. 
 */
@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
public class InMemorySessionManager extends SessionManager {

    @SuppressWarnings({ "serial", "PMD.UseConcurrentHashMap" })
    private final Map sessionsById
        = new LinkedHashMap<>(16, 0.75f, true) {

            @Override
            protected boolean
                    removeEldestEntry(Entry eldest) {
                if (maxSessions() > 0 && size() > maxSessions()
                    && eldest.getValue().setBeingDiscarded()) {
                    fire(new DiscardSession(eldest.getValue()));
                }
                return false;
            }
        };

    /**
     * Creates a new session manager with its channel set to
     * itself and the path set to "/". The manager handles
     * all {@link Request} events.
     */
    public InMemorySessionManager() {
        this("/");
    }

    /**
     * Creates a new session manager with its channel set to
     * itself and the path set to the given path. The manager
     * handles all requests that match the given path, using the
     * same rules as browsers do for selecting the cookies that
     * are to be sent.
     * 
     * @param path the path
     */
    public InMemorySessionManager(String path) {
        this(Channel.SELF, path);
    }

    /**
     * Creates a new session manager with its channel set to
     * the given channel, the path to "/" and the handler's priority 
     * to 1000. The manager handles all {@link Request} events.
     * 
     * @param componentChannel the component channel
     */
    public InMemorySessionManager(Channel componentChannel) {
        this(componentChannel, "/");
    }

    /**
     * Creates a new session manager with the given channel and path.
     * The manager handles all requests that match the given path, using
     * the same rules as browsers do for selecting the cookies that
     * are to be sent. The request handler's priority is set to 1000.
     *  
     * @param componentChannel the component channel
     * @param path the path
     */
    public InMemorySessionManager(Channel componentChannel, String path) {
        this(componentChannel, derivePattern(path), 1000, path);
    }

    /**
     * Creates a new session manager using the given channel and path.
     * The manager handles only requests that match the given pattern.
     * The {@link Request} handler is registered with the given priority.
     * 
     * This constructor can be used if special handling of top level
     * requests is needed.
     *
     * @param componentChannel the component channel
     * @param pattern the path part of a {@link ResourcePattern}
     * @param priority the priority
     * @param path the path
     */
    public InMemorySessionManager(Channel componentChannel, String pattern,
            int priority, String path) {
        super(componentChannel, pattern, priority, path);
    }

    @Override
    @SuppressWarnings({ "PMD.CognitiveComplexity",
        "PMD.AvoidInstantiatingObjectsInLoops" })
    protected Optional startDiscarding(long absoluteTimeout,
            long idleTimeout) {
        synchronized (this) {
            Instant nextTimout = null;
            for (InMemorySession session : sessionsById.values()) {
                if (hasTimedOut(session)) {
                    if (session.setBeingDiscarded()) {
                        fire(new DiscardSession(session));
                    }
                    continue;
                }
                if (absoluteTimeout > 0) {
                    Instant timesOutAt = session.createdAt()
                        .plus(Duration.ofMillis(absoluteTimeout));
                    if (nextTimout == null
                        || timesOutAt.isBefore(nextTimout)) {
                        nextTimout = timesOutAt;
                    }
                }
                if (idleTimeout > 0) {
                    Instant timesOutAt = session.lastUsedAt()
                        .plus(Duration.ofMillis(idleTimeout));
                    if (nextTimout == null
                        || timesOutAt.isBefore(nextTimout)) {
                        nextTimout = timesOutAt;
                    }
                }
            }
            return Optional.ofNullable(nextTimout);
        }
    }

    @Override
    protected Session createSession(String sessionId) {
        InMemorySession session = new InMemorySession(sessionId);
        synchronized (this) {
            sessionsById.put(sessionId, session);
        }
        return session;
    }

    @Override
    protected Optional lookupSession(String sessionId) {
        synchronized (this) {
            return Optional.ofNullable(sessionsById.get(sessionId));
        }
    }

    @Override
    protected void removeSession(String sessionId) {
        synchronized (this) {
            sessionsById.remove(sessionId);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.jgrapes.http.SessionManager#sessionCount()
     */
    @Override
    protected int sessionCount() {
        synchronized (this) {
            return sessionsById.size();
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy