SessionManager.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates and open the template
* in the editor.
*/
package it.cnr.iit.ucs.sessionmanager;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.logging.Logger;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.dao.ForeignCollection;
import com.j256.ormlite.jdbc.JdbcConnectionSource;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import it.cnr.iit.ucs.constants.STATUS;
import it.cnr.iit.ucs.properties.components.SessionManagerProperties;
import it.cnr.iit.ucs.sessionmanager.OnGoingAttribute.COLUMN;
import it.cnr.iit.utility.errorhandling.Reject;
import it.cnr.iit.xacml.Attribute;
/**
* Creates, updates, deletes and retrieves Sessions by waiting for Context
* Handler Requests. It exploits OrmLite DAL to manage different relational
* databases.
*
* @author Fabio Bindi and Filippo Lauria and Antonio La Marra and Alessandro Rosetti
*/
public final class SessionManager implements SessionManagerInterface {
private static final Logger log = Logger.getLogger( SessionManager.class.getName() );
private static final String MSG_ERR_SQL = "Error in SQL query : {0}";
// url to connect to the database
private final String databaseURL;
private ConnectionSource connection;
// dao to perform operations on the session table
private Dao<Session, String> sessionDao;
// dao to perform operations on the attributes table
private Dao<OnGoingAttribute, String> attributesDao;
private volatile boolean initialized = false;
protected SessionManager( String databaseURL ) {
this.databaseURL = databaseURL;
sessionDao = null;
attributesDao = null;
}
public SessionManager( SessionManagerProperties properties ) {
Reject.ifNull( properties );
Reject.ifNull( properties.getDbUri() );
databaseURL = properties.getDbUri();
sessionDao = null;
attributesDao = null;
initialized = true;
}
/**
* Starts the connection to the database and creates the tables if not exist
*
* @return true if Session Manager starts properly, false otherwise
*/
@Override
public Boolean start() {
isInitialized();
try {
connection = new JdbcConnectionSource( databaseURL );
sessionDao = DaoManager.createDao( connection, Session.class );
attributesDao = DaoManager.createDao( connection, OnGoingAttribute.class );
TableUtils.createTableIfNotExists( connection, Session.class );
TableUtils.createTableIfNotExists( connection, OnGoingAttribute.class );
} catch( SQLException e ) {
log.severe( e.getMessage() );
initialized = false;
throw new IllegalStateException( "SessionManager not in a valid state anymore" );
}
return true;
}
/**
* Stops the connection to the database
*
* @return true if Session Manager stops properly, false otherwise
*/
@Override
public Boolean stop() {
if( !isInitialized() ) {
throw new IllegalStateException( "SessionManager was not correctly initialized" );
}
try {
connection.close();
} catch( IOException e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
initialized = false;
throw new IllegalStateException( "SessionManager not in a valid state anymore" );
} catch (Exception e) {
throw new RuntimeException(e);
}
return true;
}
/**
* Updates the status of a certain session
*
* @param sessionId
* session ID
* @param status
* new session status
* @return true if the new status is properly updated in th DB row, false
* otherwise
*/
@Override
public Boolean updateEntry( String sessionId, String status ) {
Reject.ifBlank( status );
Reject.ifBlank( sessionId );
try {
Session s = sessionDao.queryForId( sessionId );
s.setStatus( status );
sessionDao.update( s );
} catch( SQLException e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
return false;
}
return true;
}
/**
* Deletes a certain session
*
* @param sessionId
* ID of the session to be deleted in the DB
* @return true if the Session is properly deleted in the DB, false otherwise
*/
@Override
public Boolean deleteEntry( String sessionId ) {
validStateAndArguments( sessionId );
try {
ForeignCollection<OnGoingAttribute> a;
try {
a = sessionDao.queryForId(sessionId)
.getOnGoingAttributesAsForeign();
} catch (NullPointerException e) {
return false;
}
for( OnGoingAttribute attribute : a ) {
attributesDao.deleteById( attribute.getId() );
}
a.clear();
sessionDao.deleteById( sessionId );
} catch( SQLException ex ) {
return false;
}
return true;
}
/**
* Creates an entry for a session. This is the general function, in this case
* the request has ongoingattributes related to the subject, the
* object/resource, the action and the environment
* @param parameterObject
*
* @return true if everything goes fine, false otherwise
*/
@Override
public Boolean createEntry( SessionAttributes parameterObject ) {
Reject.ifNull( parameterObject );
try {
Session s = prepareSession( parameterObject );
if( sessionDao.idExists( parameterObject.getSessionId() ) ) {
log.severe( "ID already exists" );
return false;
}
sessionDao.create( s );
Session sessionResult = sessionDao.queryForId( parameterObject.getSessionId() );
ForeignCollection<OnGoingAttribute> attributes = sessionResult
.getOnGoingAttributesAsForeign();
if( parameterObject.getOnGoingAttributesForSubject() != null ) {
for( String attr : parameterObject.getOnGoingAttributesForSubject() ) {
OnGoingAttribute a = OnGoingAttribute.createOnGoingAttribute( attr, parameterObject.getSubjectName(), COLUMN.SUBJECT );
attributes.add( a );
}
}
if( parameterObject.getOnGoingAttributesForResource() != null ) {
for( String attr : parameterObject.getOnGoingAttributesForResource() ) {
OnGoingAttribute a = OnGoingAttribute.createOnGoingAttribute( attr, parameterObject.getResourceName(),
COLUMN.RESOURCE );
attributes.add( a );
}
}
if( parameterObject.getOnGoingAttributesForAction() != null ) {
for( String attr : parameterObject.getOnGoingAttributesForAction() ) {
OnGoingAttribute a = OnGoingAttribute.createOnGoingAttribute( attr, parameterObject.getActionName(), COLUMN.ACTION );
attributes.add( a );
}
}
if( parameterObject.getOnGoingAttributesForEnvironment() != null ) {
for( String attr : parameterObject.getOnGoingAttributesForEnvironment() ) {
OnGoingAttribute a = OnGoingAttribute.createOnGoingAttribute( attr, "", COLUMN.ENVIRONMENT );
attributes.add( a );
}
}
} catch( SQLException e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
return false;
}
return true;
}
private Session prepareSession( SessionAttributes parameterObject ) {
return new Session( parameterObject.getSessionId(), parameterObject.getPolicySet(), parameterObject.getOriginalRequest(),
parameterObject.getStatus(),
parameterObject.getPepURI(), parameterObject.getMyIP() );
}
/**
* Retrieves the list of sessions interested by that attribute id
*
* @param attributeId
* the attribute id in which sessions are interested
* @return the list of sessions interested in that attribute id
*/
@Override
public List<SessionInterface> getSessionsForAttribute( String attributeId ) {
validStateAndArguments( attributeId );
try {
QueryBuilder<OnGoingAttribute, String> qbAttributes = attributesDao
.queryBuilder();
List<OnGoingAttribute> attributes = qbAttributes.where()
.eq( OnGoingAttribute.ATTRIBUTEID_FIELD, attributeId ).query();
List<SessionInterface> sessions = new LinkedList<>();
for( OnGoingAttribute attr : attributes ) {
// add the considered session only if its status is equal to 's'
if( attr.getSession().isStatus( STATUS.START.name() )
|| attr.getSession().isStatus( STATUS.REVOKE.name() ) ) {
sessions.add( attr.getSession() );
}
}
return sessions;
} catch( SQLException e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
}
return new ArrayList<>();
}
/**
* Retrieves the list of sessions that have that attributeid and that subject
* specified as ongoing attributes. This is done to avoid the retrieval of
* sessions that are interested in a certain attributeid related to different
* subject
*
* @param subjectName
* the name of the subject
* @param attributeId
* the attribute id
* @return the list of sessions interested by the couple
*/
@Override
public List<SessionInterface> getSessionsForSubjectAttributes(
String subjectName, String attributeId ) {
validStateAndArguments( subjectName, attributeId );
try {
QueryBuilder<OnGoingAttribute, String> qbAttributes = attributesDao
.queryBuilder();
List<OnGoingAttribute> attributes = qbAttributes.where()
.isNotNull( OnGoingAttribute.SUBJECTNAME_FIELD ).and()
.isNull( OnGoingAttribute.RESOURCENAME_FIELD ).and()
.isNull( OnGoingAttribute.ACTIONNAME_FIELD ).and()
.eq( OnGoingAttribute.ATTRIBUTEID_FIELD, attributeId ).and()
.eq( OnGoingAttribute.SUBJECTNAME_FIELD, subjectName ).query();
if( attributes == null ) {
return new ArrayList<>();
}
List<SessionInterface> sessions = new LinkedList<>();
for( OnGoingAttribute attr : attributes ) {
// add the considered session only if its status is equal to 's'
if( attr.getSession().isStatus( STATUS.START.name() )
|| attr.getSession().isStatus( STATUS.REVOKE.name() ) ) {
sessions.add( attr.getSession() );
}
}
return sessions;
} catch( SQLException e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
}
return new ArrayList<>();
}
/**
* Retrieves the list of sessions that have that attributeid and that object
* specified as on going attributes. This is done to avoid the retrieval of
* sessions that are interested in a certain attribute id related the a
* different object
*
* @param resourceName
* the name of the object
* @param attributeId
* the attribute id
* @return the list of sessions interested by the couple
*/
@Override
public List<SessionInterface> getSessionsForResourceAttributes(
String resourceName, String attributeId ) {
validStateAndArguments( resourceName, attributeId );
try {
QueryBuilder<OnGoingAttribute, String> qbAttributes = attributesDao
.queryBuilder();
List<OnGoingAttribute> attributes = qbAttributes.where()
.isNull( OnGoingAttribute.SUBJECTNAME_FIELD ).and()
.isNotNull( OnGoingAttribute.RESOURCENAME_FIELD ).and()
.isNull( OnGoingAttribute.ACTIONNAME_FIELD ).and()
.eq( OnGoingAttribute.ATTRIBUTEID_FIELD, attributeId ).and()
.eq( OnGoingAttribute.RESOURCENAME_FIELD, resourceName ).query();
List<SessionInterface> sessions = new LinkedList<>();
for( OnGoingAttribute attr : attributes ) {
if( attr.getSession().isStatus( STATUS.START.name() )
|| attr.getSession().isStatus( STATUS.REVOKE.name() ) ) {
sessions.add( attr.getSession() );
}
}
return sessions;
} catch( SQLException e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
}
return new ArrayList<>();
}
/**
* Retrieves the list of sessions that have that attributeId and that action
* specified as ongoing attributes. This is done to avoid the retrieval of
* sessions that are interested in a certain attribute related to different
* actions.
*
* @param actionName
* the name of the action
* @param attributeId
* the id of the attribute
* @return the list of sessions interested by the couple
*/
@Override
public List<SessionInterface> getSessionsForActionAttributes(
String actionName, String attributeId ) {
validStateAndArguments( actionName, attributeId );
try {
QueryBuilder<OnGoingAttribute, String> qbAttributes = attributesDao
.queryBuilder();
List<OnGoingAttribute> attributes = qbAttributes.where()
.isNull( OnGoingAttribute.SUBJECTNAME_FIELD ).and()
.isNull( OnGoingAttribute.RESOURCENAME_FIELD ).and()
.isNotNull( OnGoingAttribute.ACTIONNAME_FIELD ).and()
.eq( OnGoingAttribute.ATTRIBUTEID_FIELD, attributeId ).and()
.eq( OnGoingAttribute.ACTIONNAME_FIELD, actionName ).query();
List<SessionInterface> sessions = new LinkedList<>();
for( OnGoingAttribute attr : attributes ) {
if( attr.getSession().isStatus( STATUS.START.name() )
|| attr.getSession().isStatus( STATUS.REVOKE.name() ) ) {
sessions.add( attr.getSession() );
}
}
return sessions;
} catch( SQLException e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
}
return new ArrayList<>();
}
/**
* Retrieve the session that is identified by the specified session id
*
* @param sessionId
* the id of the session in which we're interested
* @return the object implementing the Session interface
*/
@Override
public Optional<SessionInterface> getSessionForId( String sessionId ) {
validStateAndArguments( sessionId );
try {
return Optional.ofNullable( sessionDao.queryForId( sessionId ) );
} catch( SQLException e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
return Optional.empty();
}
}
/**
* Retrieves the list of sessions that are sharing the same status
*
* @param status
* the status in which we're interested in
* @return the list of session interface that have that status
*/
@Override
public List<SessionInterface> getSessionsForStatus( String status ) {
validStateAndArguments( status );
try {
QueryBuilder<Session, String> qbSessions = sessionDao.queryBuilder();
List<Session> list = qbSessions.where()
.eq( Session.STATUS_FIELD_NAME, status ).query();
List<SessionInterface> returnList = new ArrayList<>( list.size() );
for( Session session : list ) {
returnList.add( session );
}
return returnList;
} catch( SQLException e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
return new ArrayList<>();
}
}
/**
* Retrieve the list of sessions related to that attributeName
*
* @param attributeId
* attribute name related to the environment in which we're
* interested into
* @return the list of sessions
*/
@Override
public List<SessionInterface> getSessionsForEnvironmentAttributes(
String attributeId ) {
validStateAndArguments( attributeId );
try {
QueryBuilder<OnGoingAttribute, String> qbAttributes = attributesDao
.queryBuilder();
List<OnGoingAttribute> attributes = qbAttributes.where()
.isNull( OnGoingAttribute.SUBJECTNAME_FIELD ).and()
.isNull( OnGoingAttribute.RESOURCENAME_FIELD ).and()
.isNull( OnGoingAttribute.ACTIONNAME_FIELD ).and()
.eq( OnGoingAttribute.ATTRIBUTEID_FIELD, attributeId ).query();
List<SessionInterface> sessions = new LinkedList<>();
for( OnGoingAttribute attr : attributes ) {
// add the considered session only if its status is equal to 's'
if( attr.getSession().isStatus( STATUS.START.name() )
|| attr.getSession().isStatus( STATUS.REVOKE.name() ) ) {
sessions.add( attr.getSession() );
}
}
return sessions;
} catch( SQLException e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
}
return new ArrayList<>();
}
@Override
public List<OnGoingAttributesInterface> getOnGoingAttributes( String sessionId ) {
validStateAndArguments( sessionId );
try {
Session session = sessionDao.queryForId( sessionId );
return session.getOnGoingAttribute();
} catch( Exception e ) {
log.severe( MSG_ERR_SQL + e.getMessage() ) ;
return new ArrayList<>();
}
}
@Override
public REEV_STATUS checkSession( String sessionId, Attribute attribute ) {
return null;
}
@Override
public boolean insertSession( SessionInterface session, Attribute attribute ) {
return false;
}
@Override
public boolean stopSession( SessionInterface session ) {
return false;
}
private void validStateAndArguments( Object... objects ) {
isInitialized();
checkObjectsNotNull( objects );
}
@Override
public boolean isInitialized() {
Reject.ifFalse( initialized, "SessionManager was not correctly initialized" );
return initialized;
}
private boolean checkObjectsNotNull( Object... objects ) {
if( objects == null ) {
return false;
}
for( Object object : objects ) {
if( object == null ) {
return false;
}
if( object instanceof String ) {
Reject.ifBlank( (String) object );
}
}
return true;
}
}