From afa58d4a8081626a586a6ad0e574dca3528b624c Mon Sep 17 00:00:00 2001 From: markt Date: Mon, 27 Jun 2011 22:13:39 +0000 Subject: [PATCH] Use a more reliable method to expire sessions. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1140347 13f79535-47bb-0310-9956-ffa450edef68 --- .../valves/CrawlerSessionManagerValve.java | 87 ++++++++-------------- .../apache/catalina/valves/mbeans-descriptors.xml | 38 ++++++++++ 2 files changed, 67 insertions(+), 58 deletions(-) diff --git a/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java b/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java index 9d3ab5001..965a2bb9b 100644 --- a/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java +++ b/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java @@ -18,16 +18,15 @@ package org.apache.catalina.valves; import java.io.IOException; import java.util.Enumeration; -import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import javax.servlet.ServletException; import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpSessionBindingEvent; +import javax.servlet.http.HttpSessionBindingListener; -import org.apache.catalina.LifecycleException; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.juli.logging.Log; @@ -40,13 +39,16 @@ import org.apache.juli.logging.LogFactory; * users - regardless of whether or not they provide a session token with their * requests. */ -public class CrawlerSessionManagerValve extends ValveBase { +public class CrawlerSessionManagerValve extends ValveBase + implements HttpSessionBindingListener { private static final Log log = LogFactory.getLog(CrawlerSessionManagerValve.class); - private Map uaIpSessionInfo = - new ConcurrentHashMap(); + private Map clientIpSessionId = + new ConcurrentHashMap(); + private Map sessionIdClientIp = + new ConcurrentHashMap(); private String crawlerUserAgents = ".*[bB]ot.*|.*Yahoo! Slurp.*|.*Feedfetcher-Google.*"; @@ -106,11 +108,8 @@ public class CrawlerSessionManagerValve extends ValveBase { } - @Override - protected void initInternal() throws LifecycleException { - super.initInternal(); - - uaPattern = Pattern.compile(crawlerUserAgents); + public Map getClientIpSessionId() { + return clientIpSessionId; } @@ -119,7 +118,7 @@ public class CrawlerSessionManagerValve extends ValveBase { ServletException { boolean isBot = false; - SessionInfo sessionInfo = null; + String sessionId = null; String clientIp = null; if (log.isDebugEnabled()) { @@ -158,12 +157,12 @@ public class CrawlerSessionManagerValve extends ValveBase { // If this is a bot, is the session ID known? if (isBot) { clientIp = request.getRemoteAddr(); - sessionInfo = uaIpSessionInfo.get(clientIp); - if (sessionInfo != null) { - request.setRequestedSessionId(sessionInfo.getSessionId()); + sessionId = clientIpSessionId.get(clientIp); + if (sessionId != null) { + request.setRequestedSessionId(sessionId); if (log.isDebugEnabled()) { - log.debug(request.hashCode() + - ": SessionID=" + sessionInfo.getSessionId()); + log.debug(request.hashCode() + ": SessionID=" + + sessionId); } } } @@ -172,11 +171,14 @@ public class CrawlerSessionManagerValve extends ValveBase { getNext().invoke(request, response); if (isBot) { - if (sessionInfo == null) { + if (sessionId == null) { // Has bot just created a session, if so make a note of it HttpSession s = request.getSession(false); if (s != null) { - uaIpSessionInfo.put(clientIp, new SessionInfo(s.getId())); + clientIpSessionId.put(clientIp, s.getId()); + sessionIdClientIp.put(s.getId(), clientIp); + // #valueUnbound() will be called on session expiration + s.setAttribute(this.getClass().getName(), this); s.setMaxInactiveInterval(sessionInactiveInterval); if (log.isDebugEnabled()) { @@ -185,12 +187,9 @@ public class CrawlerSessionManagerValve extends ValveBase { } } } else { - sessionInfo.access(); - if (log.isDebugEnabled()) { log.debug(request.hashCode() + - ": Bot session accessed. SessionID=" + - sessionInfo.getSessionId()); + ": Bot session accessed. SessionID=" + sessionId); } } } @@ -198,44 +197,16 @@ public class CrawlerSessionManagerValve extends ValveBase { @Override - public void backgroundProcess() { - super.backgroundProcess(); - - long expireTime = System.currentTimeMillis() - - (sessionInactiveInterval + 60) * 1000; - - Iterator> iter = - uaIpSessionInfo.entrySet().iterator(); - - // Remove any sessions in the cache that have expired. - while (iter.hasNext()) { - Entry entry = iter.next(); - if (entry.getValue().getLastAccessed() < expireTime) { - iter.remove(); - } - } + public void valueBound(HttpSessionBindingEvent event) { + // NOOP } - private static final class SessionInfo { - private final String sessionId; - private volatile long lastAccessed; - - public SessionInfo(String sessionId) { - this.sessionId = sessionId; - this.lastAccessed = System.currentTimeMillis(); - } - - public String getSessionId() { - return sessionId; - } - - public long getLastAccessed() { - return lastAccessed; - } - - public void access() { - lastAccessed = System.currentTimeMillis(); + @Override + public void valueUnbound(HttpSessionBindingEvent event) { + String clientIp = sessionIdClientIp.remove(event.getSession().getId()); + if (clientIp != null) { + clientIpSessionId.remove(clientIp); } } } diff --git a/java/org/apache/catalina/valves/mbeans-descriptors.xml b/java/org/apache/catalina/valves/mbeans-descriptors.xml index cb46bd258..ce2c56f8f 100644 --- a/java/org/apache/catalina/valves/mbeans-descriptors.xml +++ b/java/org/apache/catalina/valves/mbeans-descriptors.xml @@ -103,6 +103,44 @@ + + + + + + + + + + + + + + + +