View | Details | Raw Unified | Return to bug 63324
Collapse All | Expand All

(-)a/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java (-11 / +19 lines)
Lines 42-48 Link Here
42
 * users - regardless of whether or not they provide a session token with their
42
 * users - regardless of whether or not they provide a session token with their
43
 * requests.
43
 * requests.
44
 */
44
 */
45
public class CrawlerSessionManagerValve extends ValveBase implements HttpSessionBindingListener {
45
public class CrawlerSessionManagerValve extends ValveBase {
46
46
47
    private static final Log log = LogFactory.getLog(CrawlerSessionManagerValve.class);
47
    private static final Log log = LogFactory.getLog(CrawlerSessionManagerValve.class);
48
48
Lines 241-247 public void invoke(Request request, Response response) throws IOException, Servl Link Here
241
                    clientIdSessionId.put(clientIdentifier, s.getId());
241
                    clientIdSessionId.put(clientIdentifier, s.getId());
242
                    sessionIdClientId.put(s.getId(), clientIdentifier);
242
                    sessionIdClientId.put(s.getId(), clientIdentifier);
243
                    // #valueUnbound() will be called on session expiration
243
                    // #valueUnbound() will be called on session expiration
244
                    s.setAttribute(this.getClass().getName(), this);
244
                    s.setAttribute(this.getClass().getName(), new CrawlerHttpSessionBindingListener(clientIdSessionId, sessionIdClientId));
245
                    s.setMaxInactiveInterval(sessionInactiveInterval);
245
                    s.setMaxInactiveInterval(sessionInactiveInterval);
246
246
247
                    if (log.isDebugEnabled()) {
247
                    if (log.isDebugEnabled()) {
Lines 269-286 private String getClientIdentifier(Host host, Context context, String clientIp) Link Here
269
        return result.toString();
269
        return result.toString();
270
    }
270
    }
271
271
272
    private static class CrawlerHttpSessionBindingListener implements HttpSessionBindingListener {
273
        private final Map<String, String> clientIdSessionId;
274
        private final Map<String, String> sessionIdClientId;
272
275
273
    @Override
276
        public CrawlerHttpSessionBindingListener(Map<String, String> clientIdSessionId, Map<String, String> sessionIdClientId) {
274
    public void valueBound(HttpSessionBindingEvent event) {
277
            this.clientIdSessionId = clientIdSessionId;
275
        // NOOP
278
            this.sessionIdClientId = sessionIdClientId;
276
    }
279
        }
277
280
281
        @Override
282
        public void valueBound(HttpSessionBindingEvent event) {
283
            // NOOP
284
        }
278
285
279
    @Override
286
        @Override
280
    public void valueUnbound(HttpSessionBindingEvent event) {
287
        public void valueUnbound(HttpSessionBindingEvent event) {
281
        String clientIdentifier = sessionIdClientId.remove(event.getSession().getId());
288
            String clientIdentifier = sessionIdClientId.remove(event.getSession().getId());
282
        if (clientIdentifier != null) {
289
            if (clientIdentifier != null) {
283
            clientIdSessionId.remove(clientIdentifier);
290
                clientIdSessionId.remove(clientIdentifier);
291
            }
284
        }
292
        }
285
    }
293
    }
286
}
294
}
(-)a/test/org/apache/catalina/valves/TestCrawlerSessionManagerValve.java (-2 / +45 lines)
Lines 22-28 Link Here
22
22
23
import javax.servlet.ServletException;
23
import javax.servlet.ServletException;
24
import javax.servlet.http.HttpSession;
24
import javax.servlet.http.HttpSession;
25
import javax.servlet.http.HttpSessionBindingListener;
25
26
27
import org.apache.catalina.Manager;
28
import org.apache.catalina.core.StandardContext;
29
import org.apache.catalina.session.StandardManager;
30
import org.apache.catalina.session.StandardSession;
31
import org.hamcrest.CoreMatchers;
26
import org.junit.Test;
32
import org.junit.Test;
27
33
28
import org.apache.catalina.Context;
34
import org.apache.catalina.Context;
Lines 33-40 Link Here
33
import org.easymock.EasyMock;
39
import org.easymock.EasyMock;
34
import org.easymock.IExpectationSetters;
40
import org.easymock.IExpectationSetters;
35
41
42
import static org.hamcrest.CoreMatchers.*;
43
import static org.hamcrest.MatcherAssert.assertThat;
44
36
public class TestCrawlerSessionManagerValve {
45
public class TestCrawlerSessionManagerValve {
37
46
47
    private static final Manager TEST_MANAGER;
48
49
    static {
50
        TEST_MANAGER = new StandardManager();
51
        TEST_MANAGER.setContext(new StandardContext());
52
    }
53
54
55
38
    @Test
56
    @Test
39
    public void testCrawlerIpsPositive() throws Exception {
57
    public void testCrawlerIpsPositive() throws Exception {
40
        CrawlerSessionManagerValve valve = new CrawlerSessionManagerValve();
58
        CrawlerSessionManagerValve valve = new CrawlerSessionManagerValve();
Lines 79-84 public void testCrawlerMultipleHostsHostAware() throws Exception { Link Here
79
        verifyCrawlingLocalhost(valve, "example.invalid");
97
        verifyCrawlingLocalhost(valve, "example.invalid");
80
    }
98
    }
81
99
100
    @Test
101
    public void testCrawlersSessionIdIsRemovedAfterSessionExpiry() throws IOException, ServletException {
102
        CrawlerSessionManagerValve valve = new CrawlerSessionManagerValve();
103
        valve.setCrawlerIps("216\\.58\\.206\\.174");
104
        valve.setCrawlerUserAgents(valve.getCrawlerUserAgents());
105
        valve.setNext(EasyMock.createMock(Valve.class));
106
        valve.setSessionInactiveInterval(0);
107
        StandardSession session = new StandardSession(TEST_MANAGER);
108
        session.setId("id");
109
        session.setValid(true);
110
111
        Request request = createRequestExpectations("216.58.206.174", session, true);
112
113
        EasyMock.replay(request);
114
115
        valve.invoke(request, EasyMock.createMock(Response.class));
116
117
        EasyMock.verify(request);
118
119
        assertThat(valve.getClientIpSessionId().values(), hasItem("id"));
120
121
        session.expire();
122
123
        assertThat(valve.getClientIpSessionId().values().size(), is(0));
124
    }
125
82
126
83
    private void verifyCrawlingLocalhost(CrawlerSessionManagerValve valve, String hostname)
127
    private void verifyCrawlingLocalhost(CrawlerSessionManagerValve valve, String hostname)
84
            throws IOException, ServletException {
128
            throws IOException, ServletException {
Lines 97-103 private HttpSession createSessionExpectations(CrawlerSessionManagerValve valve, Link Here
97
        HttpSession session = EasyMock.createMock(HttpSession.class);
141
        HttpSession session = EasyMock.createMock(HttpSession.class);
98
        if (isBot) {
142
        if (isBot) {
99
            EasyMock.expect(session.getId()).andReturn("id").times(2);
143
            EasyMock.expect(session.getId()).andReturn("id").times(2);
100
            session.setAttribute(valve.getClass().getName(), valve);
144
            session.setAttribute(EasyMock.eq(valve.getClass().getName()), EasyMock.anyObject(HttpSessionBindingListener.class));
101
            EasyMock.expectLastCall();
145
            EasyMock.expectLastCall();
102
            session.setMaxInactiveInterval(60);
146
            session.setMaxInactiveInterval(60);
103
            EasyMock.expectLastCall();
147
            EasyMock.expectLastCall();
104
smaller object. It helps to serialize this sessions with libraries like kryo.
148
smaller object. It helps to serialize this sessions with libraries like kryo.
105
--
106
.../valves/CrawlerSessionManagerValve.java      | 17 +++++++++--------
149
.../valves/CrawlerSessionManagerValve.java      | 17 +++++++++--------
107
.../valves/TestCrawlerSessionManagerValve.java  |  1 -
150
.../valves/TestCrawlerSessionManagerValve.java  |  1 -
108
2 files changed, 9 insertions(+), 9 deletions(-)
151
2 files changed, 9 insertions(+), 9 deletions(-)
(-)a/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java (-8 / +9 lines)
Lines 17-22 Link Here
17
package org.apache.catalina.valves;
17
package org.apache.catalina.valves;
18
18
19
import java.io.IOException;
19
import java.io.IOException;
20
import java.io.Serializable;
20
import java.util.Enumeration;
21
import java.util.Enumeration;
21
import java.util.Map;
22
import java.util.Map;
22
import java.util.concurrent.ConcurrentHashMap;
23
import java.util.concurrent.ConcurrentHashMap;
Lines 241-247 public void invoke(Request request, Response response) throws IOException, Servl Link Here
241
                    clientIdSessionId.put(clientIdentifier, s.getId());
242
                    clientIdSessionId.put(clientIdentifier, s.getId());
242
                    sessionIdClientId.put(s.getId(), clientIdentifier);
243
                    sessionIdClientId.put(s.getId(), clientIdentifier);
243
                    // #valueUnbound() will be called on session expiration
244
                    // #valueUnbound() will be called on session expiration
244
                    s.setAttribute(this.getClass().getName(), new CrawlerHttpSessionBindingListener(clientIdSessionId, sessionIdClientId));
245
                    s.setAttribute(this.getClass().getName(), new CrawlerHttpSessionBindingListener(clientIdSessionId, clientIdentifier));
245
                    s.setMaxInactiveInterval(sessionInactiveInterval);
246
                    s.setMaxInactiveInterval(sessionInactiveInterval);
246
247
247
                    if (log.isDebugEnabled()) {
248
                    if (log.isDebugEnabled()) {
Lines 269-281 private String getClientIdentifier(Host host, Context context, String clientIp) Link Here
269
        return result.toString();
270
        return result.toString();
270
    }
271
    }
271
272
272
    private static class CrawlerHttpSessionBindingListener implements HttpSessionBindingListener {
273
    private static class CrawlerHttpSessionBindingListener implements HttpSessionBindingListener, Serializable {
273
        private final Map<String, String> clientIdSessionId;
274
        private final transient Map<String, String> clientIdSessionId;
274
        private final Map<String, String> sessionIdClientId;
275
        private final transient String clientIdentifier;
275
276
276
        public CrawlerHttpSessionBindingListener(Map<String, String> clientIdSessionId, Map<String, String> sessionIdClientId) {
277
        private CrawlerHttpSessionBindingListener(Map<String, String> clientIdSessionId, String clientIdentifier) {
277
            this.clientIdSessionId = clientIdSessionId;
278
            this.clientIdSessionId = clientIdSessionId;
278
            this.sessionIdClientId = sessionIdClientId;
279
            this.clientIdentifier = clientIdentifier;
279
        }
280
        }
280
281
281
        @Override
282
        @Override
Lines 285-292 public void valueBound(HttpSessionBindingEvent event) { Link Here
285
286
286
        @Override
287
        @Override
287
        public void valueUnbound(HttpSessionBindingEvent event) {
288
        public void valueUnbound(HttpSessionBindingEvent event) {
288
            String clientIdentifier = sessionIdClientId.remove(event.getSession().getId());
289
            if (clientIdentifier != null && clientIdSessionId != null) {
289
            if (clientIdentifier != null) {
290
                if(clientIdSessionId.get(clientIdentifier).equals(event.getSession().getId()))
290
                clientIdSessionId.remove(clientIdentifier);
291
                clientIdSessionId.remove(clientIdentifier);
291
            }
292
            }
292
        }
293
        }
(-)a/test/org/apache/catalina/valves/TestCrawlerSessionManagerValve.java (-2 lines)
Lines 28-34 Link Here
28
import org.apache.catalina.core.StandardContext;
28
import org.apache.catalina.core.StandardContext;
29
import org.apache.catalina.session.StandardManager;
29
import org.apache.catalina.session.StandardManager;
30
import org.apache.catalina.session.StandardSession;
30
import org.apache.catalina.session.StandardSession;
31
import org.hamcrest.CoreMatchers;
32
import org.junit.Test;
31
import org.junit.Test;
33
32
34
import org.apache.catalina.Context;
33
import org.apache.catalina.Context;
35
--
36
.../catalina/valves/CrawlerSessionManagerValve.java | 13 +++++++------
34
.../catalina/valves/CrawlerSessionManagerValve.java | 13 +++++++------
37
1 file changed, 7 insertions(+), 6 deletions(-)
35
1 file changed, 7 insertions(+), 6 deletions(-)
(-)a/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java (-6 / +7 lines)
Lines 88-95 public void setCrawlerUserAgents(String crawlerUserAgents) { Link Here
88
    }
88
    }
89
89
90
    /**
90
    /**
91
     * @return The current regular expression being used to match user agents.
91
     * @see #setCrawlerUserAgents(String)
92
     * @see #setCrawlerUserAgents(String)
92
     * @return  The current regular expression being used to match user agents.
93
     */
93
     */
94
    public String getCrawlerUserAgents() {
94
    public String getCrawlerUserAgents() {
95
        return crawlerUserAgents;
95
        return crawlerUserAgents;
Lines 113-120 public void setCrawlerIps(String crawlerIps) { Link Here
113
    }
113
    }
114
114
115
    /**
115
    /**
116
     * @see #setCrawlerIps(String)
117
     * @return The current regular expression being used to match IP addresses.
116
     * @return The current regular expression being used to match IP addresses.
117
     * @see #setCrawlerIps(String)
118
     */
118
     */
119
    public String getCrawlerIps() {
119
    public String getCrawlerIps() {
120
        return crawlerIps;
120
        return crawlerIps;
Lines 125-139 public String getCrawlerIps() { Link Here
125
     * Specify the session timeout (in seconds) for a crawler's session. This is
125
     * Specify the session timeout (in seconds) for a crawler's session. This is
126
     * typically lower than that for a user session. The default is 60 seconds.
126
     * typically lower than that for a user session. The default is 60 seconds.
127
     *
127
     *
128
     * @param sessionInactiveInterval   The new timeout for crawler sessions
128
     * @param sessionInactiveInterval The new timeout for crawler sessions
129
     */
129
     */
130
    public void setSessionInactiveInterval(int sessionInactiveInterval) {
130
    public void setSessionInactiveInterval(int sessionInactiveInterval) {
131
        this.sessionInactiveInterval = sessionInactiveInterval;
131
        this.sessionInactiveInterval = sessionInactiveInterval;
132
    }
132
    }
133
133
134
    /**
134
    /**
135
     * @return The current timeout in seconds
135
     * @see #setSessionInactiveInterval(int)
136
     * @see #setSessionInactiveInterval(int)
136
     * @return  The current timeout in seconds
137
     */
137
     */
138
    public int getSessionInactiveInterval() {
138
    public int getSessionInactiveInterval() {
139
        return sessionInactiveInterval;
139
        return sessionInactiveInterval;
Lines 287-294 public void valueBound(HttpSessionBindingEvent event) { Link Here
287
        @Override
287
        @Override
288
        public void valueUnbound(HttpSessionBindingEvent event) {
288
        public void valueUnbound(HttpSessionBindingEvent event) {
289
            if (clientIdentifier != null && clientIdSessionId != null) {
289
            if (clientIdentifier != null && clientIdSessionId != null) {
290
                if(clientIdSessionId.get(clientIdentifier).equals(event.getSession().getId()))
290
                if (clientIdSessionId.get(clientIdentifier).equals(event.getSession().getId())) {
291
                clientIdSessionId.remove(clientIdentifier);
291
                    clientIdSessionId.remove(clientIdentifier);
292
                }
292
            }
293
            }
293
        }
294
        }
294
    }
295
    }

Return to bug 63324