Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-11.0.x

This commit is contained in:
Joakim Erdfelt 2020-10-16 08:52:05 -05:00
commit 60fa27f12f
No known key found for this signature in database
GPG Key ID: 2D0E1FB8FE4B68B4
22 changed files with 373 additions and 291 deletions

View File

@ -18,8 +18,9 @@
package org.eclipse.jetty.demos;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import jakarta.servlet.ServletException;
@ -120,8 +121,8 @@ public class ManyHandlers
gzipHandler.addIncludedMimeTypes("text/html");
// configure request logging
File requestLogFile = File.createTempFile("demo", "log");
CustomRequestLog ncsaLog = new CustomRequestLog(requestLogFile.getAbsolutePath());
Path requestLogFile = Files.createTempFile("demo", "log");
CustomRequestLog ncsaLog = new CustomRequestLog(requestLogFile.toString());
server.setRequestLog(ncsaLog);
// create the handlers list

View File

@ -20,7 +20,6 @@ package org.eclipse.jetty.io;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
@ -35,17 +34,21 @@ import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.IO;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@ -55,8 +58,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ExtendWith(WorkDirExtension.class)
public class IOTest
{
public WorkDir workDir;
@Test
public void testIO() throws Exception
{
@ -95,7 +101,6 @@ public class IOTest
// but cannot write
Assertions.assertThrows(SocketException.class, () -> client.getOutputStream().write(1));
// but can still write in opposite direction.
server.getOutputStream().write(1);
assertEquals(1, client.getInputStream().read());
@ -418,13 +423,9 @@ public class IOTest
@Test
public void testGatherWrite() throws Exception
{
File dir = MavenTestingUtils.getTargetTestingDir();
if (!dir.exists())
dir.mkdir();
File file = File.createTempFile("test", ".txt", dir);
file.deleteOnExit();
FileChannel out = FileChannel.open(file.toPath(),
Path dir = workDir.getEmptyPathDir();
Path file = Files.createTempFile(dir, "test", ".txt");
FileChannel out = FileChannel.open(file,
StandardOpenOption.CREATE,
StandardOpenOption.READ,
StandardOpenOption.WRITE,

View File

@ -38,7 +38,6 @@ import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
@ -694,8 +693,6 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
_request.setMetaData(request);
_request.setSecure(HttpScheme.HTTPS.is(request.getURI().getScheme()));
_combinedListener.onRequestBegin(_request);
if (LOG.isDebugEnabled())

View File

@ -32,6 +32,8 @@ import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -42,6 +44,8 @@ import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.Part;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.ByteArrayOutputStream2;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.QuotedStringTokenizer;
@ -189,7 +193,7 @@ public class MultiPartFormInputStream
Path p = Path.of(fileName);
if (!p.isAbsolute())
p = _tmpDir.resolve(p);
if (_file == null)
{
_temporary = false;
@ -220,19 +224,11 @@ public class MultiPartFormInputStream
protected void createFile() throws IOException
{
/*
* Some statics just to make the code below easier to understand This get optimized away during the compile anyway
*/
final boolean USER = true;
final boolean WORLD = false;
Path parent = MultiPartFormInputStream.this._tmpDir;
Path tempFile = Files.createTempFile(parent, "MultiPart", "", IO.getUserOnlyFileAttribute(parent));
_file = tempFile.toFile();
_file = Files.createTempFile(MultiPartFormInputStream.this._tmpDir, "MultiPart", "").toFile();
_file.setReadable(false, WORLD); // (reset) disable it for everyone first
_file.setReadable(true, USER); // enable for user only
if (_deleteOnExit)
_file.deleteOnExit();
FileOutputStream fos = new FileOutputStream(_file);
OutputStream fos = Files.newOutputStream(tempFile, StandardOpenOption.WRITE);
BufferedOutputStream bos = new BufferedOutputStream(fos);
if (_size > 0 && _out != null)
@ -386,7 +382,7 @@ public class MultiPartFormInputStream
return;
}
}
_in = new BufferedInputStream(in);
}
@ -822,9 +818,13 @@ public class MultiPartFormInputStream
}
}
/**
* @deprecated no replacement provided.
*/
@Deprecated
public void setDeleteOnExit(boolean deleteOnExit)
{
_deleteOnExit = deleteOnExit;
// does nothing.
}
public void setWriteFilesWithFilenames(boolean writeFilesWithFilenames)
@ -837,9 +837,13 @@ public class MultiPartFormInputStream
return _writeFilesWithFilenames;
}
/**
* @deprecated no replacement provided
*/
@Deprecated
public boolean isDeleteOnExit()
{
return _deleteOnExit;
return false;
}
private static String value(String nameEqualsValue)

View File

@ -1688,21 +1688,18 @@ public class Request implements HttpServletRequest
final HttpURI uri = request.getURI();
if (uri.isAbsolute() && uri.hasAuthority() && uri.getPath() != null)
{
_uri = uri;
}
else
{
HttpURI.Mutable builder = HttpURI.build(uri);
if (uri.isAbsolute())
{
if (uri.getPath() == null)
builder.path("/");
setSecure(HttpScheme.HTTPS.is(uri.getScheme()));
}
else
{
if (!uri.isAbsolute())
builder.scheme(HttpScheme.HTTP.asString());
}
if (uri.getPath() == null)
builder.path("/");
if (!uri.hasAuthority())
{
@ -1720,6 +1717,8 @@ public class Request implements HttpServletRequest
_uri = builder.asImmutable();
}
setSecure(HttpScheme.HTTPS.is(_uri.getScheme()));
String encoded = _uri.getPath();
String path;
if (encoded == null)

View File

@ -27,6 +27,8 @@ import java.io.InputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.Principal;
import java.time.Duration;
import java.util.ArrayList;
@ -72,6 +74,8 @@ import org.eclipse.jetty.server.session.SessionData;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.IO;
import org.hamcrest.Matchers;
@ -79,6 +83,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -100,9 +105,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
// @checkstyle-disable-check : AvoidEscapedUnicodeCharactersCheck
@ExtendWith(WorkDirExtension.class)
public class RequestTest
{
private static final Logger LOG = LoggerFactory.getLogger(RequestTest.class);
public WorkDir workDir;
private Server _server;
private LocalConnector _connector;
private RequestHandler _handler;
@ -414,20 +421,15 @@ public class RequestTest
@Test
public void testMultiPart() throws Exception
{
final File testTmpDir = File.createTempFile("reqtest", null);
if (testTmpDir.exists())
testTmpDir.delete();
testTmpDir.mkdir();
testTmpDir.deleteOnExit();
assertTrue(testTmpDir.list().length == 0);
Path testTmpDir = workDir.getEmptyPathDir();
// We should have two tmp files after parsing the multipart form.
RequestTester tester = (request, response) -> testTmpDir.list().length == 2;
RequestTester tester = (request, response) -> Files.list(testTmpDir).count() == 2;
ContextHandler contextHandler = new ContextHandler();
contextHandler.setContextPath("/foo");
contextHandler.setResourceBase(".");
contextHandler.setHandler(new MultiPartRequestHandler(testTmpDir, tester));
contextHandler.setHandler(new MultiPartRequestHandler(testTmpDir.toFile(), tester));
_server.stop();
_server.setHandler(contextHandler);
_server.start();
@ -462,19 +464,14 @@ public class RequestTest
endPoint.addInput(cleanupRequest);
assertTrue(endPoint.getResponse().startsWith("HTTP/1.1 200"));
assertThat(testTmpDir.list().length, is(0));
assertThat("File Count in dir: " + testTmpDir, getFileCount(testTmpDir), is(0L));
}
@Test
public void testBadMultiPart() throws Exception
{
//a bad multipart where one of the fields has no name
final File testTmpDir = File.createTempFile("badmptest", null);
if (testTmpDir.exists())
testTmpDir.delete();
testTmpDir.mkdir();
testTmpDir.deleteOnExit();
assertTrue(testTmpDir.list().length == 0);
Path testTmpDir = workDir.getEmptyPathDir();
ContextHandler contextHandler = new ContextHandler();
contextHandler.setContextPath("/foo");
@ -504,7 +501,7 @@ public class RequestTest
multipart;
LocalEndPoint endPoint = _connector.connect();
try (StacklessLogging stackless = new StacklessLogging(HttpChannel.class))
try (StacklessLogging ignored = new StacklessLogging(HttpChannel.class))
{
endPoint.addInput(request);
assertTrue(endPoint.getResponse().startsWith("HTTP/1.1 500"));
@ -513,7 +510,7 @@ public class RequestTest
// Wait for the cleanup of the multipart files.
assertTimeoutPreemptively(Duration.ofSeconds(5), () ->
{
while (testTmpDir.list().length > 0)
while (getFileCount(testTmpDir) > 0)
{
Thread.yield();
}
@ -1811,7 +1808,7 @@ public class RequestTest
assertNotNull(request.getParameterMap());
assertEquals(0, request.getParameterMap().size());
}
@Test
public void testPushBuilder() throws Exception
{
@ -1978,18 +1975,30 @@ public class RequestTest
assertThat(m.getPathInfo(), is(spec.getPathInfo(uri)));
}
private static long getFileCount(Path path)
{
try
{
return Files.list(path).count();
}
catch (IOException e)
{
throw new RuntimeException("Unable to get file list count: " + path, e);
}
}
interface RequestTester
{
boolean check(HttpServletRequest request, HttpServletResponse response) throws IOException;
}
private class TestRequest extends Request
{
public static final String TEST_SESSION_ID = "abc123";
Response _response = new Response(null, null);
Cookie c1;
Cookie c2;
public TestRequest(HttpChannel channel, HttpInput input)
{
super(channel, input);
@ -2122,9 +2131,9 @@ public class RequestTest
private class BadMultiPartRequestHandler extends AbstractHandler
{
File tmpDir;
final Path tmpDir;
public BadMultiPartRequestHandler(File tmpDir)
public BadMultiPartRequestHandler(Path tmpDir)
{
this.tmpDir = tmpDir;
}
@ -2142,7 +2151,7 @@ public class RequestTest
try
{
MultipartConfigElement mpce = new MultipartConfigElement(tmpDir.getAbsolutePath(), -1, -1, 2);
MultipartConfigElement mpce = new MultipartConfigElement(tmpDir.toString(), -1, -1, 2);
request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
//We should get an error when we getParams if there was a problem parsing the multipart

View File

@ -38,9 +38,12 @@ import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.eclipse.jetty.util.resource.Resource;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
@ -50,8 +53,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ExtendWith(WorkDirExtension.class)
public class ContextHandlerTest
{
public WorkDir workDir;
@Test
public void testGetResourcePathsWhenSuppliedPathEndsInSlash() throws Exception
{
@ -796,24 +802,14 @@ public class ContextHandlerTest
private File setupTestDirectory() throws IOException
{
File tmpDir = new File(System.getProperty("basedir", ".") + "/target/tmp/ContextHandlerTest");
tmpDir = tmpDir.getCanonicalFile();
if (!tmpDir.exists())
assertTrue(tmpDir.mkdirs());
File tmp = File.createTempFile("cht", null, tmpDir);
assertTrue(tmp.delete());
assertTrue(tmp.mkdir());
tmp.deleteOnExit();
File root = new File(tmp, getClass().getName());
assertTrue(root.mkdir());
Path root = workDir.getEmptyPathDir();
File webInf = new File(root, "WEB-INF");
assertTrue(webInf.mkdir());
Path webInfDir = root.resolve("WEB-INF");
FS.ensureDirExists(webInfDir);
FS.ensureDirExists(webInfDir.resolve("jsp"));
FS.touch(webInfDir.resolve("web.xml"));
assertTrue(new File(webInf, "jsp").mkdir());
assertTrue(new File(webInf, "web.xml").createNewFile());
return root;
return root.toFile();
}
private void checkWildcardHost(boolean succeed, Server server, String[] contextHosts, String[] requestHosts) throws Exception

View File

@ -157,6 +157,11 @@ public class ServletTester extends ContainerLifeCycle
return _context.getBaseResource();
}
public void setBaseResource(Resource resource)
{
_context.setBaseResource(resource);
}
public String getResourceBase()
{
return _context.getResourceBase();

View File

@ -25,6 +25,10 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@ -212,8 +216,8 @@ public class PutFilter implements Filter
if (_putAtomic)
{
File tmp = File.createTempFile(file.getName(), null, _tmpdir);
try (OutputStream out = new FileOutputStream(tmp, false))
Path tmp = Files.createTempFile(_tmpdir.toPath(), file.getName(), null);
try (OutputStream out = Files.newOutputStream(tmp, StandardOpenOption.WRITE))
{
if (toRead >= 0)
IO.copy(in, out, toRead);
@ -221,8 +225,7 @@ public class PutFilter implements Filter
IO.copy(in, out);
}
if (!tmp.renameTo(file))
throw new IOException("rename from " + tmp + " to " + file + " failed");
Files.move(tmp, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
else
{

View File

@ -18,54 +18,59 @@
package org.eclipse.jetty.servlets;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletTester;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.resource.PathResource;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.in;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ExtendWith(WorkDirExtension.class)
public class PutFilterTest
{
private File _dir;
public WorkDir workDir;
private Path root;
private ServletTester tester;
@BeforeEach
public void setUp() throws Exception
{
_dir = File.createTempFile("testPutFilter", null);
assertTrue(_dir.delete());
assertTrue(_dir.mkdir());
_dir.deleteOnExit();
assertTrue(_dir.isDirectory());
root = workDir.getEmptyPathDir();
tester = new ServletTester("/context");
tester.setResourceBase(_dir.getCanonicalPath());
tester.setBaseResource(new PathResource(root));
tester.addServlet(org.eclipse.jetty.servlet.DefaultServlet.class, "/");
FilterHolder holder = tester.addFilter(PutFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
holder.setInitParameter("delAllowed", "true");
tester.setAttribute(ServletContext.TEMPDIR, workDir.getPath().toFile());
// Bloody Windows does not allow file renaming
if (!System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows"))
holder.setInitParameter("putAtomic", "true");
@ -76,7 +81,6 @@ public class PutFilterTest
public void tearDown() throws Exception
{
tester.stop();
IO.delete(_dir);
}
@Test
@ -103,9 +107,9 @@ public class PutFilterTest
response = HttpTester.parseResponse(tester.getResponses(request.generate()));
assertEquals(HttpServletResponse.SC_CREATED, response.getStatus());
File file = new File(_dir, "file.txt");
assertTrue(file.exists());
assertEquals(data0, IO.toString(new FileInputStream(file)));
Path file = root.resolve("file.txt");
assertTrue(Files.exists(file));
assertEquals(data0, IO.toString(file, UTF_8));
// test GET1
request.setMethod("GET");
@ -125,9 +129,9 @@ public class PutFilterTest
response = HttpTester.parseResponse(tester.getResponses(request.generate()));
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
file = new File(_dir, "file.txt");
assertTrue(file.exists());
assertEquals(data1, IO.toString(new FileInputStream(file)));
file = root.resolve("file.txt");
assertTrue(Files.exists(file));
assertEquals(data1, IO.toString(file, UTF_8));
// test PUT2
request.setMethod("PUT");
@ -193,19 +197,16 @@ public class PutFilterTest
response = HttpTester.parseResponse(tester.getResponses(request.generate()));
assertEquals(HttpServletResponse.SC_CREATED, response.getStatus());
File file = new File(_dir, "file.txt");
assertTrue(file.exists());
try (InputStream fis = new FileInputStream(file))
{
assertEquals(data1, IO.toString(fis));
}
Path file = root.resolve("file.txt");
assertTrue(Files.exists(file));
assertEquals(data1, IO.toString(file, UTF_8));
request.setMethod("DELETE");
request.setURI("/context/file.txt");
response = HttpTester.parseResponse(tester.getResponses(request.generate()));
assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus());
assertTrue(!file.exists());
assertFalse(Files.exists(file));
request.setMethod("DELETE");
request.setURI("/context/file.txt");
@ -232,12 +233,9 @@ public class PutFilterTest
assertEquals(HttpServletResponse.SC_CREATED, response.getStatus());
File file = new File(_dir, "file.txt");
assertTrue(file.exists());
try (InputStream fis = new FileInputStream(file))
{
assertEquals(data1, IO.toString(fis));
}
Path file = root.resolve("file.txt");
assertTrue(Files.exists(file));
assertEquals(data1, IO.toString(file, UTF_8));
request.setMethod("MOVE");
request.setURI("/context/file.txt");
@ -245,10 +243,10 @@ public class PutFilterTest
response = HttpTester.parseResponse(tester.getResponses(request.generate()));
assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus());
assertTrue(!file.exists());
assertFalse(Files.exists(file));
File nFile = new File(_dir, "blah.txt");
assertTrue(nFile.exists());
Path nFile = root.resolve("blah.txt");
assertTrue(Files.exists(nFile));
}
@Test

View File

@ -34,6 +34,16 @@ import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.channels.GatheringByteChannel;
import java.nio.charset.Charset;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.HashSet;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -47,6 +57,24 @@ public class IO
{
private static final Logger LOG = LoggerFactory.getLogger(IO.class);
private static final FileAttribute<?>[] NO_FILE_ATTRIBUTES = new FileAttribute[0];
private static final FileAttribute<?>[] USER_ONLY_POSIX_FILE_ATTRIBUTES =
new FileAttribute[]{
PosixFilePermissions.asFileAttribute(
new HashSet<PosixFilePermission>()
{
{
add(PosixFilePermission.OWNER_EXECUTE);
add(PosixFilePermission.OWNER_READ);
add(PosixFilePermission.OWNER_WRITE);
// we don't add GROUP or OTHER write perms here.
add(PosixFilePermission.GROUP_READ);
add(PosixFilePermission.OTHERS_READ);
}
}
)
};
public static final String
CRLF = "\r\n";
@ -276,6 +304,21 @@ public class IO
}
}
/**
* Read Path to string.
*
* @param path the path to read from (until EOF)
* @param charset the charset to read with
* @return the String parsed from path (default Charset)
* @throws IOException if unable to read the path (or handle the charset)
*/
public static String toString(Path path, Charset charset)
throws IOException
{
byte[] buf = Files.readAllBytes(path);
return new String(buf, charset);
}
/**
* Read input stream to string.
*
@ -416,6 +459,58 @@ public class IO
close((Closeable)writer);
}
/**
* Get the array of {@link FileAttribute} values for the provided path
* that will set the path to Full Read/Write for the user running Jetty,
* but Readonly for other users.
* <p>
* For Unix, that's means {@link java.nio.file.attribute.PosixFileAttributes}
* where the World and Other groups have their read / write flags removed.
* </p>
* <p>
* For Windows / Dos, that means {@link java.nio.file.attribute.DosFileAttributes}
* </p>
*/
public static FileAttribute<?>[] getUserOnlyFileAttribute(Path path)
{
FileStore fileStore = null;
try
{
// Obtain a reference to the FileStore to know what kind of read-only we are capable of.
fileStore = Files.getFileStore(Objects.requireNonNull(path));
if (fileStore == null)
{
// Not on a properly implemented FileStore (seen with 3rd party FileStore implementations)
// We cannot do anything in this case, so just return.
return NO_FILE_ATTRIBUTES;
}
if (fileStore.supportsFileAttributeView(DosFileAttributeView.class))
{
// We are on a Windows / DOS filesystem.
// It might support ACL, but we don't attempt to support that here.
return NO_FILE_ATTRIBUTES;
}
if (fileStore.supportsFileAttributeView(PosixFileAttributeView.class))
{
// We are on a Unix / Linux / OSX system
return USER_ONLY_POSIX_FILE_ATTRIBUTES;
}
// If we reached this point, we have a Path on a FileSystem / FileStore that we cannot control.
// So skip the attempt to set readable.
}
catch (IOException e)
{
if (LOG.isDebugEnabled())
LOG.debug("Unable to determine attribute types on path: {}", path, e);
}
return NO_FILE_ATTRIBUTES;
}
public static byte[] readBytes(InputStream in)
throws IOException
{

View File

@ -18,27 +18,26 @@
package org.eclipse.jetty.server.session;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* ClusteredOrphanedSessionTest
*/
@ExtendWith(WorkDirExtension.class)
public class ClusteredOrphanedSessionTest extends AbstractClusteredOrphanedSessionTest
{
public WorkDir workDir;
FileTestHelper _helper;
@BeforeEach
public void before() throws Exception
{
_helper = new FileTestHelper();
}
@AfterEach
public void after()
{
_helper.teardown();
_helper = new FileTestHelper(workDir.getEmptyPathDir());
}
@Override

View File

@ -18,27 +18,24 @@
package org.eclipse.jetty.server.session;
import org.junit.jupiter.api.AfterEach;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* FileSessionDataStoreTest
*/
@ExtendWith(WorkDirExtension.class)
public class FileSessionDataStoreTest extends AbstractSessionDataStoreTest
{
public WorkDir workDir;
private FileTestHelper _helper;
@BeforeEach
public void before() throws Exception
{
_helper = new FileTestHelper();
}
@AfterEach
public void after()
{
_helper.teardown();
_helper = null;
_helper = new FileTestHelper(workDir.getEmptyPathDir());
}
@Override

View File

@ -21,19 +21,26 @@ package org.eclipse.jetty.server.session;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
import org.eclipse.jetty.util.IO;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
@ -41,124 +48,76 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/
public class FileTestHelper
{
File _tmpDir;
private final Path storeDirRoot;
public FileTestHelper()
throws Exception
public FileTestHelper(Path root)
{
_tmpDir = File.createTempFile("file", "test");
_tmpDir.delete();
_tmpDir.mkdirs();
_tmpDir.deleteOnExit();
storeDirRoot = Objects.requireNonNull(root);
assertTrue(Files.exists(root), "Path must exist: " + root);
assertTrue(Files.isDirectory(root), "Path must be a directory: " + root);
}
public void teardown()
public void assertStoreDirEmpty(boolean isEmpty) throws IOException
{
IO.delete(_tmpDir);
_tmpDir = null;
}
long storeDirCount = Files.list(storeDirRoot).count();
public void assertStoreDirEmpty(boolean isEmpty)
{
assertNotNull(_tmpDir);
assertTrue(_tmpDir.exists());
String[] files = _tmpDir.list();
if (isEmpty)
{
if (files != null)
assertEquals(0, files.length);
assertThat("Store Dir content count", storeDirCount, is(0L));
}
else
{
assertNotNull(files);
assertFalse(files.length == 0);
assertThat("Store Dir content count", storeDirCount, greaterThan(0L));
}
}
public File getFile(String sessionId)
public File getFile(String sessionId) throws IOException
{
assertNotNull(_tmpDir);
assertTrue(_tmpDir.exists());
String[] files = _tmpDir.list();
assertNotNull(files);
String fname = null;
for (String name : files)
{
int i = name.lastIndexOf('_');
if (i < 0 || i == name.length() - 1)
continue;
String id = name.substring(i + 1);
if (id.equals(sessionId))
{
fname = name;
break;
}
}
if (fname != null)
return new File(_tmpDir, fname);
Optional<Path> sessionPath = Files.list(storeDirRoot)
.filter((path) -> path.getFileName().toString().contains(sessionId))
.findFirst();
if (sessionPath.isPresent())
return sessionPath.get().toFile();
return null;
}
public void assertSessionExists(String sessionId, boolean exists)
public void assertSessionExists(String sessionId, boolean exists) throws IOException
{
assertNotNull(_tmpDir);
assertTrue(_tmpDir.exists());
String[] files = _tmpDir.list();
assertNotNull(files);
Optional<Path> sessionPath = Files.list(storeDirRoot)
.filter((path) -> path.getFileName().toString().contains(sessionId))
.findFirst();
if (exists)
assertFalse(files.length == 0);
boolean found = false;
for (String name : files)
{
int i = name.lastIndexOf('_');
if (i < 0)
continue;
String id = name.substring(i + 1);
if (id.equals(sessionId))
{
found = true;
break;
}
}
if (exists)
assertTrue(found);
assertTrue(sessionPath.isPresent());
else
assertFalse(found);
assertFalse(sessionPath.isPresent());
}
public void assertFileExists(String filename, boolean exists)
{
assertNotNull(_tmpDir);
assertTrue(_tmpDir.exists());
File file = new File(_tmpDir, filename);
Path path = storeDirRoot.resolve(filename);
if (exists)
assertTrue(file.exists());
assertTrue(Files.exists(path), "File should exist: " + path);
else
assertFalse(file.exists());
assertFalse(Files.exists(path), "File should NOT exist: " + path);
}
public void createFile(String filename)
throws IOException
{
assertNotNull(_tmpDir);
assertTrue(_tmpDir.exists());
File file = new File(_tmpDir, filename);
Files.deleteIfExists(file.toPath());
file.createNewFile();
Path path = storeDirRoot.resolve(filename);
Files.deleteIfExists(path);
FS.touch(path);
}
public void createFile(String id, String contextPath, String vhost,
String lastNode, long created, long accessed,
long lastAccessed, long maxIdle, long expiry,
long cookieSet, Map<String, Object> attributes)
String lastNode, long created, long accessed,
long lastAccessed, long maxIdle, long expiry,
long cookieSet, Map<String, Object> attributes)
throws Exception
{
String filename = "" + expiry + "_" + contextPath + "_" + vhost + "_" + id;
File file = new File(_tmpDir, filename);
try (FileOutputStream fos = new FileOutputStream(file, false);
Path path = storeDirRoot.resolve(filename);
try (OutputStream fos = Files.newOutputStream(path);
DataOutputStream out = new DataOutputStream(fos))
{
out.writeUTF(id);
@ -185,10 +144,11 @@ public class FileTestHelper
throws Exception
{
String filename = "" + data.getExpiry() + "_" + data.getContextPath() + "_" + data.getVhost() + "_" + data.getId();
File file = new File(_tmpDir, filename);
assertTrue(file.exists());
Path file = storeDirRoot.resolve(filename);
try (FileInputStream in = new FileInputStream(file);
assertTrue(Files.exists(file));
try (InputStream in = Files.newInputStream(file);
DataInputStream di = new DataInputStream(in))
{
String id = di.readUTF();
@ -220,44 +180,35 @@ public class FileTestHelper
//same number of attributes
assertEquals(data.getAllAttributes().size(), tmp.getAllAttributes().size());
//same keys
assertTrue(data.getKeys().equals(tmp.getAllAttributes().keySet()));
assertEquals(tmp.getAllAttributes().keySet(), data.getKeys());
//same values
for (String name : data.getKeys())
{
assertTrue(data.getAttribute(name).equals(tmp.getAttribute(name)));
assertEquals(tmp.getAttribute(name), data.getAttribute(name));
}
}
return true;
}
public void deleteFile(String sessionId)
public void deleteFile(String sessionId) throws IOException
{
assertNotNull(_tmpDir);
assertTrue(_tmpDir.exists());
String[] files = _tmpDir.list();
assertNotNull(files);
assertFalse(files.length == 0);
String filename = null;
for (String name : files)
// Collect
List<Path> matches = Files.list(storeDirRoot)
.filter((path) -> path.getFileName().toString().contains(sessionId))
.collect(Collectors.toList());
// Delete outside of lambda
for (Path path : matches)
{
if (name.contains(sessionId))
{
filename = name;
break;
}
}
if (filename != null)
{
File f = new File(_tmpDir, filename);
assertTrue(f.delete());
FS.deleteFile(path);
}
}
public FileSessionDataStoreFactory newSessionDataStoreFactory()
{
FileSessionDataStoreFactory storeFactory = new FileSessionDataStoreFactory();
storeFactory.setStoreDir(_tmpDir);
storeFactory.setStoreDir(storeDirRoot.toFile());
return storeFactory;
}
}

View File

@ -22,9 +22,11 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.logging.StacklessLogging;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.junit.jupiter.api.AfterEach;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@ -35,21 +37,16 @@ import static org.junit.jupiter.api.Assertions.fail;
/**
* TestFileSessions
*/
@ExtendWith(WorkDirExtension.class)
public class TestFileSessions extends AbstractTestBase
{
public WorkDir workDir;
FileTestHelper _helper;
@BeforeEach
public void before() throws Exception
{
_helper = new FileTestHelper();
}
@AfterEach
public void after()
{
_helper.teardown();
_helper = null;
_helper = new FileTestHelper(workDir.getEmptyPathDir());
}
@Override

View File

@ -19,12 +19,16 @@
package org.eclipse.jetty.server.session;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* ClusteredOrphanedSessionTest
*/
@ExtendWith(WorkDirExtension.class)
public class ClusteredOrphanedSessionTest extends AbstractClusteredOrphanedSessionTest
{
static
@ -32,26 +36,27 @@ public class ClusteredOrphanedSessionTest extends AbstractClusteredOrphanedSessi
LoggingUtil.init();
}
public static InfinispanTestSupport __testSupport;
public WorkDir workDir;
public InfinispanTestSupport testSupport;
@BeforeAll
public static void setup() throws Exception
@BeforeEach
public void setup() throws Exception
{
__testSupport = new InfinispanTestSupport();
__testSupport.setup();
testSupport = new InfinispanTestSupport();
testSupport.setup(workDir.getEmptyPathDir());
}
@AfterAll
public static void teardown() throws Exception
@AfterEach
public void teardown() throws Exception
{
__testSupport.teardown();
testSupport.teardown();
}
@Override
public SessionDataStoreFactory createSessionDataStoreFactory()
{
InfinispanSessionDataStoreFactory factory = new InfinispanSessionDataStoreFactory();
factory.setCache(__testSupport.getCache());
factory.setCache(testSupport.getCache());
return factory;
}
}

View File

@ -19,31 +19,36 @@
package org.eclipse.jetty.server.session;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* ClusteredSerializedSessionScavengingTest
*/
@ExtendWith(WorkDirExtension.class)
public class ClusteredSerializedSessionScavengingTest extends AbstractClusteredSessionScavengingTest
{
public static InfinispanTestSupport __testSupport;
public WorkDir workDir;
public static InfinispanTestSupport testSupport;
@BeforeAll
public static void setup() throws Exception
@BeforeEach
public void setup() throws Exception
{
__testSupport = new InfinispanTestSupport();
__testSupport.setUseFileStore(true);
__testSupport.setSerializeSessionData(true);
__testSupport.setup();
testSupport = new InfinispanTestSupport();
testSupport.setUseFileStore(true);
testSupport.setSerializeSessionData(true);
testSupport.setup(workDir.getEmptyPathDir());
}
@AfterAll
public static void teardown() throws Exception
@AfterEach
public void teardown() throws Exception
{
if (__testSupport != null)
__testSupport.teardown();
if (testSupport != null)
testSupport.teardown();
}
@Override
@ -61,7 +66,7 @@ public class ClusteredSerializedSessionScavengingTest extends AbstractClusteredS
public SessionDataStoreFactory createSessionDataStoreFactory()
{
InfinispanSessionDataStoreFactory factory = new InfinispanSessionDataStoreFactory();
factory.setCache(__testSupport.getCache());
factory.setCache(testSupport.getCache());
return factory;
}
}

View File

@ -19,13 +19,17 @@
package org.eclipse.jetty.server.session;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* ClusteredSessionScavengingTest
*/
@ExtendWith(WorkDirExtension.class)
public class ClusteredSessionScavengingTest extends AbstractClusteredSessionScavengingTest
{
static
@ -33,21 +37,22 @@ public class ClusteredSessionScavengingTest extends AbstractClusteredSessionScav
LoggingUtil.init();
}
public InfinispanTestSupport _testSupport;
public WorkDir workDir;
public InfinispanTestSupport testSupport;
@BeforeEach
public void setup() throws Exception
{
_testSupport = new InfinispanTestSupport();
_testSupport.setUseFileStore(true);
_testSupport.setup();
testSupport = new InfinispanTestSupport();
testSupport.setUseFileStore(true);
testSupport.setup(workDir.getEmptyPathDir());
}
@AfterEach
public void teardown() throws Exception
{
if (_testSupport != null)
_testSupport.teardown();
if (testSupport != null)
testSupport.teardown();
}
@Override
@ -62,7 +67,7 @@ public class ClusteredSessionScavengingTest extends AbstractClusteredSessionScav
public SessionDataStoreFactory createSessionDataStoreFactory()
{
InfinispanSessionDataStoreFactory factory = new InfinispanSessionDataStoreFactory();
factory.setCache(_testSupport.getCache());
factory.setCache(testSupport.getCache());
return factory;
}
}

View File

@ -18,18 +18,24 @@
package org.eclipse.jetty.server.session;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* HotInitInfinispanSessionDataStoreTest
*/
@ExtendWith(WorkDirExtension.class)
public class InfinispanFileSessionDataStoreTest extends InfinispanSessionDataStoreTest
{
public WorkDir workDir;
@BeforeEach
public void setup() throws Exception
{
_testSupport = new InfinispanTestSupport();
_testSupport.setUseFileStore(true);
_testSupport.setup();
_testSupport.setup(workDir.getEmptyPathDir());
}
}

View File

@ -24,12 +24,15 @@ import org.eclipse.jetty.session.infinispan.InfinispanSessionData;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStore;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.eclipse.jetty.session.infinispan.QueryManager;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.infinispan.query.Search;
import org.infinispan.query.dsl.Query;
import org.infinispan.query.dsl.QueryFactory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ -37,6 +40,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* InfinispanSessionDataStoreTest
*/
@ExtendWith(WorkDirExtension.class)
public class InfinispanSessionDataStoreTest extends AbstractSessionDataStoreTest
{
static
@ -46,11 +50,13 @@ public class InfinispanSessionDataStoreTest extends AbstractSessionDataStoreTest
public InfinispanTestSupport _testSupport;
public WorkDir workDir;
@BeforeEach
public void setup() throws Exception
{
_testSupport = new InfinispanTestSupport();
_testSupport.setup();
_testSupport.setup(workDir.getEmptyPathDir());
}
@AfterEach

View File

@ -45,10 +45,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* InfinispanTestSupport
*/
@ExtendWith(WorkDirExtension.class)
public class InfinispanTestSupport
{
public WorkDir workDir;
public static final String DEFAULT_CACHE_NAME = "session_test_cache";
public Cache _cache;
@ -100,9 +98,8 @@ public class InfinispanTestSupport
return _cache;
}
public void setup() throws Exception
public void setup(Path root) throws Exception
{
Path root = workDir.getEmptyPathDir();
Path indexesDir = root.resolve("indexes");
FS.ensureDirExists(indexesDir);

View File

@ -24,12 +24,15 @@ import org.eclipse.jetty.session.infinispan.InfinispanSessionData;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStore;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.eclipse.jetty.session.infinispan.QueryManager;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.infinispan.query.Search;
import org.infinispan.query.dsl.Query;
import org.infinispan.query.dsl.QueryFactory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ -37,16 +40,19 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* SerializedInfinispanSessionDataStoreTest
*/
@ExtendWith(WorkDirExtension.class)
public class SerializedInfinispanSessionDataStoreTest extends AbstractSessionDataStoreTest
{
public InfinispanTestSupport _testSupport;
public WorkDir workDir;
@BeforeEach
public void setup() throws Exception
{
_testSupport = new InfinispanTestSupport();
_testSupport.setSerializeSessionData(true);
_testSupport.setup();
_testSupport.setup(workDir.getEmptyPathDir());
}
@AfterEach