View Javadoc
1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.server.session;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertNotNull;
23  import static org.junit.Assert.assertTrue;
24  
25  import java.io.IOException;
26  
27  import javax.servlet.ServletException;
28  import javax.servlet.http.HttpServlet;
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  import javax.servlet.http.HttpSession;
32  import javax.servlet.http.HttpSessionEvent;
33  import javax.servlet.http.HttpSessionListener;
34  
35  import org.eclipse.jetty.client.HttpClient;
36  import org.eclipse.jetty.client.api.ContentResponse;
37  import org.eclipse.jetty.server.Request;
38  import org.eclipse.jetty.servlet.ServletContextHandler;
39  import org.eclipse.jetty.util.statistic.CounterStatistic;
40  import org.junit.Test;
41  
42  /**
43   * AbstractLocalSessionScavengingTest
44   */
45  public abstract class AbstractLocalSessionScavengingTest extends AbstractTestBase
46  {
47  
48      public void pause(int scavengePeriod)
49      {
50          try
51          {
52              Thread.sleep(scavengePeriod * 1000L);
53          }
54          catch (InterruptedException e)
55          {
56              e.printStackTrace();
57          }
58      }
59      
60      
61      public static class SessionListener implements HttpSessionListener
62      {
63          public CounterStatistic count = new CounterStatistic();
64          /** 
65           * @see javax.servlet.http.HttpSessionListener#sessionCreated(javax.servlet.http.HttpSessionEvent)
66           */
67          @Override
68          public void sessionCreated(HttpSessionEvent se)
69          {
70              count.increment();
71          }
72  
73          /** 
74           * @see javax.servlet.http.HttpSessionListener#sessionDestroyed(javax.servlet.http.HttpSessionEvent)
75           */
76          @Override
77          public void sessionDestroyed(HttpSessionEvent se)
78          {
79             count.decrement();
80          }
81      }
82      
83      @Test
84      public void testNoScavenging() throws Exception
85      {
86          String contextPath = "";
87          String servletMapping = "/server";
88          int inactivePeriod = 3;
89          int scavengePeriod = 0;
90          AbstractTestServer server1 = createServer(0, inactivePeriod, scavengePeriod, SessionCache.NEVER_EVICT);
91          ServletContextHandler context1 = server1.addContext(contextPath);
92          context1.addServlet(TestServlet.class, servletMapping);
93          SessionListener listener = new SessionListener();
94          context1.getSessionHandler().addEventListener(listener);
95             
96          
97          try
98          {
99              server1.start();
100             int port1 = server1.getPort();
101 
102             HttpClient client = new HttpClient();
103             client.start();
104             try
105             {
106                 String url = "http://localhost:" + port1 + contextPath + servletMapping;
107 
108 
109                 // Create the session
110                 ContentResponse response1 = client.GET(url + "?action=init");
111                 assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
112                 String sessionCookie = response1.getHeaders().get("Set-Cookie");
113                 assertTrue(sessionCookie != null);
114                 // Mangle the cookie, replacing Path with $Path, etc.
115                 sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
116                 SessionHandler m1 = context1.getSessionHandler();
117                 assertEquals(1,  m1.getSessionsCreated());
118 
119 
120                 // Wait a while to ensure that the session should have expired, if the
121                 //scavenger was running
122                 pause(2*inactivePeriod);
123 
124                 assertEquals(1,  m1.getSessionsCreated());
125                
126 
127                 if (m1 instanceof TestSessionHandler)
128                 {
129                     ((TestSessionHandler)m1).assertCandidatesForExpiry(0);
130                 }
131 
132                 //check a session removed listener did not get called
133                 assertEquals(1, listener.count.getCurrent());
134             }
135             finally
136             {
137                 client.stop();
138             }
139         }
140         finally
141         {
142             server1.stop();
143         }
144     }
145     
146 
147     @Test
148     public void testLocalSessionsScavenging() throws Exception
149     {
150         String contextPath = "";
151         String servletMapping = "/server";
152         int inactivePeriod = 4;
153         int scavengePeriod = 1;
154         AbstractTestServer server1 = createServer(0, inactivePeriod, scavengePeriod, SessionCache.NEVER_EVICT);
155         ServletContextHandler context1 = server1.addContext(contextPath);
156         context1.addServlet(TestServlet.class, servletMapping);
157 
158         try
159         {
160             server1.start();
161             int port1 = server1.getPort();
162             AbstractTestServer server2 = createServer(0, inactivePeriod, scavengePeriod * 2, SessionCache.NEVER_EVICT);
163             ServletContextHandler context2 = server2.addContext(contextPath);
164             context2.addServlet(TestServlet.class, servletMapping);
165 
166             try
167             {
168                 server2.start();
169                 int port2 = server2.getPort();
170                 HttpClient client = new HttpClient();
171                 client.start();
172                 try
173                 {
174                     String[] urls = new String[2];
175                     urls[0] = "http://localhost:" + port1 + contextPath + servletMapping;
176                     urls[1] = "http://localhost:" + port2 + contextPath + servletMapping;
177 
178                     // Create the session on node1
179                     ContentResponse response1 = client.GET(urls[0] + "?action=init");
180                     assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
181                     String sessionCookie = response1.getHeaders().get("Set-Cookie");
182                     assertTrue(sessionCookie != null);
183                     // Mangle the cookie, replacing Path with $Path, etc.
184                     sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
185                     SessionHandler m1 = context1.getSessionHandler();
186                     assertEquals(1,  m1.getSessionsCreated());
187 
188                     // Be sure the session is also present in node2
189                     org.eclipse.jetty.client.api.Request request = client.newRequest(urls[1] + "?action=test");
190                     request.header("Cookie", sessionCookie);
191                     ContentResponse response2 = request.send();
192                     assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
193                     SessionHandler m2 = context2.getSessionHandler();
194 
195                     // Wait for the scavenger to run on node1
196                     pause(inactivePeriod+(2*scavengePeriod));
197 
198                     assertEquals(1,  m1.getSessionsCreated());
199 
200                     // Check that node1 does not have any local session cached
201                     request = client.newRequest(urls[0] + "?action=check");
202                     request.header("Cookie", sessionCookie);
203                     response1 = request.send();
204                     assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
205                     
206                     assertEquals(1,  m1.getSessionsCreated());
207 
208                     // Wait for the scavenger to run on node2, waiting 3 times the scavenger period
209                     // This ensures that the scavenger on node2 runs at least once.
210                     pause(inactivePeriod+(2*scavengePeriod));
211                     
212                     // Check that node2 does not have any local session cached
213                     request = client.newRequest(urls[1] + "?action=check");
214                     request.header("Cookie", sessionCookie);
215                     response2 = request.send();
216                     assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
217                 }
218                 finally
219                 {
220                     client.stop();
221                 }
222             }
223             finally
224             {
225                 server2.stop();
226             }
227         }
228         finally
229         {
230             server1.stop();
231         }
232     }
233 
234     public static class TestServlet extends HttpServlet
235     {
236         @Override
237         protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
238         {
239             String action = request.getParameter("action");
240             if ("init".equals(action))
241             {
242                 HttpSession session = request.getSession(true);
243                 session.setAttribute("test", "test");
244             }
245             else if ("test".equals(action))
246             {
247                 HttpSession session = request.getSession(false);
248                 assertNotNull(session);
249                 session.setAttribute("test", "test");
250             }
251             else if ("check".equals(action))
252             {
253                 HttpSession session = request.getSession(false);
254                 assertTrue(session == null);
255             }
256         }
257     }
258 }