402706 HttpSession.setMaxInactiveInterval(int) does not change JDBCSession expiry

This commit is contained in:
Jan Bartel 2013-03-11 19:30:52 +11:00
parent 11442814fa
commit 0834ad259c
3 changed files with 235 additions and 12 deletions

View File

@ -62,6 +62,7 @@ import org.eclipse.jetty.util.log.Logger;
public class JDBCSessionIdManager extends AbstractSessionIdManager
{
final static Logger LOG = SessionHandler.LOG;
public final static int MAX_INTERVAL_NOT_SET = -999;
protected final HashSet<String> _sessionIds = new HashSet<String>();
protected Server _server;
@ -629,6 +630,9 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
* Set up the tables in the database
* @throws SQLException
*/
/**
* @throws SQLException
*/
private void prepareTables()
throws SQLException
{
@ -671,9 +675,38 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
_createSessionTable = "create table "+_sessionTable+" ("+_sessionTableRowId+" varchar(120), sessionId varchar(120), "+
" contextPath varchar(60), virtualHost varchar(60), lastNode varchar(60), accessTime "+longType+", "+
" lastAccessTime "+longType+", createTime "+longType+", cookieTime "+longType+", "+
" lastSavedTime "+longType+", expiryTime "+longType+", map "+blobType+", primary key("+_sessionTableRowId+"))";
" lastSavedTime "+longType+", expiryTime "+longType+", maxInterval "+longType+", map "+blobType+", primary key("+_sessionTableRowId+"))";
connection.createStatement().executeUpdate(_createSessionTable);
}
else
{
//session table exists, check it has maxinterval column
ResultSet colResult = null;
try
{
colResult = metaData.getColumns(null, null,_dbAdaptor.convertIdentifier(_sessionTable), _dbAdaptor.convertIdentifier("maxInterval"));
}
catch (SQLException s)
{
LOG.warn("Problem checking if "+_sessionTable+" table contains maxInterval column. Ensure table contains column definition: \"maxInterval long not null default -999\"");
throw s;
}
if (!colResult.next())
{
try
{
//add the maxinterval column
String longType = _dbAdaptor.getLongType();
connection.createStatement().executeUpdate("alter table "+_sessionTable+" add maxInterval "+longType+" not null default "+MAX_INTERVAL_NOT_SET);
}
catch (SQLException s)
{
LOG.warn("Problem adding maxInterval column. Ensure table contains column definition: \"maxInterval long not null default -999\"");
throw s;
}
}
}
//make some indexes on the JettySessions table
String index1 = "idx_"+_sessionTable+"_expiry";
@ -701,20 +734,20 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
//set up some strings representing the statements for session manipulation
_insertSession = "insert into "+_sessionTable+
" ("+_sessionTableRowId+", sessionId, contextPath, virtualHost, lastNode, accessTime, lastAccessTime, createTime, cookieTime, lastSavedTime, expiryTime, map) "+
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
" ("+_sessionTableRowId+", sessionId, contextPath, virtualHost, lastNode, accessTime, lastAccessTime, createTime, cookieTime, lastSavedTime, expiryTime, maxInterval, map) "+
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
_deleteSession = "delete from "+_sessionTable+
" where "+_sessionTableRowId+" = ?";
_updateSession = "update "+_sessionTable+
" set sessionId = ?, lastNode = ?, accessTime = ?, lastAccessTime = ?, lastSavedTime = ?, expiryTime = ?, map = ? where "+_sessionTableRowId+" = ?";
" set sessionId = ?, lastNode = ?, accessTime = ?, lastAccessTime = ?, lastSavedTime = ?, expiryTime = ?, maxInterval = ?, map = ? where "+_sessionTableRowId+" = ?";
_updateSessionNode = "update "+_sessionTable+
" set lastNode = ? where "+_sessionTableRowId+" = ?";
_updateSessionAccessTime = "update "+_sessionTable+
" set lastNode = ?, accessTime = ?, lastAccessTime = ?, lastSavedTime = ?, expiryTime = ? where "+_sessionTableRowId+" = ?";
" set lastNode = ?, accessTime = ?, lastAccessTime = ?, lastSavedTime = ?, expiryTime = ?, maxInterval = ? where "+_sessionTableRowId+" = ?";
}

View File

@ -160,10 +160,12 @@ public class JDBCSessionManager extends AbstractSessionManager
* @param created
* @param accessed
*/
protected Session (String sessionId, String rowId, long created, long accessed)
protected Session (String sessionId, String rowId, long created, long accessed, long maxInterval)
{
super(JDBCSessionManager.this, created, accessed, sessionId);
_rowId = rowId;
super.setMaxInactiveInterval((int)maxInterval); //restore the session's previous inactivity interval setting
_expiryTime = (maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L));
}
@ -279,6 +281,33 @@ public class JDBCSessionManager extends AbstractSessionManager
}
}
/**
* Change the max idle time for this session. This recalculates the expiry time.
* @see org.eclipse.jetty.server.session.AbstractSession#setMaxInactiveInterval(int)
*/
@Override
public void setMaxInactiveInterval(int secs)
{
synchronized (this)
{
super.setMaxInactiveInterval(secs);
int maxInterval=getMaxInactiveInterval();
_expiryTime = (maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L));
//force the session to be written out right now
try
{
updateSessionAccessTime(this);
}
catch (Exception e)
{
LOG.warn("Problem saving changed max idle time for session "+ this, e);
}
}
}
/**
@ -346,7 +375,7 @@ public class JDBCSessionManager extends AbstractSessionManager
return "Session rowId="+_rowId+",id="+getId()+",lastNode="+_lastNode+
",created="+getCreationTime()+",accessed="+getAccessed()+
",lastAccessed="+getLastAccessedTime()+",cookieSet="+_cookieSet+
",lastSaved="+_lastSaved+",expiry="+_expiryTime;
",maxInterval="+getMaxInactiveInterval()+",lastSaved="+_lastSaved+",expiry="+_expiryTime;
}
}
@ -842,6 +871,9 @@ public class JDBCSessionManager extends AbstractSessionManager
final AtomicReference<Exception> _exception = new AtomicReference<Exception>();
Runnable load = new Runnable()
{
/**
* @see java.lang.Runnable#run()
*/
@SuppressWarnings("unchecked")
public void run()
{
@ -855,7 +887,15 @@ public class JDBCSessionManager extends AbstractSessionManager
ResultSet result = statement.executeQuery();
if (result.next())
{
session = new Session(id, result.getString(_jdbcSessionIdMgr._sessionTableRowId), result.getLong("createTime"), result.getLong("accessTime"));
long maxInterval = result.getLong("maxInterval");
if (maxInterval == JDBCSessionIdManager.MAX_INTERVAL_NOT_SET)
{
maxInterval = getMaxInactiveInterval(); //if value not saved for maxInactiveInterval, use current value from sessionmanager
}
session = new Session(id, result.getString(_jdbcSessionIdMgr._sessionTableRowId),
result.getLong("createTime"),
result.getLong("accessTime"),
maxInterval);
session.setCookieSet(result.getLong("cookieTime"));
session.setLastAccessedTime(result.getLong("lastAccessTime"));
session.setLastNode(result.getString("lastNode"));
@ -939,6 +979,7 @@ public class JDBCSessionManager extends AbstractSessionManager
statement.setLong(9, session.getCookieSet());//time cookie was set
statement.setLong(10, now); //last saved time
statement.setLong(11, session.getExpiryTime());
statement.setLong(12, session.getMaxInactiveInterval());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
@ -946,7 +987,8 @@ public class JDBCSessionManager extends AbstractSessionManager
byte[] bytes = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
statement.setBinaryStream(12, bais, bytes.length);//attribute map as blob
statement.setBinaryStream(13, bais, bytes.length);//attribute map as blob
statement.executeUpdate();
session.setRowId(rowId); //set it on the in-memory data as well as in db
@ -989,6 +1031,7 @@ public class JDBCSessionManager extends AbstractSessionManager
statement.setLong(4, data.getLastAccessedTime()); //lastAccessTime
statement.setLong(5, now); //last saved time
statement.setLong(6, data.getExpiryTime());
statement.setLong(7, data.getMaxInactiveInterval());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
@ -996,8 +1039,8 @@ public class JDBCSessionManager extends AbstractSessionManager
byte[] bytes = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
statement.setBinaryStream(7, bais, bytes.length);//attribute map as blob
statement.setString(8, data.getRowId()); //rowId
statement.setBinaryStream(8, bais, bytes.length);//attribute map as blob
statement.setString(9, data.getRowId()); //rowId
statement.executeUpdate();
data.setLastSaved(now);
@ -1063,7 +1106,9 @@ public class JDBCSessionManager extends AbstractSessionManager
statement.setLong(3, data.getLastAccessedTime());
statement.setLong(4, now);
statement.setLong(5, data.getExpiryTime());
statement.setString(6, data.getRowId());
statement.setLong(6, data.getMaxInactiveInterval());
statement.setString(7, data.getRowId());
statement.executeUpdate();
data.setLastSaved(now);
statement.close();

View File

@ -0,0 +1,145 @@
//
// ========================================================================
// 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.assertTrue;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.junit.Test;
/**
* ModifyMaxInactiveIntervalTest
*
*
*
*/
public class ModifyMaxInactiveIntervalTest
{
public static int inactive = 4;
public static int newMaxInactive = 20;
public static int scavenge = 1;
@Test
public void testSessionExpiryAfterModifiedMaxInactiveInterval() throws Exception
{
AbstractTestServer server = new JdbcTestServer(0,inactive,scavenge);
ServletContextHandler ctxA = server.addContext("/mod");
ctxA.addServlet(TestModServlet.class, "/test");
server.start();
int port=server.getPort();
try
{
HttpClient client = new HttpClient();
client.start();
try
{
// Perform a request to create a session
ContentResponse response = client.GET("http://localhost:" + port + "/mod/test?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
//do another request to change the maxinactive interval
Request request = client.newRequest("http://localhost:" + port + "/mod/test?action=change&val="+newMaxInactive);
request.header("Cookie", sessionCookie);
response = request.send();
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
//wait for longer than the old inactive interval
Thread.currentThread().sleep(10*1000L);
//do another request using the cookie to ensure the session is still there
request= client.newRequest("http://localhost:" + port + "/mod/test?action=test");
request.header("Cookie", sessionCookie);
response = request.send();
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
}
finally
{
client.stop();
}
}
finally
{
server.stop();
}
}
public static class TestModServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String action = request.getParameter("action");
if ("create".equals(action))
{
HttpSession session = request.getSession(true);
return;
}
if ("change".equals(action))
{
HttpSession session = request.getSession(false);
if (session == null)
throw new ServletException("Session is null for action=change");
String tmp = request.getParameter("val");
int interval = -1;
interval = (tmp==null?-1:Integer.parseInt(tmp));
if (interval > 0)
session.setMaxInactiveInterval(interval);
return;
}
if ("test".equals(action))
{
HttpSession session = request.getSession(false);
if (session == null)
throw new ServletException("Session does not exist");
assertEquals(ModifyMaxInactiveIntervalTest.newMaxInactive, session.getMaxInactiveInterval());
return;
}
}
}
}