Merge remote-tracking branch 'origin/jetty-8'

This commit is contained in:
Jan Bartel 2013-03-08 14:27:24 +11:00
commit f1cd726ba2
7 changed files with 192 additions and 32 deletions

View File

@ -874,7 +874,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
statement = connection.prepareStatement(_deleteOldExpiredSessions);
statement.setLong(1, upperBound);
int rows = statement.executeUpdate();
if (LOG.isDebugEnabled()) LOG.debug("Deleted "+rows+" rows");
if (LOG.isDebugEnabled()) LOG.debug("Deleted "+rows+" rows of old sessions expired before "+upperBound);
}
}
}

View File

@ -278,6 +278,8 @@ public class JDBCSessionManager extends AbstractSessionManager
return false;
}
}
/**
* Exit from session
@ -344,7 +346,7 @@ public class JDBCSessionManager extends AbstractSessionManager
return "Session rowId="+_rowId+",id="+getId()+",lastNode="+_lastNode+
",created="+getCreationTime()+",accessed="+getAccessed()+
",lastAccessed="+getLastAccessedTime()+",cookieSet="+_cookieSet+
"lastSaved="+_lastSaved;
",lastSaved="+_lastSaved+",expiry="+_expiryTime;
}
}
@ -454,8 +456,6 @@ public class JDBCSessionManager extends AbstractSessionManager
synchronized (this)
{
try
{
//check if we need to reload the session -
//as an optimization, don't reload on every access
//to reduce the load on the database. This introduces a window of
@ -483,22 +483,31 @@ public class JDBCSessionManager extends AbstractSessionManager
" difference="+(now - memSession._lastSaved));
}
if (memSession==null)
try
{
LOG.debug("getSession("+idInCluster+"): no session in session map. Reloading session data from db.");
session = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context));
if (memSession==null)
{
LOG.debug("getSession("+idInCluster+"): no session in session map. Reloading session data from db.");
session = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context));
}
else if ((now - memSession._lastSaved) >= (_saveIntervalSec * 1000L))
{
LOG.debug("getSession("+idInCluster+"): stale session. Reloading session data from db.");
session = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context));
}
else
{
LOG.debug("getSession("+idInCluster+"): session in session map");
session = memSession;
}
}
else if ((now - memSession._lastSaved) >= (_saveIntervalSec * 1000L))
catch (Exception e)
{
LOG.debug("getSession("+idInCluster+"): stale session. Reloading session data from db.");
session = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context));
}
else
{
LOG.debug("getSession("+idInCluster+"): session in session map");
session = memSession;
LOG.warn("Unable to load session "+idInCluster, e);
return null;
}
//If we have a session
if (session != null)
{
@ -508,13 +517,23 @@ public class JDBCSessionManager extends AbstractSessionManager
//if session doesn't expire, or has not already expired, update it and put it in this nodes' memory
if (session._expiryTime <= 0 || session._expiryTime > now)
{
if (LOG.isDebugEnabled()) LOG.debug("getSession("+idInCluster+"): lastNode="+session.getLastNode()+" thisNode="+getSessionIdManager().getWorkerName());
if (LOG.isDebugEnabled())
LOG.debug("getSession("+idInCluster+"): lastNode="+session.getLastNode()+" thisNode="+getSessionIdManager().getWorkerName());
session.setLastNode(getSessionIdManager().getWorkerName());
_sessions.put(idInCluster, session);
session.didActivate();
//TODO is this the best way to do this? Or do this on the way out using
//the _dirty flag?
updateSessionNode(session);
//update in db: if unable to update, session will be scavenged later
try
{
updateSessionNode(session);
session.didActivate();
}
catch (Exception e)
{
LOG.warn("Unable to update freshly loaded session "+idInCluster, e);
return null;
}
}
else
{
@ -533,12 +552,6 @@ public class JDBCSessionManager extends AbstractSessionManager
}
return session;
}
catch (Exception e)
{
LOG.warn("Unable to get session", e);
return null;
}
}
}
@ -883,7 +896,12 @@ public class JDBCSessionManager extends AbstractSessionManager
_context.getContextHandler().handle(load);
if (_exception.get()!=null)
{
//if the session could not be restored, take its id out of the pool of currently-in-use
//session ids
_jdbcSessionIdMgr.removeSession(id);
throw _exception.get();
}
return _reference.get();
}

View File

@ -783,7 +783,7 @@ public class ServletHandler extends ScopedHandler
public ServletHolder addServletWithMapping (String className,String pathSpec)
{
ServletHolder holder = newServletHolder(null);
holder.setName(className+"-"+_servlets.length);
holder.setName(className+"-"+(_servlets==null?0:_servlets.length));
holder.setClassName(className);
addServletWithMapping(holder,pathSpec);
return holder;

View File

@ -53,11 +53,7 @@ public class JdbcTestServer extends AbstractTestServer
super(port, maxInactivePeriod, scavengePeriod, DEFAULT_CONNECTION_URL);
}
public JdbcTestServer (int port, boolean optimize)
{
super(port);
}
/**
* @see org.eclipse.jetty.server.session.AbstractTestServer#newSessionHandler(org.eclipse.jetty.server.SessionManager)
*/

View File

@ -0,0 +1,146 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.server.session;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileWriter;
import java.net.URL;
import java.net.URLClassLoader;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StdErrLog;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.Test;
/**
* ReloadedSessionMissingClassTest
*
*
*
*/
public class ReloadedSessionMissingClassTest
{
@Test
public void testSessionReloadWithMissingClass() throws Exception
{
((StdErrLog)Log.getLogger(org.eclipse.jetty.server.session.JDBCSessionManager.class)).setHideStacks(true);
String contextPath = "/foo";
File srcDir = new File(System.getProperty("basedir"), "src");
File targetDir = new File(System.getProperty("basedir"), "target");
File testDir = new File (srcDir, "test");
File resourcesDir = new File (testDir, "resources");
File unpackedWarDir = new File (targetDir, "foo");
if (unpackedWarDir.exists())
IO.delete(unpackedWarDir);
unpackedWarDir.mkdir();
File webInfDir = new File (unpackedWarDir, "WEB-INF");
webInfDir.mkdir();
File webXml = new File(webInfDir, "web.xml");
String xml =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<web-app xmlns=\"http://java.sun.com/xml/ns/j2ee\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xsi:schemaLocation=\"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd\"\n" +
" version=\"2.4\">\n" +
"\n" +
"<session-config>\n"+
" <session-timeout>1</session-timeout>\n" +
"</session-config>\n"+
"</web-app>";
FileWriter w = new FileWriter(webXml);
w.write(xml);
w.close();
File foobarJar = new File (resourcesDir, "foobar.jar");
File foobarNOfooJar = new File (resourcesDir, "foobarNOfoo.jar");
URL[] foobarUrls = new URL[]{foobarJar.toURI().toURL()};
URL[] barUrls = new URL[]{foobarNOfooJar.toURI().toURL()};
URLClassLoader loaderWithFoo = new URLClassLoader(foobarUrls, Thread.currentThread().getContextClassLoader());
URLClassLoader loaderWithoutFoo = new URLClassLoader(barUrls, Thread.currentThread().getContextClassLoader());
AbstractTestServer server1 = new JdbcTestServer(0);
WebAppContext webApp = server1.addWebAppContext(unpackedWarDir.getCanonicalPath(), contextPath);
webApp.setClassLoader(loaderWithFoo);
webApp.addServlet("Bar", "/bar");
server1.start();
int port1 = server1.getPort();
try
{
HttpClient client = new HttpClient();
client.start();
try
{
// Perform one request to server1 to create a session
ContentResponse response = client.GET("http://localhost:" + port1 + contextPath +"/bar?action=set");
assertEquals( HttpServletResponse.SC_OK, response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
assertTrue(sessionCookie != null);
String sessionId = (String)webApp.getServletContext().getAttribute("foo");
assertNotNull(sessionId);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
//Stop the webapp
webApp.stop();
webApp.setClassLoader(loaderWithoutFoo);
webApp.addServlet("Bar", "/bar");
//restart webapp
webApp.start();
Request request = client.newRequest("http://localhost:" + port1 + contextPath + "/bar?action=get");
request.header("Cookie", sessionCookie);
response = request.send();
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String afterStopSessionId = (String)webApp.getServletContext().getAttribute("foo.session");
assertNotNull(afterStopSessionId);
assertTrue(!afterStopSessionId.equals(sessionId));
}
finally
{
client.stop();
}
}
finally
{
server1.stop();
}
}
}