package net.sourceforge.javautil.developer.web.unit.mockserver.http;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import net.sourceforge.javautil.common.ChecksumUtil;
import net.sourceforge.javautil.developer.web.unit.mockserver.http.MockHttpSession.SessionSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The main implementation for managing HTTP sessions for a {@link MockHttpServletContext}.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public class MockHttpSessionContext implements HttpSessionContext, MockHttpSessionManager {
private Logger log = LoggerFactory.getLogger(MockHttpSessionContext.class);
private MockHttpServletContext context;
private Map<String, MockHttpSession> sessions = Collections.synchronizedMap( new LinkedHashMap<String, MockHttpSession>() );
public MockHttpSessionContext(MockHttpServletContext context) {
this.context = context;
}
public String[] findSessionIds () {
return new ArrayList<String>(sessions.keySet()).toArray(new String[sessions.size()]);
}
public Enumeration getIds() { return Collections.enumeration( sessions.keySet() ); }
public MockHttpSession getSession(String id) { return sessions.get(id); }
public MockHttpSession getSession(MockHttpServletRequest request, boolean create) {
String id = null;
SessionSource source = null;
Cookie[] cookies = request.getCookies();
for (int c=0; c<cookies.length; c++) {
if (cookies[c].getName().equals(MockHttpSession.SESSIONID_KEY)) {
id = cookies[c].getValue(); source = SessionSource.COOKIE; break;
}
}
if (id == null) {
id = request.getParameter(MockHttpSession.SESSIONID_KEY);
if (id != null) source = SessionSource.URL;
}
MockHttpSession session = id == null ? null : this.getSession(id);
if (session != null) session.source = source;
return session == null && create ? this.createSession(request) : session;
}
public MockHttpSession createSession(MockHttpServletRequest request) {
MockHttpSession session = new MockHttpSession(context, this.createUniqueId());
List<HttpSessionListener> listeners = this.context.getSessionListenerClasses();
HttpSessionEvent evt = new HttpSessionEvent(session);
for (int i=0; i<listeners.size(); i++) {
try {
listeners.get(i).sessionCreated(evt);
} catch (Throwable t) {
log.error("Error calling session listener", t);
}
}
log.info("Creating Session: " + session.getId());
this.sessions.put(session.getId(), session);
request.getResponse().addCookie(new Cookie(MockHttpSession.SESSIONID_KEY, session.getId()));
return session;
}
public void removeOldSessions () {
List<String> ids = new ArrayList<String>(sessions.keySet());
for (int i=0; i<ids.size(); i++) {
MockHttpSession session = this.getSession(ids.get(i));
if (System.currentTimeMillis() - session.getLastAccessedTime() > session.getMaxInactiveInterval() && session.getMaxInactiveInterval() > 0) {
this.sessions.remove(session.getId());
List<HttpSessionListener> listeners = this.context.getSessionListenerClasses();
HttpSessionEvent evt = new HttpSessionEvent(session);
for (int l=0; l<listeners.size(); l++) {
try {
listeners.get(l).sessionDestroyed(evt);
} catch (Throwable t) {
log.error("Error calling session listener", t);
}
}
}
}
}
/**
* @return Generate a unique ID for a session
*/
public String createUniqueId () {
byte[] digest = ChecksumUtil.createChecksum("MD5", String.valueOf( System.currentTimeMillis() ).getBytes());
StringBuffer sb = new StringBuffer();
for (int i=0; i<digest.length; i++) sb.append(Integer.toHexString(0xFF & digest[i]));
return sb.toString();
}
}