Merge remote-tracking branch 'origin/jetty-9.4.x'

This commit is contained in:
Greg Wilkins 2017-03-09 15:59:58 +11:00
commit 9ea4f128d4
19 changed files with 231 additions and 97 deletions

View File

@ -366,8 +366,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
//these candidates will be for our node
BasicDBObject query = new BasicDBObject();
query.append(__ID,new BasicDBObject("$in", candidates));
query.append(__EXPIRY, new BasicDBObject("$gt", 0));
query.append(__EXPIRY, new BasicDBObject("$lt", upperBound));
query.append(__EXPIRY, new BasicDBObject("$gt", 0).append("$lt", upperBound));
DBCursor verifiedExpiredSessions = null;
try

View File

@ -75,7 +75,7 @@ public abstract class AbstractConnectHandlerTest
protected Socket newSocket() throws IOException
{
Socket socket = new Socket("localhost", proxyConnector.getLocalPort());
socket.setSoTimeout(5000);
socket.setSoTimeout(20000);
return socket;
}
}

View File

@ -18,11 +18,9 @@
package org.eclipse.jetty.proxy;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

View File

@ -372,7 +372,7 @@ public class AttributeNormalizer
}
if (path.startsWith(a.path))
return String.format("${%s}/%s",a.key,a.path.relativize(path).toString());
return String.format("${%s}%c%s",a.key,File.separatorChar,a.path.relativize(path).toString());
}
return path.toString();

View File

@ -128,14 +128,21 @@ public class FileSessionDataStore extends AbstractSessionDataStore
{
if (dir != _storeDir)
return false;
String s = name.substring(0, name.indexOf('_'));
long expiry = (s==null?0:Long.parseLong(s));
if (expiry > 0 && expiry < now)
return true;
else
//dir may contain files that don't match our naming pattern
int index = name.indexOf('_');
if (index < 0)
return false;
try
{
long expiry = Long.parseLong(name.substring(0, index));
return expiry > 0 && expiry < now;
}
catch (NumberFormatException e)
{
return false;
}
}
});

View File

@ -361,7 +361,7 @@ public class AsyncRequestReadTest
break;
out.write(c);
}
out.println();
out.write('\n');
}
}
}

View File

@ -18,13 +18,19 @@
package org.eclipse.jetty.server;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -39,9 +45,6 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertTrue;
public class ServerConnectorTimeoutTest extends ConnectorTimeoutTest
{
@Before
@ -114,7 +117,7 @@ public class ServerConnectorTimeoutTest extends ConnectorTimeoutTest
try (Socket socket = new Socket((String)null,connector.getLocalPort()))
{
socket.setSoTimeout(10 * MAX_IDLE_TIME);
socket.getOutputStream().write(request.getBytes(StandardCharsets.UTF_8));
socket.getOutputStream().write(request.getBytes(UTF_8));
InputStream inputStream = socket.getInputStream();
long start = System.currentTimeMillis();
String response = IO.toString(inputStream);
@ -137,35 +140,64 @@ public class ServerConnectorTimeoutTest extends ConnectorTimeoutTest
IO.copy(request.getInputStream(), response.getOutputStream());
}
});
Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
client.setSoTimeout(10000);
Assert.assertFalse(client.isClosed());
OutputStream os=client.getOutputStream();
InputStream is=client.getInputStream();
final OutputStream os = client.getOutputStream();
final InputStream is = client.getInputStream();
final StringBuilder response = new StringBuilder();
CompletableFuture<Void> responseFuture = CompletableFuture.runAsync(() ->
{
try (InputStreamReader reader = new InputStreamReader(is, UTF_8))
{
int c;
while ((c = reader.read()) != -1)
{
response.append((char) c);
}
}
catch (IOException e)
{
// Valid path (as connection is forcibly closed)
// t.printStackTrace(System.err);
}
});
CompletableFuture<Void> requestFuture = CompletableFuture.runAsync(() ->
{
try
{
os.write((
"POST /echo HTTP/1.0\r\n" +
"host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"content-type: text/plain; charset=utf-8\r\n" +
"content-length: 20\r\n" +
"\r\n").getBytes("utf-8"));
os.flush();
os.write("123456789\n".getBytes("utf-8"));
os.flush();
TimeUnit.SECONDS.sleep(1);
os.write("=========\n".getBytes("utf-8"));
os.flush();
}
catch (InterruptedException | IOException e)
{
// Valid path, as write of second half of content can fail
// e.printStackTrace(System.err);
}
});
try (StacklessLogging scope = new StacklessLogging(HttpChannel.class))
{
os.write((
"POST /echo HTTP/1.0\r\n"+
"host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"content-type: text/plain; charset=utf-8\r\n"+
"content-length: 20\r\n"+
"\r\n").getBytes("utf-8"));
os.flush();
os.write("123456789\n".getBytes("utf-8"));
os.flush();
Thread.sleep(1000);
os.write("=========\n".getBytes("utf-8"));
os.flush();
Thread.sleep(2000);
String response =IO.toString(is);
Assert.assertThat(response,containsString(" 500 "));
Assert.assertThat(response, Matchers.not(containsString("=========")));
requestFuture.get(2, TimeUnit.SECONDS);
responseFuture.get(3, TimeUnit.SECONDS);
Assert.assertThat(response.toString(), containsString(" 500 "));
Assert.assertThat(response.toString(), Matchers.not(containsString("=========")));
}
}
}

View File

@ -82,7 +82,10 @@ public class AllowSymLinkAliasCheckerTest
@After
public void teardown() throws Exception
{
server.stop();
if( server != null )
{
server.stop();
}
}
private void setupRoot() throws IOException

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.server.session;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Collections;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
@ -195,4 +196,52 @@ public class FileSessionManagerTest
server.stop();
}
@Test
public void testIrregularFilenames() throws Exception
{
Server server = new Server();
SessionHandler handler = new SessionHandler();
handler.setServer(server);
final DefaultSessionIdManager idmgr = new DefaultSessionIdManager(server);
idmgr.setServer(server);
server.setSessionIdManager(idmgr);
FileSessionDataStore ds = new FileSessionDataStore();
ds.setDeleteUnrestorableFiles(true);
DefaultSessionCache ss = new DefaultSessionCache(handler);
handler.setSessionCache(ss);
ss.setSessionDataStore(ds);
//manager.setLazyLoad(true);
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
testDir.mkdirs();
ds.setStoreDir(testDir);
handler.setSessionIdManager(idmgr);
handler.start();
//Create a file in the session storeDir that has no underscore.
File noUnderscore = new File(testDir, "spuriousFile");
noUnderscore.createNewFile();
try
{
Assert.assertTrue("Expired should be empty!", ds.getExpired(Collections.emptySet()).isEmpty());
}
finally
{
noUnderscore.delete();
}
//Create a file that starts with a non-number before an underscore
File nonNumber = new File(testDir, "nonNumber_0.0.0.0_spuriousFile");
nonNumber.createNewFile();
try
{
Assert.assertTrue("Expired should be empty!", ds.getExpired(Collections.emptySet()).isEmpty());
}
finally
{
nonNumber.delete();
}
}
}

View File

@ -234,4 +234,23 @@ public abstract class AbstractLifeCycle implements LifeCycle
@Override public void lifeCycleStopped(LifeCycle event) {}
@Override public void lifeCycleStopping(LifeCycle event) {}
}
/**
* A LifeCycle Listener that will call stop if any failures are notified.
*/
public static final LifeCycle.Listener STOP_ON_FAILURE = new AbstractLifeCycleListener()
{
@Override
public void lifeCycleFailure(LifeCycle lifecycle, Throwable cause)
{
try
{
lifecycle.stop();
}
catch(Exception e)
{
cause.addSuppressed(e);
}
}
};
}

View File

@ -18,12 +18,17 @@
package org.eclipse.jetty.websocket.server;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.DispatcherType;
@ -42,10 +47,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
@RunWith(Parameterized.class)
public class WebSocketUpgradeFilterTest
{
@ -54,6 +55,13 @@ public class WebSocketUpgradeFilterTest
Server newServer() throws Exception;
}
private static AtomicInteger uniqTestDirId = new AtomicInteger(0);
private static File getNewTestDir()
{
return MavenTestingUtils.getTargetTestingDir("WSUF-webxml-" + uniqTestDirId.getAndIncrement());
}
@Parameterized.Parameters(name = "{0}")
public static List<Object[]> data()
{
@ -188,7 +196,7 @@ public class WebSocketUpgradeFilterTest
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/ServletContextListener", (ServerProvider) () ->
{
File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml");
File testDir = getNewTestDir();
WSServer server15 = new WSServer(testDir, "/");
@ -210,7 +218,7 @@ public class WebSocketUpgradeFilterTest
@Override
public Server newServer() throws Exception
{
File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml");
File testDir = getNewTestDir();
WSServer server = new WSServer(testDir, "/");
@ -234,7 +242,7 @@ public class WebSocketUpgradeFilterTest
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/Servlet.init", (ServerProvider) () ->
{
File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml");
File testDir = getNewTestDir();
WSServer server16 = new WSServer(testDir, "/");
@ -253,7 +261,7 @@ public class WebSocketUpgradeFilterTest
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/ServletContextListener/alt-config", (ServerProvider) () ->
{
File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml");
File testDir = getNewTestDir();
WSServer server17 = new WSServer(testDir, "/");

View File

@ -227,7 +227,7 @@ public class AttributeNormalizerTest
{
// Normalize WAR deep path as File
File testWarDeep = new File(new File(war), OS.separators("deep/ref")).getAbsoluteFile();
assertNormalize(testWarDeep, "${WAR.path}/deep/ref");
assertNormalize(testWarDeep, "${WAR.path}" + OS.separators("/deep/ref"));
}
@Test

View File

@ -50,10 +50,5 @@ public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessi
{
return FileTestHelper.newSessionDataStoreFactory();
}
@Test
public void testNewSession() throws Exception
{
super.testNewSession();
}
}

View File

@ -50,10 +50,4 @@ public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessi
return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore());
}
@Test
public void testNewSession() throws Exception
{
super.testNewSession();
}
}

View File

@ -59,12 +59,4 @@ public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessi
factory.setCache(__testSupport.getCache());
return factory;
}
@Override
public void testNewSession() throws Exception
{
super.testNewSession();
}
}

View File

@ -59,13 +59,4 @@ public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessi
factory.setCache(__testSupport.getCache());
return factory;
}
@Override
public void testNewSession() throws Exception
{
super.testNewSession();
}
}

View File

@ -35,13 +35,7 @@ public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessi
{
return JdbcTestHelper.newSessionDataStoreFactory();
}
@Test
public void testNewSession() throws Exception
{
super.testNewSession();
}
@After
public void tearDown() throws Exception

View File

@ -22,7 +22,6 @@ import org.eclipse.jetty.server.session.AbstractNonClusteredSessionScavengingTes
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* NonClusteredSessionScavengingTest
@ -51,10 +50,4 @@ public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessi
{
return MongoTestHelper.newSessionDataStoreFactory();
}
@Test
public void testNewSession() throws Exception
{
super.testNewSession();
}
}

View File

@ -111,8 +111,62 @@ public abstract class AbstractNonClusteredSessionScavengingTest extends Abstract
{
server.stop();
}
}
@Test
public void testImmortalSession() throws Exception
{
String servletMapping = "/server";
int scavengePeriod = 3;
int maxInactivePeriod = 0;
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
SessionDataStoreFactory storeFactory = createSessionDataStoreFactory();
((AbstractSessionDataStoreFactory)storeFactory).setGracePeriodSec(scavengePeriod);
TestServer server = new TestServer(0, maxInactivePeriod, scavengePeriod,
cacheFactory, storeFactory);
ServletContextHandler context = server.addContext("/");
context.addServlet(TestServlet.class, servletMapping);
String contextPath = "";
try
{
server.start();
int port=server.getPort();
HttpClient client = new HttpClient();
client.start();
try
{
//create an immortal session
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
// Let's wait for the scavenger to run
pause(2*scavengePeriod);
// Test that the session is still there
Request request = client.newRequest("http://localhost:" + port + contextPath + servletMapping + "?action=old-test");
request.header("Cookie", sessionCookie);
response = request.send();
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
}
finally
{
client.stop();
}
}
finally
{
server.stop();
}
}
public static class TestServlet extends HttpServlet
{
String id;
@ -135,6 +189,12 @@ public abstract class AbstractNonClusteredSessionScavengingTest extends Abstract
assertNotNull(s);
assertFalse(s.getId().equals(id));
}
else if ("old-test".equals(action))
{
HttpSession s = request.getSession(false);
assertNotNull(s);
assertTrue(s.getId().equals(id));
}
else
{
assertTrue(false);