/* * Copyright 2013 Simon Taddiken * * This file is part of Polly HTTP API. * * Polly HTTP API is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Polly HTTP API 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * Polly HTTP API. If not, see http://www.gnu.org/licenses/. */ package de.skuzzle.polly.http.internal; import java.util.ArrayDeque; import java.util.Collections; import java.util.Date; import java.util.Deque; import java.util.Map; import de.skuzzle.polly.http.api.HttpEvent; import de.skuzzle.polly.http.api.HttpSession; import de.skuzzle.polly.tools.collections.TemporaryValueMap; class HttpSessionImpl implements HttpSession { // negative means to cache forever private final static long DEFAULT_ELEMENT_CACHE_TIME = -1l; private final static int EVENTS_TO_BUFFER = 20; private final String id; private final long timestamp; private final TemporaryValueMap<String, Object> attached; private final TrafficInformationImpl trafficInfo; private final Deque<HttpEvent> events; private Date lastAction; private boolean doKill; private Date expirationDate; private boolean pending; public HttpSessionImpl(HttpServerImpl server, String id) { this.id = id; this.timestamp = System.currentTimeMillis(); this.attached = new TemporaryValueMap<>(DEFAULT_ELEMENT_CACHE_TIME); this.trafficInfo = server.newTrafficInformation(); this.events = new ArrayDeque<>(); // make sure session is initially unblocked } public void setPending(boolean pending) { this.pending = pending; } public boolean isPending() { return this.pending; } void clearData() { synchronized (this.attached) { this.attached.clear(); } } void setLastAction(Date lastAction) { this.lastAction = lastAction; } @Override public Date getLastActionDate() { return this.lastAction; } /** * Adds an event to this session's event history. If the history grows * bigger than {@link #EVENTS_TO_BUFFER}, the eldest entry will be removed * from the history. * * @param event * Event to remember. */ void addEvent(HttpEvent event) { synchronized (this.events) { this.events.add(event); if (this.events.size() == EVENTS_TO_BUFFER) { this.events.poll(); } } } /** * Determiens whether this session is marked to be killed. * * @return Whether this session should be killed upon next action */ boolean shouldKill() { return this.doKill; } @Override public Deque<HttpEvent> getEvents() { return this.events; } @Override public String getId() { return this.id; } @Override public void setExpirationDate(Date d) { this.expirationDate = d; } @Override public Date getExpirationDate() { return this.expirationDate; } @Override public long getTimestamp() { return this.timestamp; } @Override public void set(String key, Object item) { synchronized (this.attached) { this.attached.put(key, item); } } public void set(String key, Object item, long cacheTime) { synchronized (this.attached) { this.attached.put(key, item, cacheTime); } } @Override public void detach(String key) { synchronized (this.attached) { this.attached.remove(key); } } @Override public boolean isSet(String key) { synchronized (this.attached) { return this.attached.containsKey(key); } } @Override @SuppressWarnings("unchecked") public <T> T get(String key) { synchronized (this.attached) { return (T) this.attached.get(key); } } @Override @SuppressWarnings("unchecked") public <T> T get(String key, T backup) { synchronized (this.attached) { final T result = (T) this.attached.get(key); if (result == null) { return backup; } return result; } } @Override @SuppressWarnings("unchecked") public <T> T getOnce(String key) { synchronized (this.attached) { return (T) this.attached.remove(key); } } @Override public Map<String, Object> getAttached() { return Collections.unmodifiableMap(this.attached); } @Override public TrafficInformationImpl getTrafficInfo() { return this.trafficInfo; } @Override public void kill() { this.doKill = true; } }