SEC-484: fixed concurrency issue

This commit is contained in:
Vishal Puri 2007-07-23 07:58:31 +00:00
parent e70f01c260
commit 5ea8232f84
2 changed files with 203 additions and 178 deletions

View File

@ -34,7 +34,6 @@ import java.util.Set;
import javax.servlet.http.HttpSession;
/**
* Base implementation of {@link org.acegisecurity.concurrent.SessionRegistry}
* which also listens for {@link
@ -49,16 +48,19 @@ import javax.servlet.http.HttpSession;
* </p>
*
* @author Ben Alex
* @version $Id${date}
* @version $Id: SessionRegistryImpl.java 1862 2007-05-25 01:38:42Z benalex
* ${date}
*/
public class SessionRegistryImpl implements SessionRegistry,
ApplicationListener {
//~ Instance fields ========================================================
// ~ Instance fields
// ========================================================
private Map principals = Collections.synchronizedMap(new HashMap()); // <principal:Object,SessionIdSet>
private Map sessionIds = Collections.synchronizedMap(new HashMap()); // <sessionId:Object,SessionInformation>
//~ Methods ================================================================
// ~ Methods
// ================================================================
public Object[] getAllPrincipals() {
return principals.keySet().toArray();
@ -67,16 +69,15 @@ public class SessionRegistryImpl implements SessionRegistry,
public SessionInformation[] getAllSessions(Object principal,
boolean includeExpiredSessions) {
Set sessionsUsedByPrincipal = (Set) principals.get(principal);
if (sessionsUsedByPrincipal == null) {
return null;
}
List list = new ArrayList();
Iterator iter = sessionsUsedByPrincipal.iterator();
while (iter.hasNext()) {
synchronized (sessionsUsedByPrincipal) {
for (Iterator iter = sessionsUsedByPrincipal.iterator(); iter
.hasNext();) {
String sessionId = (String) iter.next();
SessionInformation sessionInformation = getSessionInformation(sessionId);
@ -90,7 +91,8 @@ public class SessionRegistryImpl implements SessionRegistry,
}
public SessionInformation getSessionInformation(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
Assert.hasText(sessionId,
"SessionId required as per interface contract");
return (SessionInformation) sessionIds.get(sessionId);
}
@ -103,7 +105,8 @@ public class SessionRegistryImpl implements SessionRegistry,
}
public void refreshLastRequest(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
Assert.hasText(sessionId,
"SessionId required as per interface contract");
SessionInformation info = getSessionInformation(sessionId);
@ -112,21 +115,25 @@ public class SessionRegistryImpl implements SessionRegistry,
}
}
public synchronized void registerNewSession(String sessionId, Object principal) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
Assert.notNull(principal, "Principal required as per interface contract");
public synchronized void registerNewSession(String sessionId,
Object principal) {
Assert.hasText(sessionId,
"SessionId required as per interface contract");
Assert.notNull(principal,
"Principal required as per interface contract");
if (getSessionInformation(sessionId) != null) {
removeSessionInformation(sessionId);
}
sessionIds.put(sessionId,
new SessionInformation(principal, sessionId, new Date()));
sessionIds.put(sessionId, new SessionInformation(principal, sessionId,
new Date()));
Set sessionsUsedByPrincipal = (Set) principals.get(principal);
if (sessionsUsedByPrincipal == null) {
sessionsUsedByPrincipal = Collections.synchronizedSet(new HashSet());
sessionsUsedByPrincipal = Collections
.synchronizedSet(new HashSet());
}
sessionsUsedByPrincipal.add(sessionId);
@ -135,14 +142,16 @@ public class SessionRegistryImpl implements SessionRegistry,
}
public void removeSessionInformation(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
Assert.hasText(sessionId,
"SessionId required as per interface contract");
SessionInformation info = getSessionInformation(sessionId);
if (info != null) {
sessionIds.remove(sessionId);
Set sessionsUsedByPrincipal = (Set) principals.get(info.getPrincipal());
Set sessionsUsedByPrincipal = (Set) principals.get(info
.getPrincipal());
if (sessionsUsedByPrincipal != null) {
synchronized (sessionsUsedByPrincipal) {

View File

@ -23,7 +23,6 @@ import org.springframework.mock.web.MockHttpSession;
import java.util.Date;
/**
* Tests {@link SessionRegistryImpl}.
*
@ -31,7 +30,8 @@ import java.util.Date;
* @version $Id$
*/
public class SessionRegistryImplTests extends TestCase {
//~ Methods ========================================================================================================
// ~ Methods
// ========================================================================================================
public void testEventPublishing() {
MockHttpSession httpSession = new MockHttpSession();
@ -45,7 +45,8 @@ public class SessionRegistryImplTests extends TestCase {
sessionRegistry.registerNewSession(sessionId, principal);
// Deregister session via an ApplicationEvent
sessionRegistry.onApplicationEvent(new HttpSessionDestroyedEvent(httpSession));
sessionRegistry.onApplicationEvent(new HttpSessionDestroyedEvent(
httpSession));
// Check attempts to retrieve cleared session return null
assertNull(sessionRegistry.getSessionInformation(sessionId));
@ -77,10 +78,14 @@ public class SessionRegistryImplTests extends TestCase {
sessionRegistry.registerNewSession(sessionId, principal);
// Retrieve existing session by session ID
Date currentDateTime = sessionRegistry.getSessionInformation(sessionId).getLastRequest();
assertEquals(principal, sessionRegistry.getSessionInformation(sessionId).getPrincipal());
assertEquals(sessionId, sessionRegistry.getSessionInformation(sessionId).getSessionId());
assertNotNull(sessionRegistry.getSessionInformation(sessionId).getLastRequest());
Date currentDateTime = sessionRegistry.getSessionInformation(sessionId)
.getLastRequest();
assertEquals(principal, sessionRegistry
.getSessionInformation(sessionId).getPrincipal());
assertEquals(sessionId, sessionRegistry
.getSessionInformation(sessionId).getSessionId());
assertNotNull(sessionRegistry.getSessionInformation(sessionId)
.getLastRequest());
// Retrieve existing session by principal
assertEquals(1, sessionRegistry.getAllSessions(principal, false).length);
@ -91,11 +96,13 @@ public class SessionRegistryImplTests extends TestCase {
// Update request date/time
sessionRegistry.refreshLastRequest(sessionId);
Date retrieved = sessionRegistry.getSessionInformation(sessionId).getLastRequest();
Date retrieved = sessionRegistry.getSessionInformation(sessionId)
.getLastRequest();
assertTrue(retrieved.after(currentDateTime));
// Check it retrieves correctly when looked up via principal
assertEquals(retrieved, sessionRegistry.getAllSessions(principal, false)[0].getLastRequest());
assertEquals(retrieved, sessionRegistry
.getAllSessions(principal, false)[0].getLastRequest());
// Clear session information
sessionRegistry.removeSessionInformation(sessionId);
@ -114,20 +121,25 @@ public class SessionRegistryImplTests extends TestCase {
// Register new Session
sessionRegistry.registerNewSession(sessionId1, principal);
assertEquals(1, sessionRegistry.getAllSessions(principal, false).length);
assertEquals(sessionId1, sessionRegistry.getAllSessions(principal, false)[0].getSessionId());
assertEquals(sessionId1, sessionRegistry.getAllSessions(principal,
false)[0].getSessionId());
// Register new Session
sessionRegistry.registerNewSession(sessionId2, principal);
assertEquals(2, sessionRegistry.getAllSessions(principal, false).length);
assertEquals(sessionId2, sessionRegistry.getAllSessions(principal, false)[1].getSessionId());
assertEquals(sessionId2, sessionRegistry.getAllSessions(principal,
false)[1].getSessionId());
// Expire one session
SessionInformation session = sessionRegistry.getSessionInformation(sessionId2);
SessionInformation session = sessionRegistry
.getSessionInformation(sessionId2);
session.expireNow();
// Check retrieval still correct
assertTrue(sessionRegistry.getSessionInformation(sessionId2).isExpired());
assertFalse(sessionRegistry.getSessionInformation(sessionId1).isExpired());
assertTrue(sessionRegistry.getSessionInformation(sessionId2)
.isExpired());
assertFalse(sessionRegistry.getSessionInformation(sessionId1)
.isExpired());
}
public void testTwoSessionsOnePrincipalHandling() throws Exception {
@ -139,21 +151,25 @@ public class SessionRegistryImplTests extends TestCase {
// Register new Session
sessionRegistry.registerNewSession(sessionId1, principal);
assertEquals(1, sessionRegistry.getAllSessions(principal, false).length);
assertEquals(sessionId1, sessionRegistry.getAllSessions(principal, false)[0].getSessionId());
assertEquals(sessionId1, sessionRegistry.getAllSessions(principal,
false)[0].getSessionId());
// Register new Session
sessionRegistry.registerNewSession(sessionId2, principal);
assertEquals(2, sessionRegistry.getAllSessions(principal, false).length);
assertEquals(sessionId2, sessionRegistry.getAllSessions(principal, false)[1].getSessionId());
assertEquals(sessionId2, sessionRegistry.getAllSessions(principal,
false)[1].getSessionId());
// Clear session information
sessionRegistry.removeSessionInformation(sessionId1);
assertEquals(1, sessionRegistry.getAllSessions(principal, false).length);
assertEquals(sessionId2, sessionRegistry.getAllSessions(principal, false)[0].getSessionId());
assertEquals(sessionId2, sessionRegistry.getAllSessions(principal,
false)[0].getSessionId());
// Clear final session
sessionRegistry.removeSessionInformation(sessionId2);
assertNull(sessionRegistry.getSessionInformation(sessionId2));
assertNull(sessionRegistry.getAllSessions(principal, false));
}
}