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

(-)a/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java (-7 / +16 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-280 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 valueUnbound(HttpSessionBindingEvent event) {
277
            this.clientIdSessionId = clientIdSessionId;
275
        String clientIdentifier = sessionIdClientId.remove(event.getSession().getId());
278
            this.sessionIdClientId = sessionIdClientId;
276
        if (clientIdentifier != null) {
279
        }
277
            clientIdSessionId.remove(clientIdentifier);
280
281
        @Override
282
        public void valueUnbound(HttpSessionBindingEvent event) {
283
            String clientIdentifier = sessionIdClientId.remove(event.getSession().getId());
284
            if (clientIdentifier != null) {
285
                clientIdSessionId.remove(clientIdentifier);
286
            }
278
        }
287
        }
279
    }
288
    }
280
}
289
}
(-)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     | 18 +++++++++---------
149
.../valves/CrawlerSessionManagerValve.java     | 18 +++++++++---------
107
.../valves/TestCrawlerSessionManagerValve.java |  1 -
150
.../valves/TestCrawlerSessionManagerValve.java |  1 -
108
2 files changed, 9 insertions(+), 10 deletions(-)
151
2 files changed, 9 insertions(+), 10 deletions(-)
(-)a/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java (-9 / +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-288 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
282
        public void valueUnbound(HttpSessionBindingEvent event) {
283
        public void valueUnbound(HttpSessionBindingEvent event) {
283
            String clientIdentifier = sessionIdClientId.remove(event.getSession().getId());
284
            if (clientIdentifier != null && clientIdSessionId != null) {
284
            if (clientIdentifier != null) {
285
                clientIdSessionId.remove(clientIdentifier, event.getSession().getId());
285
                clientIdSessionId.remove(clientIdentifier);
286
            }
286
            }
287
        }
287
        }
288
    }
288
    }
(-)a/test/org/apache/catalina/valves/TestCrawlerSessionManagerValve.java (-1 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;

Return to bug 63324