mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-20 04:35:32 +00:00
added persistence support for clearing ReplicatingCacheManager and ReplicatingCache; added session garbage collection upon SecurityService construction
Change-Id: I78475411ef01916678e383922d9d0bd11dfd5aec
This commit is contained in:
+29
@@ -84,4 +84,33 @@ public class SessionPersistenceTest {
|
||||
mof.removeSession(cacheName, session);
|
||||
assertTrue(dof.loadSessionsByCacheName().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionExpiry() throws InterruptedException {
|
||||
final String cacheName = "shiroSessionCache";
|
||||
final String host = "myHost";
|
||||
final String id = UUID.randomUUID().toString();
|
||||
final Date start = new Date();
|
||||
final Date last = new Date();
|
||||
final long timeout = 5000l; // 5s
|
||||
final SimpleSession session = new SimpleSession();
|
||||
session.setId(id);
|
||||
session.setHost(host);
|
||||
session.setStartTimestamp(start);
|
||||
session.setLastAccessTime(last);
|
||||
session.setTimeout(timeout);
|
||||
mof.storeSession(cacheName, session);
|
||||
final Map<String, Set<Session>> sessions = dof.loadSessionsByCacheName();
|
||||
// expecting the session to be still there because the 10s haven't expired yet:
|
||||
final Session readSession = sessions.get(cacheName).iterator().next();
|
||||
assertEquals(session, readSession);
|
||||
assertEquals(id, readSession.getId());
|
||||
assertEquals(host, readSession.getHost());
|
||||
assertEquals(start, readSession.getStartTimestamp());
|
||||
assertEquals(last, readSession.getLastAccessTime());
|
||||
assertEquals(timeout, readSession.getTimeout());
|
||||
Thread.sleep(timeout);
|
||||
final Map<String, Set<Session>> sessionsWithoutExpired = dof.loadSessionsByCacheName();
|
||||
assertTrue(sessionsWithoutExpired.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@ public interface MongoObjectFactory {
|
||||
|
||||
void removeSession(String cacheName, Session session);
|
||||
|
||||
void removeAllSessions();
|
||||
void removeAllSessions(String cacheName);
|
||||
|
||||
}
|
||||
|
||||
+14
-1
@@ -2,8 +2,10 @@ package com.sap.sse.security.persistence.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.session.mgt.SimpleSession;
|
||||
@@ -13,9 +15,12 @@ import org.bson.Document;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsDurationImpl;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.security.persistence.DomainObjectFactory;
|
||||
|
||||
public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName());
|
||||
private final MongoCollection<Document> sessionsCollection;
|
||||
|
||||
public DomainObjectFactoryImpl(MongoDatabase mongoDatabase) {
|
||||
@@ -25,11 +30,19 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
@Override
|
||||
public Map<String, Set<Session>> loadSessionsByCacheName() {
|
||||
final Map<String, Set<Session>> sessionsByCacheName = new HashMap<>();
|
||||
final Set<Serializable> expiredSessionIds = new HashSet<>();
|
||||
sessionsCollection.find().forEach((Document sessionDocument)->{
|
||||
final String cacheName = sessionDocument.getString(FieldNames.CACHE_NAME.name());
|
||||
final Session session = loadSession(sessionDocument);
|
||||
Util.addToValueSet(sessionsByCacheName, cacheName, session);
|
||||
if (new MillisecondsTimePoint(session.getLastAccessTime()).plus(new MillisecondsDurationImpl(session.getTimeout())).before(MillisecondsTimePoint.now())) {
|
||||
// expired
|
||||
logger.info("Session "+session+" expired");
|
||||
expiredSessionIds.add(session.getId());
|
||||
} else {
|
||||
Util.addToValueSet(sessionsByCacheName, cacheName, session);
|
||||
}
|
||||
});
|
||||
expiredSessionIds.forEach(id->sessionsCollection.deleteOne(new Document(FieldNames.SESSION_ID.name(), id)));
|
||||
return sessionsByCacheName;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -82,8 +82,8 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllSessions() {
|
||||
sessionCollection.deleteMany(new Document());
|
||||
public void removeAllSessions(String cacheName) {
|
||||
sessionCollection.deleteMany(new Document(FieldNames.CACHE_NAME.name(), cacheName));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -49,6 +49,6 @@ public interface ReplicableSecurityService extends SecurityService {
|
||||
|
||||
void removeSession(String cacheName, Session result);
|
||||
|
||||
void removeAllSessions();
|
||||
void removeAllSessions(String cacheName);
|
||||
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class ReplicatingCache<K, V> implements Cache<K, V>, Named {
|
||||
securityService.replicate(s->{
|
||||
s.getCacheManager().getCache(myName).clear(); return null;
|
||||
});
|
||||
securityService.removeAllSessions();
|
||||
securityService.removeAllSessions(getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+12
-6
@@ -1,6 +1,7 @@
|
||||
package com.sap.sse.security.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@@ -56,14 +57,14 @@ public class ReplicatingCacheManager implements CacheManager, Serializable {
|
||||
if (castCache == null) {
|
||||
this.caches.put(name, otherCache);
|
||||
} else {
|
||||
putAll(castCache, otherCache);
|
||||
putAll(otherCache, castCache);
|
||||
}
|
||||
}
|
||||
|
||||
private <K, V> void putAll(final ReplicatingCache<K, V> from, ReplicatingCache<K, V> into) {
|
||||
from.clear();
|
||||
for (K k:into.keys()) {
|
||||
from.put(k, into.get(k));
|
||||
private <K, V> void putAll(ReplicatingCache<K, V> from, final ReplicatingCache<K, V> to) {
|
||||
to.clear();
|
||||
for (K k : from.keys()) {
|
||||
to.put(k, from.get(k));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +72,11 @@ public class ReplicatingCacheManager implements CacheManager, Serializable {
|
||||
* For test purposes; clears all state held by this cache manager.
|
||||
*/
|
||||
public void clear() {
|
||||
this.caches.clear();
|
||||
final ReplicableSecurityService securityService = (ReplicableSecurityService) Activator.getSecurityService();
|
||||
for (final Iterator<Entry<String, ReplicatingCache<?, ?>>> i=caches.entrySet().iterator(); i.hasNext(); ) {
|
||||
final Entry<String, ReplicatingCache<?, ?>> cacheNameAndCache = i.next();
|
||||
securityService.removeAllSessions(cacheNameAndCache.getKey());
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1132,7 +1132,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllSessions() {
|
||||
PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().removeAllSessions();
|
||||
public void removeAllSessions(String cacheName) {
|
||||
PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().removeAllSessions(cacheName);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user