View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 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 java.io.IOException;
22  import java.io.PrintWriter;
23  import java.util.Random;
24  
25  import javax.servlet.ServletException;
26  import javax.servlet.http.HttpServlet;
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpServletResponse;
29  import javax.servlet.http.HttpSession;
30  import javax.servlet.http.HttpSessionEvent;
31  import javax.servlet.http.HttpSessionListener;
32  
33  import org.eclipse.jetty.client.ContentExchange;
34  import org.eclipse.jetty.client.HttpClient;
35  import org.eclipse.jetty.http.HttpMethods;
36  import org.eclipse.jetty.servlet.ServletContextHandler;
37  import org.eclipse.jetty.servlet.ServletHolder;
38  import org.junit.Test;
39  import static org.junit.Assert.assertEquals;
40  import static org.junit.Assert.assertTrue;
41  
42  
43  /**
44   * AbstractLastAccessTimeTest
45   */
46  public abstract class AbstractLastAccessTimeTest
47  {
48      public abstract AbstractTestServer createServer(int port, int max, int scavenge);
49  
50      @Test
51      public void testLastAccessTime() throws Exception
52      {
53          String contextPath = "";
54          String servletMapping = "/server";
55          int maxInactivePeriod = 8;
56          int scavengePeriod = 2;
57          AbstractTestServer server1 = createServer(0, maxInactivePeriod, scavengePeriod);
58          TestServlet servlet1 = new TestServlet();
59          ServletHolder holder1 = new ServletHolder(servlet1);
60          ServletContextHandler context = server1.addContext(contextPath);
61          TestSessionListener listener1 = new TestSessionListener();
62          context.addEventListener(listener1);
63          context.addServlet(holder1, servletMapping);
64          server1.start();
65          int port1=server1.getPort();
66          try
67          {
68              AbstractTestServer server2 = createServer(0, maxInactivePeriod, scavengePeriod);
69              server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
70              server2.start();
71              int port2=server2.getPort();
72              try
73              {
74                  HttpClient client = new HttpClient();
75                  client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
76                  client.start();
77                  try
78                  {
79                      // Perform one request to server1 to create a session
80                      ContentExchange exchange1 = new ContentExchange(true);
81                      exchange1.setMethod(HttpMethods.GET);
82                      exchange1.setURL("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
83                      client.send(exchange1);
84                      exchange1.waitForDone();
85                      assertEquals(HttpServletResponse.SC_OK, exchange1.getResponseStatus());
86                      assertEquals("test", exchange1.getResponseContent());
87                      String sessionCookie = exchange1.getResponseFields().getStringField("Set-Cookie");
88                      assertTrue( sessionCookie != null );
89                      // Mangle the cookie, replacing Path with $Path, etc.
90                      sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
91  
92                      // Perform some request to server2 using the session cookie from the previous request
93                      // This should migrate the session from server1 to server2, and leave server1's
94                      // session in a very stale state, while server2 has a very fresh session.
95                      // We want to test that optimizations done to the saving of the shared lastAccessTime
96                      // do not break the correct working
97                      int requestInterval = 500;
98                      for (int i = 0; i < maxInactivePeriod * (1000 / requestInterval); ++i)
99                      {
100                         ContentExchange exchange2 = new ContentExchange(true);
101                         exchange2.setMethod(HttpMethods.GET);
102                         exchange2.setURL("http://localhost:" + port2 + contextPath + servletMapping);
103                         exchange2.getRequestFields().add("Cookie", sessionCookie);
104                         client.send(exchange2);
105                         exchange2.waitForDone();
106                         assertEquals(HttpServletResponse.SC_OK , exchange2.getResponseStatus());
107                         assertEquals("test", exchange2.getResponseContent());
108 
109                         String setCookie = exchange1.getResponseFields().getStringField("Set-Cookie");
110                         if (setCookie!=null)                    
111                             sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
112                         
113                         Thread.sleep(requestInterval);
114                     }
115 
116                     // At this point, session1 should be eligible for expiration.
117                     // Let's wait for the scavenger to run, waiting 2.5 times the scavenger period
118                     Thread.sleep(scavengePeriod * 2500L);
119 
120                     //check that the session was not scavenged over on server1 by ensuring that the SessionListener destroy method wasn't called
121                     assertTrue (listener1.destroyed == false);  
122 
123                 }
124                 finally
125                 {
126                     client.stop();
127                 }
128             }
129             finally
130             {
131                 server2.stop();
132             }
133         }
134         finally
135         {
136             server1.stop();
137         }
138     }
139 
140     public static class TestSessionListener implements HttpSessionListener
141     {
142         public boolean destroyed = false;
143         public boolean created = false;
144 
145  
146         public void sessionDestroyed(HttpSessionEvent se)
147         {
148             destroyed = true;
149         }
150 
151    
152         public void sessionCreated(HttpSessionEvent se)
153         {
154             created = true;
155         }
156     }
157 
158 
159     public static class TestServlet extends HttpServlet
160     {
161         @Override
162         protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
163         {
164             String action = request.getParameter("action");
165             if ("init".equals(action))
166             {
167                 HttpSession session = request.getSession(true);
168                 session.setAttribute("test", "test");
169                 
170                 sendResult(session, httpServletResponse.getWriter());
171 
172             }
173             else
174             {
175                 HttpSession session = request.getSession(false);
176 
177                 // if we node hopped we should get the session and test should already be present
178                 sendResult(session, httpServletResponse.getWriter());
179 
180                 if (session!=null)
181                 {                                       
182                     session.setAttribute("test", "test");
183                 }
184                 
185 
186             }
187         }
188         
189         private void sendResult(HttpSession session, PrintWriter writer)
190         {
191                 if (session != null)
192                 {                    
193                         writer.print(session.getAttribute("test"));
194                 }
195                 else
196                 {
197                         writer.print("null");
198                 }
199         }
200     }
201 }