/*
* ============LICENSE_START==========================================
* ONAP Portal SDK
* ===================================================================
* Copyright © 2017 AT&T Intellectual Property. All rights reserved.
* ===================================================================
*
* Unless otherwise specified, all software contained herein is licensed
* under the Apache License, Version 2.0 (the "License");
* you may not use this software 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.
*
* Unless otherwise specified, all documentation contained herein is licensed
* under the Creative Commons License, Attribution 4.0 Intl. (the "License");
* you may not use this documentation except in compliance with the License.
* You may obtain a copy of the License at
*
* https://creativecommons.org/licenses/by/4.0/
*
* Unless required by applicable law or agreed to in writing, documentation
* 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.
*
* ============LICENSE_END============================================
*
* ECOMP is a trademark and service mark of AT&T Intellectual Property.
*/
/*
* Copyright 2014-2017 the original author or authors.
*
* Licensed 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.
*/
package org.onap.portalapp.music.conf;
import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.onap.music.eelf.logging.EELFLoggerDelegate;
import org.onap.music.exceptions.MusicLockingException;
import org.onap.music.exceptions.MusicServiceException;
import org.onap.portalapp.music.service.MusicService;
import org.onap.portalapp.music.util.MusicProperties;
import org.onap.portalapp.music.util.MusicUtil;
import org.springframework.session.MapSession;
import org.springframework.session.Session;
/**
*
* A {@link Session} implementation that is backed by a {@link java.util.Map}. The
* defaults for the properties are:
*
*
* - id - a secure random generated id
* - creationTime - the moment the {@link MapSession} was instantiated
* - lastAccessedTime - the moment the {@link MapSession} was instantiated
* - maxInactiveInterval - 30 minutes
*
*
*
* This implementation has no synchronization, so it is best to use the copy constructor
* when working on multiple threads.
*
*
* @author SRIDHAR REDDY M
* @since 1.0
*/
public final class MusicSession implements Session, Serializable {
/**
* Default {@link #setMaxInactiveInterval(Duration)} (30 minutes).
*/
public static final int DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS = MusicProperties.getProperty(MusicProperties.SESSION_MAX_INACTIVE_INTERVAL_SECONDS)==null ? 1800 :Integer.valueOf(MusicProperties.getProperty(MusicProperties.SESSION_MAX_INACTIVE_INTERVAL_SECONDS)) ;
private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicSession.class);
private String id;
private String originalId;
private Map sessionAttrs = new HashMap<>();
private Instant creationTime = Instant.now();
private Instant lastAccessedTime = this.creationTime;
private Map cachingMap = new HashMap<>();
private boolean musicCache = MusicUtil.isCached();
/**
* Defaults to 30 minutes.
*/
private Duration maxInactiveInterval = Duration.ofSeconds(DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
/**
* Creates a new instance with a secure randomly generated identifier.
*/
public MusicSession() {
this(generateId());
}
/**
* Creates a new instance with the specified id. This is preferred to the default
* constructor when the id is known to prevent unnecessary consumption on entropy
* which can be slow.
*
* @param id the identifier to use
*/
public MusicSession(String id) {
this.id = id;
this.originalId = id;
}
/**
* Creates a new instance from the provided {@link Session}.
*
* @param session the {@link Session} to initialize this {@link Session} with. Cannot
* be null.
*/
public MusicSession(Session session) {
if (session == null) {
throw new IllegalArgumentException("session cannot be null");
}
this.id = session.getId();
this.originalId = this.id;
this.sessionAttrs = new HashMap<>(
session.getAttributeNames().size());
for (String attrName : session.getAttributeNames()) {
Object attrValue = session.getAttribute(attrName);
if (attrValue != null) {
this.sessionAttrs.put(attrName, attrValue);
}
}
this.creationTime = session.getCreationTime();
this.lastAccessedTime = session.getLastAccessedTime();
this.maxInactiveInterval = session.getMaxInactiveInterval();
}
@Override
public void setLastAccessedTime(Instant lastAccessedTime) {
logger.debug(EELFLoggerDelegate.debugLogger, "setLastAccessedTime: start");
try{
MusicService.setAttribute(MusicProperties.LAST_ACCESS_TIME, this.lastAccessedTime, this.id);
}catch(Exception e){
logger.error(EELFLoggerDelegate.errorLogger, "setLastAccessedTime failed with id " + this.id, e);
}
this.lastAccessedTime = lastAccessedTime;
}
@Override
public Instant getCreationTime() {
Instant creationTime = null;
logger.debug(EELFLoggerDelegate.debugLogger, "getCreationTime: start");
if(musicCache)
creationTime = this.creationTime;
else{
try {
String creationTimeStr = MusicService.getAttribute( MusicProperties.CREATION_TIME, this.id);
if(creationTimeStr!=null)
creationTime = Instant.parse(creationTimeStr);
else
creationTime = Instant.now();
} catch (Exception e) {
logger.error(EELFLoggerDelegate.errorLogger, "getCreationTime failed with id " + this.id, e);
}
}
return creationTime;
}
@Override
public String getId() {
return this.id;
}
String getOriginalId() {
return this.originalId;
}
void setOriginalId(String originalId) {
this.originalId = originalId;
}
@Override
public String changeSessionId() {
String changedId = generateId();
setId(changedId);
return changedId;
}
@Override
public Instant getLastAccessedTime() {
Instant lastAccessedTime = null;
logger.debug(EELFLoggerDelegate.debugLogger, "getLastAccessedTime: start");
if(musicCache)
lastAccessedTime = this.lastAccessedTime;
else{
try {
String lastAccessedTimeStr = MusicService.getAttribute( MusicProperties.LAST_ACCESS_TIME, this.id);
if(lastAccessedTimeStr!=null)
lastAccessedTime = Instant.parse(lastAccessedTimeStr);
else
lastAccessedTime = this.creationTime;
} catch (Exception e) {
logger.error(EELFLoggerDelegate.errorLogger, "getLastAccessedTime failed with id "+this.id, e);
}
}
return lastAccessedTime;
}
@Override
public void setMaxInactiveInterval(Duration interval) {
logger.debug(EELFLoggerDelegate.debugLogger, "setMaxInactiveInterval: start");
this.maxInactiveInterval = interval;
try{
MusicService.setAttribute(MusicProperties.MAX_INACTIVE_INTERVAL, this.maxInactiveInterval, this.id);
}catch(Exception e){
logger.error(EELFLoggerDelegate.errorLogger, "setMaxInactiveInterval failed with id " + this.id, e);
}
}
@Override
public Duration getMaxInactiveInterval() {
logger.debug(EELFLoggerDelegate.debugLogger, "getMaxInactiveInterval: start");
Duration maxInactiveInterval = null;
if(musicCache)
maxInactiveInterval = this.maxInactiveInterval;
else{
try {
String maxInactiveIntervalStr = MusicService.getAttribute( MusicProperties.MAX_INACTIVE_INTERVAL, this.id);
if(maxInactiveIntervalStr!=null)
maxInactiveInterval = Duration.parse(maxInactiveIntervalStr);
else
maxInactiveInterval = Duration.ofSeconds(DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
} catch (Exception e) {
logger.error(EELFLoggerDelegate.errorLogger, "getMaxInactiveInterval failed with id " + this.id, e);
}
}
return maxInactiveInterval==null? Duration.ofSeconds(DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS):maxInactiveInterval;
}
@Override
public boolean isExpired() {
return isExpired(Instant.now());
}
boolean isExpired(Instant now) {
logger.debug(EELFLoggerDelegate.debugLogger, "isExpired: start");
boolean isExpired = false;
Duration maxInactiveInterval = null;
Instant lastAccessedTime = null;
try {
if(musicCache){
maxInactiveInterval = this.maxInactiveInterval;
lastAccessedTime = this.lastAccessedTime;
}else{
maxInactiveInterval = getMaxInactiveInterval();
lastAccessedTime = getLastAccessedTime();
}
if (maxInactiveInterval.isNegative()) {
return false;
}
isExpired = now.minus(maxInactiveInterval).compareTo(lastAccessedTime) >= 0;
if(isExpired){
MusicService.removeSession(this.id);
}
} catch (MusicLockingException e) {
logger.error(EELFLoggerDelegate.errorLogger, "isExpired locking failed with id:" + id, e);
} catch (MusicServiceException e) {
logger.error(EELFLoggerDelegate.errorLogger, "isExpired failed with id:" + id, e);
}
return isExpired;
}
@Override
@SuppressWarnings("unchecked")
public T getAttribute(String attributeName) {
if(musicCache){
return (T) this.sessionAttrs.get(attributeName);
}else{
try {
return MusicService.getAttribute( attributeName, this.id);
} catch (Exception e) {
logger.error(EELFLoggerDelegate.errorLogger, " getAttribute failed with id:" + this.id + " attribute name "+ attributeName , e);
return null;
}
}
}
@Override
public Set getAttributeNames() {
return this.sessionAttrs.keySet();
}
@Override
public void setAttribute(String attributeName, Object attributeValue) {
if (attributeValue == null) {
removeAttribute(attributeName);
}else {
this.sessionAttrs.put(attributeName, attributeValue);
try{
MusicService.setAttribute(attributeName , attributeValue, this.id);
}catch(Exception e){
logger.error(EELFLoggerDelegate.errorLogger, " setAttribute failed id:" + this.id + " attribute name "+ attributeName , e);
}
}
}
@Override
public void removeAttribute(String attributeName) {
this.sessionAttrs.remove(attributeName);
try{
MusicService.removeAttribute(attributeName, this.id);
}catch(MusicLockingException e){
logger.error(EELFLoggerDelegate.errorLogger, " removeAttribute locking failed id:" + this.id + " attribute name "+ attributeName , e);
}catch(MusicServiceException e){
logger.error(EELFLoggerDelegate.errorLogger, " removeAttribute failed id:" + this.id + " attribute name "+ attributeName , e);
}
}
/**
* Sets the time that this {@link Session} was created. The default is when the
* {@link Session} was instantiated.
* @param creationTime the time that this {@link Session} was created.
*/
public void setCreationTime(Instant creationTime) {
//MusicService musicService = new MusicService();
this.creationTime = creationTime;
try{
MusicService.setAttribute(MusicProperties.CREATION_TIME, creationTime, this.id);
}catch(Exception e){
logger.error(EELFLoggerDelegate.errorLogger, " setCreationTime failed id:" + this.id + " creationTime "+ creationTime , e);
}
}
/**
* Sets the identifier for this {@link Session}. The id should be a secure random
* generated value to prevent malicious users from guessing this value. The default is
* a secure random generated identifier.
*
* @param id the identifier for this session.
*/
public void setId(String id) {
this.id = id;
}
@Override
public boolean equals(Object obj) {
return obj instanceof Session && this.id.equals(((Session) obj).getId());
}
@Override
public int hashCode() {
return this.id.hashCode();
}
private static String generateId() {
return UUID.randomUUID().toString();
}
private static final long serialVersionUID = 7160779239673823561L;
}