Issue #4432 Implement get/setSessionTimeout for ServletContext (#4458)

* Issue #4432 Implement get/setSessionTimeout for ServletContext

Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
Jan Bartel 2020-01-20 17:26:55 +01:00 committed by GitHub
parent b520ca6d30
commit 45b3a34170
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 165 additions and 18 deletions

View File

@ -2877,7 +2877,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
@Override
public int getSessionTimeout()
{
// TODO new in 4.0
LOG.warn(UNIMPLEMENTED_USE_SERVLET_CONTEXT_HANDLER, "getSessionTimeout()");
return 0;
}
@ -2888,7 +2887,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
@Override
public void setSessionTimeout(int sessionTimeout)
{
// TODO new in 4.0
LOG.warn(UNIMPLEMENTED_USE_SERVLET_CONTEXT_HANDLER, "setSessionTimeout(int)");
}

View File

@ -133,14 +133,7 @@ public class SessionHandler extends ScopedHandler
HttpSessionIdListener.class,
HttpSessionListener.class
};
/**
* Web.xml session-timeout is set in minutes, but is stored as an int in seconds by HttpSession and
* the sessionmanager. Thus MAX_INT is the max number of seconds that can be set, and MAX_INT/60 is the
* max number of minutes that you can set.
*/
public static final java.math.BigDecimal MAX_INACTIVE_MINUTES = new java.math.BigDecimal(Integer.MAX_VALUE / 60);
@Deprecated(since = "Servlet API 2.1")
static final HttpSessionContext __nullSessionContext = new HttpSessionContext()
{
@ -159,7 +152,7 @@ public class SessionHandler extends ScopedHandler
return Collections.enumeration(Collections.EMPTY_LIST);
}
};
/**
* Setting of max inactive interval for new sessions
* -1 means no timeout

View File

@ -29,6 +29,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
@ -1410,6 +1412,42 @@ public class ServletContextHandler extends ContextHandler
_sessionHandler.setSessionTrackingModes(sessionTrackingModes);
}
@Override
public int getSessionTimeout()
{
if (!isStarting())
throw new IllegalStateException();
if (!_enabled)
throw new UnsupportedOperationException();
int timeout = -1;
if (_sessionHandler != null)
{
timeout = _sessionHandler.getMaxInactiveInterval();
}
return (int)TimeUnit.SECONDS.toMinutes(timeout);
}
@Override
public void setSessionTimeout(int sessionTimeout)
{
if (!isStarting())
throw new IllegalStateException();
if (!_enabled)
throw new UnsupportedOperationException();
if (_sessionHandler != null)
{
long tmp = TimeUnit.MINUTES.toSeconds(sessionTimeout);
if (tmp > Integer.MAX_VALUE)
tmp = Integer.MAX_VALUE;
if (tmp < Integer.MIN_VALUE)
tmp = Integer.MIN_VALUE;
_sessionHandler.setMaxInactiveInterval((int)tmp);
}
}
@Override
public void addListener(String className)
{

View File

@ -109,6 +109,20 @@ public class ServletContextHandlerTest
public static class MySCI implements ServletContainerInitializer
{
boolean callSessionTimeouts;
int timeout;
public MySCI(boolean callSessionTimeouts, int timeout)
{
this.callSessionTimeouts = callSessionTimeouts;
this.timeout = timeout;
}
public MySCI()
{
this(false, -1);
}
@Override
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException
{
@ -116,7 +130,20 @@ public class ServletContextHandlerTest
if (ctx.getAttribute("MySCI.startup") != null)
throw new IllegalStateException("MySCI already called");
ctx.setAttribute("MySCI.startup", Boolean.TRUE);
ctx.addListener(new MyContextListener());
ctx.addListener(new MyContextListener(callSessionTimeouts, timeout));
if (callSessionTimeouts)
{
try
{
ctx.setSessionTimeout(timeout);
ctx.setAttribute("MYSCI.setSessionTimeout", Boolean.TRUE);
ctx.setAttribute("MYSCI.getSessionTimeout", Integer.valueOf(ctx.getSessionTimeout()));
}
catch (Exception e)
{
ctx.setAttribute("MYSCI.sessionTimeoutFailure", e);
}
}
}
}
@ -143,12 +170,50 @@ public class ServletContextHandlerTest
public static class MyContextListener implements ServletContextListener
{
boolean callSessionTimeouts;
int timeout;
public MyContextListener(boolean callSessionTimeouts, int timeout)
{
this.callSessionTimeouts = callSessionTimeouts;
this.timeout = timeout;
}
public MyContextListener()
{
this(false, -1);
}
@Override
public void contextInitialized(ServletContextEvent sce)
{
assertNull(sce.getServletContext().getAttribute("MyContextListener.contextInitialized"));
sce.getServletContext().setAttribute("MyContextListener.contextInitialized", Boolean.TRUE);
if (callSessionTimeouts)
{
try
{
sce.getServletContext().setSessionTimeout(timeout);
sce.getServletContext().setAttribute("MyContextListener.setSessionTimeout", Boolean.FALSE);
}
catch (UnsupportedOperationException e)
{
//Should NOT be able to call setSessionTimeout from this SCL
sce.getServletContext().setAttribute("MyContextListener.setSessionTimeout", Boolean.TRUE);
}
try
{
sce.getServletContext().getSessionTimeout();
sce.getServletContext().setAttribute("MyContextListener.getSessionTimeout", Boolean.FALSE);
}
catch (UnsupportedOperationException e)
{
//Should NOT be able to call getSessionTimeout from this SCL
sce.getServletContext().setAttribute("MyContextListener.getSessionTimeout", Boolean.TRUE);
}
}
}
@Override
@ -404,6 +469,28 @@ public class ServletContextHandlerTest
_server.stop();
_server.join();
}
@Test
public void testGetSetSessionTimeout() throws Exception
{
ContextHandlerCollection contexts = new ContextHandlerCollection();
_server.setHandler(contexts);
Integer timeout = Integer.valueOf(100);
ServletContextHandler root = new ServletContextHandler(contexts, "/", ServletContextHandler.SESSIONS);
root.addBean(new MySCIStarter(root.getServletContext(), new MySCI(true, timeout.intValue())), true);
_server.start();
//test can set session timeout from ServletContainerInitializer
assertTrue((Boolean)root.getServletContext().getAttribute("MYSCI.setSessionTimeout"));
//test can get session timeout from ServletContainerInitializer
assertEquals(timeout, (Integer)root.getServletContext().getAttribute("MYSCI.getSessionTimeout"));
assertNull(root.getAttribute("MYSCI.sessionTimeoutFailure"));
//test can't get session timeout from ContextListener that is not from annotation or web.xml
assertTrue((Boolean)root.getServletContext().getAttribute("MyContextListener.getSessionTimeout"));
//test can't set session timeout from ContextListener that is not from annotation or web.xml
assertTrue((Boolean)root.getServletContext().getAttribute("MyContextListener.setSessionTimeout"));
}
@Test
public void testAddSessionListener() throws Exception

View File

@ -30,6 +30,8 @@ import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.servlet.DispatcherType;
import javax.servlet.MultipartConfigElement;
import javax.servlet.SessionTrackingMode;
@ -650,11 +652,11 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
XmlParser.Node tNode = node.get("session-timeout");
if (tNode != null)
{
java.math.BigDecimal asDecimal = new java.math.BigDecimal(tNode.toString(false, true));
if (asDecimal.compareTo(org.eclipse.jetty.server.session.SessionHandler.MAX_INACTIVE_MINUTES) > 0)
throw new IllegalStateException("Max session-timeout in minutes is " + org.eclipse.jetty.server.session.SessionHandler.MAX_INACTIVE_MINUTES);
context.getSessionHandler().setMaxInactiveInterval(asDecimal.intValueExact() * 60);
long val = Long.parseLong(tNode.toString(false, true));
val = TimeUnit.MINUTES.toSeconds(val);
if (val > Integer.MAX_VALUE)
throw new IllegalStateException("Max session-timeout in minutes is " + TimeUnit.SECONDS.toMinutes(Integer.MAX_VALUE));
context.getServletContext().setSessionTimeout((int)val);
}
//Servlet Spec 3.0

View File

@ -107,6 +107,29 @@ public class AnnotatedListener implements HttpSessionListener, HttpSessionAttrib
throw new IllegalStateException("AnnotatedListener already initialized");
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclInjectWebListenerTest", Boolean.valueOf(maxAmount != null));
boolean setSessionTimeout;
try
{
sce.getServletContext().setSessionTimeout(180);
setSessionTimeout = true;
}
catch (Exception e)
{
setSessionTimeout = false;
}
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclSetSessionTimeout", Boolean.valueOf(setSessionTimeout));
boolean getSessionTimeout;
try
{
getSessionTimeout = (sce.getServletContext().getSessionTimeout() == 180);
}
catch (Exception e)
{
getSessionTimeout = false;
}
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclGetSessionTimeout", Boolean.valueOf(getSessionTimeout));
}
public void requestCompleted(ServletRequestEvent rre)

View File

@ -275,6 +275,12 @@ public class AnnotationTest extends HttpServlet
Boolean annotatedListenerInject = (Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.sclInjectWebListenerTest");
out.println("<p><b>Result: " + (annotatedListenerInject.booleanValue() ? "<span class=\"pass\">PASS" : "<span class=\"fail\">FAIL") + "</span></b></p>");
out.println("<h2>ServletContextListener as @WebListener Get/Set Session Timeout</h2>");
out.println("<p><b>getSessionTimeout Result: " +
((Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.sclGetSessionTimeout") ? "<span class=\"pass\">PASS" : "<span class=\"fail\">FAIL") + "</span></b></p>");
out.println("<p><b>setSessionTimeout Result: " +
((Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.sclSetSessionTimeout") ? "<span class=\"pass\">PASS" : "<span class=\"fail\">FAIL") + "</span></b></p>");
out.println("<h2>Programmatic Listener Injected</h2>");
Boolean programListenerInject = (Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.programListenerInjectTest");
out.println("<p><b>Result: " + (programListenerInject.booleanValue() ? "<span class=\"pass\">PASS" : "<span class=\"fail\">FAIL") + "</span></b></p>");