001/*
002 * JGrapes Event Driven Framework
003 * Copyright (C) 2017-2018 Michael N. Lipp
004 * 
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero General Public License as published by 
007 * the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 * 
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 * 
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jgrapes.http;
020
021import java.io.Serializable;
022import java.time.Instant;
023import java.util.Map;
024import java.util.concurrent.ConcurrentHashMap;
025
026/**
027 * Implements the {@link Session} interface using a {@link ConcurrentHashMap}.
028 */
029@SuppressWarnings("serial")
030public class InMemorySession
031        extends ConcurrentHashMap<Serializable, Serializable>
032        implements Session {
033
034    @SuppressWarnings("PMD.ShortVariable")
035    private final String id;
036    private final Instant createdAt;
037    private Instant lastUsedAt;
038    private final Map<Object, Object> transientData = new ConcurrentHashMap<>();
039    private boolean beingDiscarded;
040
041    /**
042     * Create a new session.
043     */
044    @SuppressWarnings("PMD.ShortVariable")
045    public InMemorySession(String id) {
046        this.id = id;
047        createdAt = Instant.now();
048        lastUsedAt = createdAt;
049    }
050
051    /**
052     * Returns the session id.
053     * 
054     * @return the id
055     */
056    @SuppressWarnings("PMD.ShortMethodName")
057    public String id() {
058        return id;
059    }
060
061    /**
062     * Returns the creation time stamp.
063     * 
064     * @return the creation time stamp
065     */
066    public Instant createdAt() {
067        return createdAt;
068    }
069
070    /**
071     * Returns the last used (referenced in request) time stamp. 
072     * 
073     * @return the last used timestamp
074     */
075    public Instant lastUsedAt() {
076        return lastUsedAt;
077    }
078
079    /**
080     * Updates the last used time stamp.
081     */
082    public void updateLastUsedAt() {
083        this.lastUsedAt = Instant.now();
084    }
085
086    /*
087     * (non-Javadoc)
088     * 
089     * @see org.jgrapes.http.Session#transientData()
090     */
091    @Override
092    public Map<Object, Object> transientData() {
093        return transientData;
094    }
095
096    /*
097     * (non-Javadoc)
098     * 
099     * @see java.lang.Object#hashCode()
100     */
101    @Override
102    public int hashCode() {
103        return id.hashCode();
104    }
105
106    /**
107     * Marks the session as to be removed.
108     *
109     * @return false, if called before (session is already being discarded)
110     */
111    public boolean setBeingDiscarded() {
112        boolean result = !beingDiscarded;
113        beingDiscarded = true;
114        return result;
115    }
116
117    /*
118     * (non-Javadoc)
119     * 
120     * @see java.lang.Object#equals(java.lang.Object)
121     */
122    @Override
123    public boolean equals(Object obj) {
124        if (obj == null) {
125            return false;
126        }
127        if (getClass() != obj.getClass()) {
128            return false;
129        }
130        @SuppressWarnings("PMD.LooseCoupling")
131        InMemorySession other = (InMemorySession) obj;
132        if (id == null) {
133            if (other.id != null) {
134                return false;
135            }
136        } else if (!id.equals(other.id)) {
137            return false;
138        }
139        return true;
140    }
141
142    /*
143     * (non-Javadoc)
144     * 
145     * @see java.lang.Object#toString()
146     */
147    @Override
148    public String toString() {
149        StringBuilder builder = new StringBuilder(50);
150        builder.append("InMemorySession [");
151        if (id != null) {
152            builder.append("id=").append(id).append(", ");
153        }
154        if (createdAt != null) {
155            builder.append("createdAt=").append(createdAt).append(", ");
156        }
157        if (lastUsedAt != null) {
158            builder.append("lastUsedAt=").append(lastUsedAt);
159        }
160        builder.append(']');
161        return builder.toString();
162    }
163
164}