Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-9.4.x-cleanup-webapp-context

This commit is contained in:
Greg Wilkins 2018-11-28 10:58:55 +01:00
commit e08a4e55dd
21 changed files with 756 additions and 674 deletions

4
Jenkinsfile vendored
View File

@ -10,7 +10,6 @@ pipeline {
options { timeout(time: 120, unit: 'MINUTES') }
steps {
mavenBuild("jdk8", "-Pmongodb install")
junit '**/target/surefire-reports/TEST-*.xml,**/target/failsafe-reports/TEST-*.xml'
// Collect up the jacoco execution results (only on main build)
jacoco inclusionPattern: '**/org/eclipse/jetty/**/*.class',
exclusionPattern: '' +
@ -95,6 +94,7 @@ def mavenBuild(jdk, cmdline) {
jdk: "$jdk",
publisherStrategy: 'EXPLICIT',
globalMavenSettingsConfig: settingsName,
options: [junitPublisher(disabled: false)],
mavenOpts: mavenOpts,
mavenLocalRepo: localRepo) {
// Some common Maven command line + provided command line
@ -102,4 +102,4 @@ def mavenBuild(jdk, cmdline) {
}
}
// vim: et:ts=2:sw=2:ft=groovy
// vim: et:ts=2:sw=2:ft=groovy

View File

@ -29,7 +29,7 @@
<executions>
<execution>
<id>copy-base-assembly-tree</id>
<phase>package</phase>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>

View File

@ -110,11 +110,11 @@ The maximum number of requests to be serviced at a time. The default is 10.
maxPriority::
The maximum valid priority that can be assigned to a request.
A request with a high priority value is more important than a request with a low priority value. The default is 10.
waitMS::
waitMs::
The length of time, in milliseconds, to wait while trying to accept a new request.
Used when the maxRequests limit is reached.
Default is 50 ms.
suspendMS::
suspendMs::
Length of time, in milliseconds, that the request will be suspended if it is not accepted immediately.
If not set, the container's default suspend period applies. Default is -1 ms.
managedAttr::

View File

@ -546,7 +546,7 @@
</excludes>
<!-- No point defining -Xbootclasspath as the actual OSGi VM is run as a forked process by pax-exam -->
<!-- But we do pass the sys property of the alpn-boot jar so that it can be configured inside tests -->
<argLine>-Dmortbay-alpn-boot=${settings.localRepository}/org/mortbay/jetty/alpn/alpn-boot/${alpn.version}/alpn-boot-${alpn.version}.jar</argLine>
<argLine>-Dmortbay-alpn-boot=${settings.localRepository}/org/mortbay/jetty/alpn/alpn-boot/${alpn.version}/alpn-boot-${alpn.version}.jar -Dconscrypt-version=${conscrypt.version}</argLine>
</configuration>
</plugin>
</plugins>
@ -573,7 +573,7 @@
<dependency>
<groupId>org.conscrypt</groupId>
<artifactId>conscrypt-openjdk-uber</artifactId>
<version>1.0.0.RC11</version>
<version>${conscrypt.version}</version>
<scope>test</scope>
</dependency>
<dependency>
@ -601,6 +601,7 @@
<excludes>
<exclude>**/TestJettyOSGiBootHTTP2</exclude>
</excludes>
<argLine>-Dconscrypt-version=${conscrypt.version}</argLine>
</configuration>
</plugin>
</plugins>

View File

@ -100,9 +100,9 @@ public class TestJettyOSGiBootHTTP2Conscrypt
res.add(CoreOptions.systemProperty("jetty.alpn.protocols").value("h2,http/1.1"));
res.add(CoreOptions.systemProperty("jetty.sslContext.provider").value("Conscrypt"));
res.add(wrappedBundle(mavenBundle().groupId("org.conscrypt").artifactId("conscrypt-openjdk-uber").version("1.1.4"))
res.add(wrappedBundle(mavenBundle().groupId("org.conscrypt").artifactId("conscrypt-openjdk-uber").versionAsInProject())
.imports("javax.net.ssl,*")
.exports("org.conscrypt;version=1.1.4")
.exports("org.conscrypt;version="+System.getProperty("conscrypt-version"))
.instructions("Bundle-NativeCode=META-INF/native/libconscrypt_openjdk_jni-linux-x86_64.so")
.start());
res.add(mavenBundle().groupId("org.eclipse.jetty.osgi").artifactId("jetty-osgi-alpn").versionAsInProject().noStart());

View File

@ -151,8 +151,9 @@ public abstract class AbstractSessionCache extends ContainerLifeCycle implements
/**
* Remove the session with this identity from the store
*
* @param id the id
* @return true if removed false otherwise
* @return Session that was removed or null
*/
public abstract Session doDelete (String id);
@ -727,12 +728,8 @@ public abstract class AbstractSessionCache extends ContainerLifeCycle implements
/**
* @see org.eclipse.jetty.server.session.SessionCache#renewSessionId(java.lang.String, java.lang.String)
*/
@Override
public Session renewSessionId (String oldId, String newId)
public Session renewSessionId (String oldId, String newId, String oldExtendedId, String newExtendedId)
throws Exception
{
if (StringUtil.isBlank(oldId))
@ -741,17 +738,40 @@ public abstract class AbstractSessionCache extends ContainerLifeCycle implements
throw new IllegalArgumentException ("New session id is null");
Session session = get(oldId);
if (session == null)
return null;
renewSessionId(session, newId, newExtendedId);
return session;
}
/**
* Swap the id on a session.
*
* @param session the session for which to do the swap
* @param newId the new id
* @param newExtendedId the full id plus node id
*
* @throws Exception if there was a failure saving the change
*/
protected void renewSessionId (Session session, String newId, String newExtendedId)
throws Exception
{
if (session == null)
return;
try (Lock lock = session.lock())
{
String oldId = session.getId();
session.checkValidForWrite(); //can't change id on invalid session
session.getSessionData().setId(newId);
session.getSessionData().setLastSaved(0); //pretend that the session has never been saved before to get a full save
session.getSessionData().setDirty(true); //ensure we will try to write the session out
session.getSessionData().setDirty(true); //ensure we will try to write the session out
session.setExtendedId(newExtendedId); //remember the new extended id
session.setIdChanged(true); //session id changed
doPutIfAbsent(newId, session); //put the new id into our map
doDelete (oldId); //take old out of map
if (_sessionDataStore != null)
{
_sessionDataStore.delete(oldId); //delete the session data with the old id
@ -759,7 +779,6 @@ public abstract class AbstractSessionCache extends ContainerLifeCycle implements
}
if (LOG.isDebugEnabled())
LOG.debug ("Session id {} swapped for new id {}", oldId, newId);
return session;
}
}

View File

@ -91,16 +91,41 @@ public interface SessionCache extends LifeCycle
*/
Session newSession (SessionData data);
/**
* Change the id of a session.
*
* This method has been superceded by the 4 arg renewSessionId method and
* should no longer be called.
*
* @param oldId the old id
* @param newId the new id
* @return the changed Session
* @throws Exception if anything went wrong
* @deprecated use
* {@link #renewSessionId(String oldId, String newId, String oldExtendedId, String newExtendedId)}
*/
@Deprecated
default Session renewSessionId(String oldId, String newId) throws Exception
{
return null;
}
/**
* Change the id of a Session.
*
* @param oldId the current session id
* @param newId the new session id
* @param oldExtendedId the current extended session id
* @param newExtendedId the new extended session id
* @return the Session after changing its id
* @throws Exception if any error occurred
*/
Session renewSessionId (String oldId, String newId) throws Exception;
default Session renewSessionId(String oldId, String newId, String oldExtendedId, String newExtendedId) throws Exception
{
return renewSessionId(oldId, newId);
}
/**

View File

@ -18,6 +18,8 @@
package org.eclipse.jetty.server.session;
import static java.lang.Math.round;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
@ -65,8 +67,6 @@ import org.eclipse.jetty.util.thread.Locker.Lock;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
import static java.lang.Math.round;
/* ------------------------------------------------------------ */
/**
* SessionHandler.
@ -343,6 +343,60 @@ public class SessionHandler extends ScopedHandler
_sessionListeners.clear();
_sessionIdListeners.clear();
}
/**
* Call the session lifecycle listeners
* @param session the session on which to call the lifecycle listeners
*/
protected void callSessionDestroyedListeners (Session session)
{
if (session == null)
return;
if (_sessionListeners!=null)
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (int i = _sessionListeners.size()-1; i>=0; i--)
{
_sessionListeners.get(i).sessionDestroyed(event);
}
}
}
/**
* Call the session lifecycle listeners
* @param session the session on which to call the lifecycle listeners
*/
protected void callSessionCreatedListeners (Session session)
{
if (session == null)
return;
if (_sessionListeners!=null)
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (int i = _sessionListeners.size()-1; i>=0; i--)
{
_sessionListeners.get(i).sessionCreated(event);
}
}
}
protected void callSessionIdListeners (Session session, String oldId)
{
//inform the listeners
if (!_sessionIdListeners.isEmpty())
{
HttpSessionEvent event = new HttpSessionEvent(session);
for (HttpSessionIdListener l:_sessionIdListeners)
{
l.sessionIdChanged(event, oldId);
}
}
}
/* ------------------------------------------------------------ */
/**
@ -793,15 +847,10 @@ public class SessionHandler extends ScopedHandler
_sessionCache.put(id, session);
_sessionsCreatedStats.increment();
if (request.isSecure())
if (request!=null && request.isSecure())
session.setAttribute(Session.SESSION_CREATED_SECURE, Boolean.TRUE);
if (_sessionListeners!=null)
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (HttpSessionListener listener : _sessionListeners)
listener.sessionCreated(event);
}
callSessionCreatedListeners(session);
return session;
}
@ -1183,24 +1232,15 @@ public class SessionHandler extends ScopedHandler
{
try
{
Session session = _sessionCache.renewSessionId (oldId, newId); //swap the id over
Session session = _sessionCache.renewSessionId (oldId, newId, oldExtendedId, newExtendedId); //swap the id over
if (session == null)
{
//session doesn't exist on this context
return;
}
session.setExtendedId(newExtendedId); //remember the extended id
//inform the listeners
if (!_sessionIdListeners.isEmpty())
{
HttpSessionEvent event = new HttpSessionEvent(session);
for (HttpSessionIdListener l:_sessionIdListeners)
{
l.sessionIdChanged(event, oldId);
}
}
callSessionIdListeners(session, oldId);
}
catch (Exception e)
{
@ -1208,28 +1248,62 @@ public class SessionHandler extends ScopedHandler
}
}
/**
* Record length of time session has been active. Called when the
* session is about to be invalidated.
*
* @param session the session whose time to record
*/
protected void recordSessionTime (Session session)
{
_sessionTimeStats.record(round((System.currentTimeMillis() - session.getSessionData().getCreated())/1000.0));
}
/* ------------------------------------------------------------ */
/**
* Called when a session has expired.
* Called by SessionIdManager to remove a session that has been invalidated,
* either by this context or another context. Also called by
* SessionIdManager when a session has expired in either this context or
* another context.
*
* @param id the id to invalidate
* @param id the session id to invalidate
*/
public void invalidate (String id)
{
if (StringUtil.isBlank(id))
return;
try
{
//remove the session and call the destroy listeners
Session session = removeSession(id, true);
{
// Remove the Session object from the session cache and any backing
// data store
Session session = _sessionCache.delete(id);
if (session != null)
{
_sessionTimeStats.record(round((System.currentTimeMillis() - session.getSessionData().getCreated())/1000.0));
session.finishInvalidate();
//start invalidating if it is not already begun, and call the listeners
try
{
if (session.beginInvalidate())
{
try
{
callSessionDestroyedListeners(session);
}
catch (Exception e)
{
LOG.warn("Session listener threw exception", e);
}
//call the attribute removed listeners and finally mark it as invalid
session.finishInvalidate();
}
}
catch (IllegalStateException e)
{
if (LOG.isDebugEnabled()) LOG.debug("Session {} already invalid", session);
LOG.ignore(e);
}
}
}
catch (Exception e)

View File

@ -29,7 +29,7 @@ import java.net.URLClassLoader;
import org.eclipse.jetty.util.component.Dumpable;
import org.junit.jupiter.api.Test;
public class ClassLoaderDumptTest
public class ClassLoaderDumpTest
{
@Test
public void testSimple() throws Exception
@ -48,8 +48,8 @@ public class ClassLoaderDumptTest
StringBuilder out = new StringBuilder();
server.dump(out);
String dump = out.toString();
assertThat(dump,containsString("+-SimpleLoader"));
assertThat(dump,containsString("+>"+Server.class.getClassLoader()));
assertThat(dump,containsString("+- SimpleLoader"));
assertThat(dump,containsString("+> "+Server.class.getClassLoader()));
}
@Test
@ -69,9 +69,9 @@ public class ClassLoaderDumptTest
StringBuilder out = new StringBuilder();
server.dump(out);
String dump = out.toString();
assertThat(dump,containsString("+-ParentedLoader"));
assertThat(dump,containsString("| +>"+Server.class.getClassLoader()));
assertThat(dump,containsString("+>"+Server.class.getClassLoader()));
assertThat(dump,containsString("+- ParentedLoader"));
assertThat(dump,containsString("| +> "+Server.class.getClassLoader()));
assertThat(dump,containsString("+> "+Server.class.getClassLoader()));
}
@Test
@ -98,10 +98,10 @@ public class ClassLoaderDumptTest
StringBuilder out = new StringBuilder();
server.dump(out);
String dump = out.toString();
assertThat(dump,containsString("+-TopLoader"));
assertThat(dump,containsString("| +>MiddleLoader"));
assertThat(dump,containsString("| +>"+Server.class.getClassLoader()));
assertThat(dump,containsString("+>"+Server.class.getClassLoader()));
assertThat(dump,containsString("+- TopLoader"));
assertThat(dump,containsString("| +> MiddleLoader"));
assertThat(dump,containsString("| +> "+Server.class.getClassLoader()));
assertThat(dump,containsString("+> "+Server.class.getClassLoader()));
}
@Test
@ -122,10 +122,10 @@ public class ClassLoaderDumptTest
StringBuilder out = new StringBuilder();
server.dump(out);
String dump = out.toString();
assertThat(dump,containsString("+-TopLoader"));
assertThat(dump,containsString("| +>DumpableClassLoader"));
assertThat(dump,not(containsString("| +>"+Server.class.getClassLoader())));
assertThat(dump,containsString("+>"+Server.class.getClassLoader()));
assertThat(dump,containsString("+- TopLoader"));
assertThat(dump,containsString("| +> DumpableClassLoader"));
assertThat(dump,not(containsString("| +> "+Server.class.getClassLoader())));
assertThat(dump,containsString("+> "+Server.class.getClassLoader()));
}
public static class DumpableClassLoader extends ClassLoader implements Dumpable
@ -184,15 +184,15 @@ public class ClassLoaderDumptTest
server.dump(out);
String dump = out.toString();
// System.err.println(dump);
assertThat(dump,containsString("+-TopLoader"));
assertThat(dump,containsString("| | +>file:/ONE"));
assertThat(dump,containsString("| | +>file:/TWO"));
assertThat(dump,containsString("| | +>file:/THREE"));
assertThat(dump,containsString("| +>MiddleLoader"));
assertThat(dump,containsString("| | +>file:/one"));
assertThat(dump,containsString("| | +>file:/two"));
assertThat(dump,containsString("| | +>file:/three"));
assertThat(dump,containsString("| +>"+Server.class.getClassLoader()));
assertThat(dump,containsString("+>"+Server.class.getClassLoader()));
assertThat(dump,containsString("+- TopLoader"));
assertThat(dump,containsString("| | +> file:/ONE"));
assertThat(dump,containsString("| | +> file:/TWO"));
assertThat(dump,containsString("| | +> file:/THREE"));
assertThat(dump,containsString("| +> MiddleLoader"));
assertThat(dump,containsString("| | +> file:/one"));
assertThat(dump,containsString("| | +> file:/two"));
assertThat(dump,containsString("| | +> file:/three"));
assertThat(dump,containsString("| +> "+Server.class.getClassLoader()));
assertThat(dump,containsString("+> "+Server.class.getClassLoader()));
}
}

View File

@ -100,7 +100,7 @@ public interface Dumpable
}
catch (Throwable th)
{
out.append("=>").append(th.toString()).append("\n");
out.append("=> ").append(th.toString()).append("\n");
}
}
@ -134,12 +134,12 @@ public interface Dumpable
for (Iterator<Object> i = container.getBeans().iterator(); i.hasNext();)
{
Object bean = i.next();
String nextIndent = indent + ((i.hasNext() || size>0) ? "| " : " ");
String nextIndent = indent + ((i.hasNext() || size>0) ? "| " : " ");
if (bean instanceof LifeCycle)
{
if (container.isManaged(bean))
{
out.append(indent).append("+=");
out.append(indent).append("+= ");
if (bean instanceof Dumpable)
((Dumpable)bean).dump(out,nextIndent);
else
@ -147,7 +147,7 @@ public interface Dumpable
}
else if (containerLifeCycle != null && containerLifeCycle.isAuto(bean))
{
out.append(indent).append("+?");
out.append(indent).append("+? ");
if (bean instanceof Dumpable)
((Dumpable)bean).dump(out,nextIndent);
else
@ -155,18 +155,18 @@ public interface Dumpable
}
else
{
out.append(indent).append("+~");
out.append(indent).append("+~ ");
dumpObject(out, bean);
}
}
else if (containerLifeCycle != null && containerLifeCycle.isUnmanaged(bean))
{
out.append(indent).append("+~");
out.append(indent).append("+~ ");
dumpObject(out, bean);
}
else
{
out.append(indent).append("+-");
out.append(indent).append("+- ");
if (bean instanceof Dumpable)
((Dumpable)bean).dump(out,nextIndent);
else
@ -179,8 +179,8 @@ public interface Dumpable
for (Iterator i = ((Iterable<?>)object).iterator(); i.hasNext();)
{
Object item = i.next();
String nextIndent = indent + ((i.hasNext() || size>0) ? "| " : " ");
out.append(indent).append("+:");
String nextIndent = indent + ((i.hasNext() || size>0) ? "| " : " ");
out.append(indent).append("+: ");
if (item instanceof Dumpable)
((Dumpable)item).dump(out,nextIndent);
else
@ -192,8 +192,8 @@ public interface Dumpable
for (Iterator<? extends Map.Entry<?, ?>> i = ((Map<?,?>)object).entrySet().iterator(); i.hasNext();)
{
Map.Entry entry = i.next();
String nextIndent = indent + ((i.hasNext() || size>0) ? "| " : " ");
out.append(indent).append("+@").append(String.valueOf(entry.getKey())).append('=');
String nextIndent = indent + ((i.hasNext() || size>0) ? "| " : " ");
out.append(indent).append("+@ ").append(String.valueOf(entry.getKey())).append('=');
Object item = entry.getValue();
if (item instanceof Dumpable)
((Dumpable)item).dump(out,nextIndent);
@ -209,13 +209,12 @@ public interface Dumpable
for (Object item : extraChildren)
{
i++;
String nextIndent = indent + (i<size ? "| " : " ");
out.append(indent).append("+>");
String nextIndent = indent + (i<size ? "| " : " ");
out.append(indent).append("+> ");
if (item instanceof Dumpable)
((Dumpable)item).dump(out,nextIndent);
else
dumpObjects(out, nextIndent, item);
}
}
}

View File

@ -215,59 +215,59 @@ public class ContainerLifeCycleTest
a0.addBean(aa0);
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+?ContainerLife");
dump = check(dump, "+? ContainerLife");
ContainerLifeCycle aa1 = new ContainerLifeCycle();
a0.addBean(aa1);
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+?ContainerLife");
dump = check(dump, "+?ContainerLife");
dump = check(dump, "+? ContainerLife");
dump = check(dump, "+? ContainerLife");
dump = check(dump, "");
ContainerLifeCycle aa2 = new ContainerLifeCycle();
a0.addBean(aa2, false);
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+?ContainerLife");
dump = check(dump, "+?ContainerLife");
dump = check(dump, "+~ContainerLife");
dump = check(dump, "+? ContainerLife");
dump = check(dump, "+? ContainerLife");
dump = check(dump, "+~ ContainerLife");
dump = check(dump, "");
aa1.start();
a0.start();
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "+~ContainerLife");
dump = check(dump, "+~ContainerLife");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "+~ ContainerLife");
dump = check(dump, "+~ ContainerLife");
dump = check(dump, "");
a0.manage(aa1);
a0.removeBean(aa2);
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "");
ContainerLifeCycle aaa0 = new ContainerLifeCycle();
aa0.addBean(aaa0);
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "| +~Container");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "| +~ Container");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "");
ContainerLifeCycle aa10 = new ContainerLifeCycle();
aa1.addBean(aa10, true);
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "| +~Container");
dump = check(dump, "+=ContainerLife");
dump = check(dump, " +=Container");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "| +~ Container");
dump = check(dump, "+= ContainerLife");
dump = check(dump, " += Container");
dump = check(dump, "");
final ContainerLifeCycle a1 = new ContainerLifeCycle();
@ -288,62 +288,62 @@ public class ContainerLifeCycleTest
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "| +~Container");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "| +=Container");
dump = check(dump, "+=ContainerLife");
dump = check(dump, " +>java.util.Arrays$ArrayList");
dump = check(dump, " | +:ContainerLifeCycle");
dump = check(dump, " | +:ContainerLifeCycle");
dump = check(dump, " +>java.util.Arrays$ArrayList");
dump = check(dump, " +:ContainerLifeCycle");
dump = check(dump, " +:ContainerLifeCycle");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "| +~ Container");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "| += Container");
dump = check(dump, "+= ContainerLife");
dump = check(dump, " +> java.util.Arrays$ArrayList");
dump = check(dump, " | +: ContainerLifeCycle");
dump = check(dump, " | +: ContainerLifeCycle");
dump = check(dump, " +> java.util.Arrays$ArrayList");
dump = check(dump, " +: ContainerLifeCycle");
dump = check(dump, " +: ContainerLifeCycle");
dump = check(dump, "");
a2.addBean(aa0, true);
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "| +~Container");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "| +=Container");
dump = check(dump, "+=ContainerLife");
dump = check(dump, " +>java.util.Arrays$ArrayList");
dump = check(dump, " | +:ContainerLifeCycle");
dump = check(dump, " | +:ContainerLifeCycle");
dump = check(dump, " | +=Conta");
dump = check(dump, " | +~C");
dump = check(dump, " +>java.util.Arrays$ArrayList");
dump = check(dump, " +:ContainerLifeCycle");
dump = check(dump, " +:ContainerLifeCycle");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "| +~ Container");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "| += Container");
dump = check(dump, "+= ContainerLife");
dump = check(dump, " +> java.util.Arrays$ArrayList");
dump = check(dump, " | +: ContainerLifeCycle");
dump = check(dump, " | +: ContainerLifeCycle");
dump = check(dump, " | += Conta");
dump = check(dump, " | +~ C");
dump = check(dump, " +> java.util.Arrays$ArrayList");
dump = check(dump, " +: ContainerLifeCycle");
dump = check(dump, " +: ContainerLifeCycle");
dump = check(dump, "");
a2.unmanage(aa0);
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "| +~Container");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "| +=Container");
dump = check(dump, "+=ContainerLife");
dump = check(dump, " +>java.util.Arrays$ArrayList");
dump = check(dump, " | +:ContainerLifeCycle");
dump = check(dump, " | +:ContainerLifeCycle");
dump = check(dump, " | +~Conta");
dump = check(dump, " +>java.util.Arrays$ArrayList");
dump = check(dump, " +:ContainerLifeCycle");
dump = check(dump, " +:ContainerLifeCycle");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "| +~ Container");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "| += Container");
dump = check(dump, "+= ContainerLife");
dump = check(dump, " +> java.util.Arrays$ArrayList");
dump = check(dump, " | +: ContainerLifeCycle");
dump = check(dump, " | +: ContainerLifeCycle");
dump = check(dump, " | +~ Conta");
dump = check(dump, " +> java.util.Arrays$ArrayList");
dump = check(dump, " +: ContainerLifeCycle");
dump = check(dump, " +: ContainerLifeCycle");
dump = check(dump, "");
a0.unmanage(aa);
dump = trim(a0.dump());
dump = check(dump, "ContainerLifeCycl");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "| +~Container");
dump = check(dump, "+=ContainerLife");
dump = check(dump, "| +=Container");
dump = check(dump, "+~ContainerLife");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "| +~ Container");
dump = check(dump, "+= ContainerLife");
dump = check(dump, "| += Container");
dump = check(dump, "+~ ContainerLife");
dump = check(dump, "");
}

View File

@ -27,7 +27,7 @@
<jsp.version>8.5.33.1</jsp.version>
<!-- default values are unsupported, but required to be defined for reactor sanity reasons -->
<alpn.version>undefined</alpn.version>
<conscrypt.version>1.1.4</conscrypt.version>
<conscrypt.version>1.4.1</conscrypt.version>
<asm.version>7.0</asm.version>
<jmh.version>1.21</jmh.version>
<jmhjar.name>benchmarks</jmhjar.name>

View File

@ -34,7 +34,9 @@ import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.junit.jupiter.api.Test;
@ -65,6 +67,100 @@ public class DefaultSessionCacheTest
}
@Test
public void testRenewIdMultipleRequests() throws Exception
{
//Test that invalidation happens on ALL copies of the session that are in-use by requests
Server server = new Server();
SessionIdManager sessionIdManager = new DefaultSessionIdManager(server);
server.setSessionIdManager(sessionIdManager);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/test");
context.setServer(server);
context.getSessionHandler().setMaxInactiveInterval((int)TimeUnit.DAYS.toSeconds(1));
context.getSessionHandler().setSessionIdManager(sessionIdManager);
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setSaveOnCreate(true); //ensures that a session is persisted as soon as it is created
DefaultSessionCache cache = (DefaultSessionCache)cacheFactory.getSessionCache(context.getSessionHandler());
TestSessionDataStore store = new TestSessionDataStore();
cache.setSessionDataStore(store);
context.getSessionHandler().setSessionCache(cache);
TestHttpSessionListener listener = new TestHttpSessionListener();
context.getSessionHandler().addEventListener(listener);
server.setHandler(context);
try
{
server.start();
//create a new session
Session s = (Session)context.getSessionHandler().newHttpSession(null);
String id = s.getId();
context.getSessionHandler().access(s, false); //simulate accessing the request
context.getSessionHandler().complete(s); //simulate completing the request
//make 1st request
final Session session = context.getSessionHandler().getSession(id); //get the session again
assertNotNull(session);
context.getSessionHandler().access(session, false); //simulate accessing the request
//make 2nd request
final Session session2 = context.getSessionHandler().getSession(id); //get the session again
context.getSessionHandler().access(session2, false); //simulate accessing the request
assertNotNull(session2);
assertTrue(session == session2);
Thread t2 = new Thread(new Runnable()
{
@Override
public void run()
{
System.err.println("Starting session id renewal");
session2.renewId(new Request(null,null));
System.err.println("Finished session id renewal");
}
});
t2.start();
Thread t = new Thread(new Runnable()
{
@Override
public void run()
{
System.err.println("Starting invalidation");
try{Thread.sleep(1000L);}catch (Exception e) {e.printStackTrace();}
session.invalidate();
System.err.println("Finished invalidation");
}
}
);
t.start();
t.join();
t2.join();
}
finally
{
server.stop();
}
}
/**
* Test sessions are saved when shutdown with a store.
@ -180,7 +276,7 @@ public class DefaultSessionCacheTest
cache.put("1234", session);
assertTrue(cache.contains("1234"));
cache.renewSessionId("1234", "5678");
cache.renewSessionId("1234", "5678", "1234.foo", "5678.foo");
assertTrue(cache.contains("5678"));
assertFalse(cache.contains("1234"));

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapps-parent</artifactId>
<version>9.3.0-SNAPSHOT</version>
</parent>
<name>Jetty Tests :: Webapps :: Dispatch Webapp</name>
<artifactId>test-dispatch-webapp</artifactId>
<packaging>war</packaging>
<properties>
<bundle-symbolic-name>${project.groupId}.dispatch</bundle-symbolic-name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${project.version}</version>
<configuration>
<scanIntervalSeconds>1</scanIntervalSeconds>
<useTestClasspath>true</useTestClasspath>
<webAppConfig>
<war>src/main/webapp</war>
<descriptor>src/main/webapp/WEB-INF/web.xml</descriptor>
<contextPath>/test-dispatch</contextPath>
<containerIncludeJarPattern>.*/javax.servlet-[^/]*\.jar$</containerIncludeJarPattern>
<configurationDiscovered>true</configurationDiscovered>
</webAppConfig>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,123 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2018 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 com.acme;
import static javax.servlet.RequestDispatcher.FORWARD_PATH_INFO;
import static javax.servlet.RequestDispatcher.FORWARD_QUERY_STRING;
import static javax.servlet.RequestDispatcher.FORWARD_SERVLET_PATH;
import static javax.servlet.RequestDispatcher.INCLUDE_PATH_INFO;
import static javax.servlet.RequestDispatcher.INCLUDE_QUERY_STRING;
import static javax.servlet.RequestDispatcher.INCLUDE_REQUEST_URI;
import static javax.servlet.RequestDispatcher.INCLUDE_SERVLET_PATH;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DispatchServlet extends HttpServlet
{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Integer depth = (Integer)request.getAttribute("depth");
if (depth==null)
depth=1;
else
depth=depth+1;
request.setAttribute("depth", depth);
String path=request.getServletPath();
String info=request.getPathInfo();
String query=request.getQueryString();
boolean include=request.getAttribute(INCLUDE_REQUEST_URI)!=null;
String tpath = include?(String)request.getAttribute(INCLUDE_SERVLET_PATH):path;
String tinfo = include?(String)request.getAttribute(INCLUDE_PATH_INFO):info;
if ("/forward".equals(tpath))
{
getServletContext().getRequestDispatcher(tinfo+"?depth="+depth+"&p"+depth+"="+"ABCDEFGHI".charAt(depth)).forward(request, response);
}
else if ("/include".equals(tpath))
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h1>Dispatch Depth="+depth+"</h1><pre>");
out.printf(" %30s%30s%30s%n","REQUEST","FORWARD","INCLUDE");
out.printf("servletPath:%30s%30s%30s%n",path,request.getAttribute(FORWARD_SERVLET_PATH),request.getAttribute(INCLUDE_SERVLET_PATH));
out.printf(" pathInfo:%30s%30s%30s%n",info,request.getAttribute(FORWARD_PATH_INFO),request.getAttribute(INCLUDE_PATH_INFO));
out.printf(" query:%30s%30s%30s%n",query,request.getAttribute(FORWARD_QUERY_STRING),request.getAttribute(INCLUDE_QUERY_STRING));
out.println();
printParameters(out, request.getParameterMap());
out.println("</pre>");
out.println("<hr/>");
getServletContext().getRequestDispatcher(tinfo+"?depth="+depth+"&p"+depth+"="+"BCDEFGHI".charAt(depth)).include(request, response);
out.println("<hr/>");
out.println("<h1>Dispatch Depth="+depth+"</h1><pre>");
out.printf(" %30s%30s%30s%n","REQUEST","FORWARD","INCLUDE");
out.printf("servletPath:%30s%30s%30s%n",path,request.getAttribute(FORWARD_SERVLET_PATH),request.getAttribute(INCLUDE_SERVLET_PATH));
out.printf(" pathInfo:%30s%30s%30s%n",info,request.getAttribute(FORWARD_PATH_INFO),request.getAttribute(INCLUDE_PATH_INFO));
out.printf(" query:%30s%30s%30s%n",query,request.getAttribute(FORWARD_QUERY_STRING),request.getAttribute(INCLUDE_QUERY_STRING));
out.println();
printParameters(out, request.getParameterMap());
out.println("</pre>");
}
else
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h1>Dispatch Depth="+depth+"</h1><pre>");
out.printf(" %30s%30s%30s%n","REQUEST","FORWARD","INCLUDE");
out.printf("servletPath:%30s%30s%30s%n",path,request.getAttribute(FORWARD_SERVLET_PATH),request.getAttribute(INCLUDE_SERVLET_PATH));
out.printf(" pathInfo:%30s%30s%30s%n",info,request.getAttribute(FORWARD_PATH_INFO),request.getAttribute(INCLUDE_PATH_INFO));
out.printf(" query:%30s%30s%30s%n",query,request.getAttribute(FORWARD_QUERY_STRING),request.getAttribute(INCLUDE_QUERY_STRING));
out.println();
printParameters(out, request.getParameterMap());
out.println("</pre>");
}
}
private static void printParameters(PrintWriter out, Map<String,String[]> params)
{
List<String> names = new ArrayList<>(params.keySet());
Collections.sort(names);
for (String name: names)
out.printf("%10s : %s%n", name,Arrays.asList(params.get(name)));
}
}

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
metadata-complete="false"
version="3.1">
<display-name>Test Dispatch WebApp</display-name>
<servlet>
<servlet-name>Dispatch</servlet-name>
<servlet-class>com.acme.DispatchServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Dispatch</servlet-name>
<url-pattern>/forward/*</url-pattern>
<url-pattern>/include/*</url-pattern>
<url-pattern>/info/*</url-pattern>
</servlet-mapping>
</web-app>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -1,48 +0,0 @@
<HTML>
<HEAD>
<TITLE>Test Dispatch WebApp</TITLE>
<META http-equiv="Pragma" content="no-cache">
<META http-equiv="Cache-Control" content="no-cache,no-store">
<link rel="stylesheet" type="text/css" href="stylesheet.css"/>
</HEAD>
<BODY >
<A HREF="http://www.eclipse.org/jetty"><IMG SRC="images/jetty_banner.gif"></A>
<h1>Request Dispatching Query Tests</h1>
<p><ul>
<li><a href="forward/info?depth=0&p0=A">forward/info?depth=0&p0=A</a></li>
<li><a href="include/info?depth=0&p0=A">include/info?depth=0&p0=A</a></li>
<li><a href="forward/forward/info?depth=0&p0=A">forward/forward/info?depth=0&p0=A</a></li>
<li><a href="forward/include/info?depth=0&p0=A">forward/include/info?depth=0&p0=A</a></li>
<li><a href="include/forward/info?depth=0&p0=A">include/forward/info?depth=0&p0=A</a></li>
<li><a href="include/include/info?depth=0&p0=A">include/include/info?depth=0&p0=A</a></li>
</ul>
</p>
<h1>Request Dispatching Form POST Tests</h1>
<p><ul>
<li><form action="forward/info" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="forward/info"></form></li>
<li><form action="include/info" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="include/info"></form></li>
<li><form action="forward/forward/info" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="forward/forward/info"></form></li>
<li><form action="forward/include/info" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="forward/include/info"></form></li>
<li><form action="include/forward/info" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="include/forward/info"></form></li>
<li><form action="include/include/info" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="include/include/info"></form></li>
</ul>
</p>
<h1>Request Dispatching Query Form POST Tests</h1>
<p><ul>
<li><form action="forward/info?depth=-1&p0=X&q=0" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="forward/info"></form></li>
<li><form action="include/info?depth=-1&p0=X&q=0" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="include/info"></form></li>
<li><form action="forward/forward/info?depth=-1&p0=X&q=0" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="forward/forward/info"></form></li>
<li><form action="forward/include/info?depth=-1&p0=X&q=0" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="forward/include/info"></form></li>
<li><form action="include/forward/info?depth=-1&p0=X&q=0" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="include/forward/info"></form></li>
<li><form action="include/include/info?depth=-1&p0=X&q=0" method="POST"><input type="hidden" name="depth" value="0"><input type="hidden" name="p0" value="A"><input type="submit" value="include/include/info"></form></li>
</ul>
</p>
<center>
<hr/>
<a href="http://www.eclipse.org/jetty"><img style="border:0" src="images/small_powered_by.gif"/></a>
</center>
</BODY>
</HTML>

View File

@ -1,7 +0,0 @@
body {color: #2E2E2E; font-family:sans-serif; font-size:90%;}
h1 {font-variant: small-caps; font-size:130%; letter-spacing: 0.1em;}
h2 {font-variant: small-caps; font-size:100%; letter-spacing: 0.1em; margin-top:2em;}
h3 {font-size:100%; letter-spacing: 0.1em;}
span.pass { color: green; }
span.fail { color:red; }