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        InMemorySession other = (InMemorySession) obj;
131        if (id == null) {
132            if (other.id != null) {
133                return false;
134            }
135        } else if (!id.equals(other.id)) {
136            return false;
137        }
138        return true;
139    }
140
141    /*
142     * (non-Javadoc)
143     * 
144     * @see java.lang.Object#toString()
145     */
146    @Override
147    public String toString() {
148        StringBuilder builder = new StringBuilder(50);
149        builder.append("InMemorySession [");
150        if (id != null) {
151            builder.append("id=");
152            builder.append(id);
153            builder.append(", ");
154        }
155        if (createdAt != null) {
156            builder.append("createdAt=");
157            builder.append(createdAt);
158            builder.append(", ");
159        }
160        if (lastUsedAt != null) {
161            builder.append("lastUsedAt=");
162            builder.append(lastUsedAt);
163        }
164        builder.append(']');
165        return builder.toString();
166    }
167
168}