/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* This copy of Woodstox XML processor is licensed under the
* Apache (Software) License, version 2.0 ("the License").
* See the License for details about distribution rights, and the
* specific rights regarding derivate works.
*
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/
*
* A copy is also included in the downloadable source code package
* containing Woodstox, in file "ASL2.0", under the same directory
* as this file.
*/
package org.jooby.internal;
import static java.util.Objects.requireNonNull;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.jooby.Mutant;
import org.jooby.Session;
import org.jooby.internal.parser.ParserExecutor;
import com.google.common.collect.ImmutableList;
public class SessionImpl implements Session {
static class Builder implements Session.Builder {
private SessionImpl session;
public Builder(final ParserExecutor resolver, final boolean isNew, final String sessionId,
final long timeout) {
this.session = new SessionImpl(resolver, isNew, sessionId, timeout);
}
@Override
public String sessionId() {
return session.sessionId;
}
@Override
public org.jooby.Session.Builder set(final String name, final String value) {
session.attributes.put(name, value);
return this;
}
@Override
public Session.Builder set(final Map<String, String> attributes) {
session.attributes.putAll(attributes);
return this;
}
@Override
public Session.Builder createdAt(final long createdAt) {
session.createdAt = createdAt;
return this;
}
@Override
public Session.Builder accessedAt(final long accessedAt) {
session.accessedAt = accessedAt;
return this;
}
@Override
public Session.Builder savedAt(final long savedAt) {
session.savedAt = savedAt;
return this;
}
@Override
public Session build() {
requireNonNull(session.sessionId, "Session's id wasn't set.");
return session;
}
}
private ConcurrentMap<String, String> attributes = new ConcurrentHashMap<>();
private String sessionId;
private long createdAt;
private volatile long accessedAt;
private volatile long timeout;
private volatile boolean isNew;
private volatile boolean dirty;
private volatile long savedAt;
private ParserExecutor resolver;
public SessionImpl(final ParserExecutor resolver, final boolean isNew, final String sessionId,
final long timeout) {
this.resolver = resolver;
this.isNew = isNew;
this.sessionId = sessionId;
long now = COOKIE_SESSION.equals(sessionId) ? -1 : System.currentTimeMillis();
this.createdAt = now;
this.accessedAt = now;
this.savedAt = -1;
this.timeout = timeout;
}
@Override
public String id() {
return sessionId;
}
@Override
public long createdAt() {
return createdAt;
}
@Override
public long accessedAt() {
return accessedAt;
}
@Override
public long expiryAt() {
if (timeout <= 0) {
return -1;
}
return accessedAt + timeout;
}
@Override
public Mutant get(final String name) {
String value = attributes.get(name);
List<String> values = value == null ? Collections.emptyList() : ImmutableList.of(value);
return new MutantImpl(resolver, new StrParamReferenceImpl("session attribute", name, values));
}
@Override
public boolean isSet(final String name) {
return attributes.containsKey(name);
}
@Override
public Map<String, String> attributes() {
return Collections.unmodifiableMap(attributes);
}
@Override
public Session set(final String name, final String value) {
requireNonNull(name, "An attribute name is required.");
requireNonNull(value, "An attribute value is required.");
String existing = attributes.put(name, value);
dirty = existing == null || !existing.equals(value);
return this;
}
@Override
public Mutant unset(final String name) {
String value = attributes.remove(name);
List<String> values = Collections.emptyList();
if (value != null) {
values = ImmutableList.of(value);
dirty = true;
}
return new MutantImpl(resolver, new StrParamReferenceImpl("session attribute", name, values));
}
@Override
public Session unset() {
attributes.clear();
dirty = true;
return this;
}
@Override
public void destroy() {
unset();
}
public boolean isNew() {
return isNew;
}
public boolean isDirty() {
return dirty;
}
@Override
public long savedAt() {
return savedAt;
}
void markAsSaved() {
isNew = false;
dirty = false;
}
public void touch() {
this.accessedAt = System.currentTimeMillis();
}
@Override
public String toString() {
return sessionId;
}
public void aboutToSave() {
savedAt = System.currentTimeMillis();
}
}