diff --git a/Jenkinsfile b/Jenkinsfile index 595cb39b2eb..2c342706781 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -54,7 +54,7 @@ pipeline { agent { node { label 'linux' } } options { timeout(time: 30, unit: 'MINUTES') } steps { - mavenBuild("jdk8", "install javadoc:javadoc -DskipTests", "maven3", true) + mavenBuild("jdk11", "install javadoc:javadoc -DskipTests", "maven3", true) warnings consoleParsers: [[parserName: 'Maven'], [parserName: 'JavaDoc'], [parserName: 'Java']] } } diff --git a/jetty-jmh/pom.xml b/jetty-jmh/pom.xml index 6e882632b61..3ee37a274e2 100644 --- a/jetty-jmh/pom.xml +++ b/jetty-jmh/pom.xml @@ -94,12 +94,6 @@ jetty-http ${project.version} - - org.eclipse.jetty - jetty-http - ${project.version} - tests - javax.servlet javax.servlet-api diff --git a/jetty-jmh/src/main/java/org/eclipse/jetty/http/jmh/MultiPartBenchmark.java b/jetty-jmh/src/main/java/org/eclipse/jetty/http/jmh/MultiPartBenchmark.java index 2867de517d9..754d3cc6801 100644 --- a/jetty-jmh/src/main/java/org/eclipse/jetty/http/jmh/MultiPartBenchmark.java +++ b/jetty-jmh/src/main/java/org/eclipse/jetty/http/jmh/MultiPartBenchmark.java @@ -18,9 +18,18 @@ package org.eclipse.jetty.http.jmh; -import org.eclipse.jetty.http.MultiPartCaptureTest.MultipartExpectations; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + import org.eclipse.jetty.http.MultiPartFormInputStream; +import org.eclipse.jetty.toolchain.test.Hex; import org.eclipse.jetty.toolchain.test.IO; +import org.eclipse.jetty.util.QuotedStringTokenizer; +import org.eclipse.jetty.util.StringUtil; +import org.hamcrest.Matchers; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Level; @@ -40,16 +49,25 @@ import org.openjdk.jmh.runner.options.OptionsBuilder; import javax.servlet.MultipartConfigElement; import javax.servlet.http.Part; + +import java.io.BufferedReader; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.security.DigestOutputStream; +import java.security.MessageDigest; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Locale; +import java.util.Objects; import java.util.Random; import java.util.concurrent.TimeUnit; +import java.util.function.Function; @State(Scope.Benchmark) @Threads(4) @@ -277,6 +295,191 @@ public class MultiPartBenchmark new Runner(opt).run(); } + + + public static class MultipartExpectations + { + public final String contentType; + public final int partCount; + public final List partFilenames = new ArrayList<>(); + public final List partSha1sums = new ArrayList<>(); + public final List partContainsContents = new ArrayList<>(); + + public MultipartExpectations(Path expectationsPath) throws IOException + { + String parsedContentType = null; + String parsedPartCount = "-1"; + + try (BufferedReader reader = Files.newBufferedReader(expectationsPath)) + { + String line; + while ((line = reader.readLine()) != null) + { + line = line.trim(); + if (StringUtil.isBlank(line) || line.startsWith("#")) + { + // skip blanks and comments + continue; + } + + String split[] = line.split("\\|"); + switch (split[0]) + { + case "Request-Header": + if(split[1].equalsIgnoreCase("Content-Type")) + { + parsedContentType = split[2]; + } + break; + case "Content-Type": + parsedContentType = split[1]; + break; + case "Parts-Count": + parsedPartCount = split[1]; + break; + case "Part-ContainsContents": + { + NameValue pair = new NameValue(); + pair.name = split[1]; + pair.value = split[2]; + partContainsContents.add(pair); + break; + } + case "Part-Filename": + { + NameValue pair = new NameValue(); + pair.name = split[1]; + pair.value = split[2]; + partFilenames.add(pair); + break; + } + case "Part-Sha1sum": + { + NameValue pair = new NameValue(); + pair.name = split[1]; + pair.value = split[2]; + partSha1sums.add(pair); + break; + } + default: + throw new IOException("Bad Line in " + expectationsPath + ": " + line); + } + } + } + + Objects.requireNonNull(parsedContentType, "Missing required 'Content-Type' declaration: " + expectationsPath); + this.contentType = parsedContentType; + this.partCount = Integer.parseInt(parsedPartCount); + } + + private void checkParts(Collection parts, Function getPart) throws Exception + { + // Evaluate Count + if (partCount >= 0) + { + assertThat("Mulitpart.parts.size", parts.size(), is(partCount)); + } + + String defaultCharset = UTF_8.toString(); + Part charSetPart = getPart.apply("_charset_"); + if(charSetPart != null) + { + defaultCharset = org.eclipse.jetty.util.IO.toString(charSetPart.getInputStream()); + } + + + // Evaluate expected Contents + for (NameValue expected : partContainsContents) + { + Part part = getPart.apply(expected.name); + assertThat("Part[" + expected.name + "]", part, is(notNullValue())); + try (InputStream partInputStream = part.getInputStream()) + { + String charset = getCharsetFromContentType(part.getContentType(), defaultCharset); + String contents = org.eclipse.jetty.util.IO.toString(partInputStream, charset); + assertThat("Part[" + expected.name + "].contents", contents, containsString(expected.value)); + } + } + + // Evaluate expected filenames + for (NameValue expected : partFilenames) + { + Part part = getPart.apply(expected.name); + assertThat("Part[" + expected.name + "]", part, is(notNullValue())); + assertThat("Part[" + expected.name + "]", part.getSubmittedFileName(), is(expected.value)); + } + + // Evaluate expected contents checksums + for (NameValue expected : partSha1sums) + { + Part part = getPart.apply(expected.name); + assertThat("Part[" + expected.name + "]", part, is(notNullValue())); + MessageDigest digest = MessageDigest.getInstance("SHA1"); + try (InputStream partInputStream = part.getInputStream(); + NoOpOutputStream noop = new NoOpOutputStream(); + DigestOutputStream digester = new DigestOutputStream(noop, digest)) + { + org.eclipse.jetty.util.IO.copy(partInputStream, digester); + String actualSha1sum = Hex.asHex(digest.digest()).toLowerCase(Locale.US); + assertThat("Part[" + expected.name + "].sha1sum", actualSha1sum, Matchers.equalToIgnoringCase(expected.value)); + } + } + } + + private String getCharsetFromContentType(String contentType, String defaultCharset) + { + if(StringUtil.isBlank(contentType)) + { + return defaultCharset; + } + + QuotedStringTokenizer tok = new QuotedStringTokenizer(contentType, ";", false, false); + while(tok.hasMoreTokens()) + { + String str = tok.nextToken().trim(); + if(str.startsWith("charset=")) + { + return str.substring("charset=".length()); + } + } + + return defaultCharset; + } + } + + static class NoOpOutputStream extends OutputStream + { + @Override + public void write(byte[] b) throws IOException + { + } + + @Override + public void write(byte[] b, int off, int len) throws IOException + { + } + + @Override + public void flush() throws IOException + { + } + + @Override + public void close() throws IOException + { + } + + @Override + public void write(int b) throws IOException + { + } + } + + public static class NameValue + { + public String name; + public String value; + } } diff --git a/pom.xml b/pom.xml index a4ec07b2c5d..14ca21dda91 100644 --- a/pom.xml +++ b/pom.xml @@ -280,8 +280,8 @@ true false - deploy - -Peclipse-release + javadoc:aggregate-jar deploy + -Peclipse-release -Paggregate-javadoc-jar clean install forked-path @@ -537,10 +537,8 @@ false false protected - com.acme.*;org.slf4j.*;org.mortbay.* - - https://docs.oracle.com/javase/8/docs/api/ - + true + com.acme,org.slf4j*,org.mortbay*,*.jmh*,org.eclipse.jetty.embedded*,org.eclipse.jetty.example.asyncrest*,org.eclipse.jetty.test* @@ -1222,6 +1220,7 @@ org.apache.maven.plugins maven-gpg-plugin + 1.6 sign-artifacts @@ -1282,38 +1281,6 @@ - - - aggregate-site - - - - org.apache.maven.plugins - maven-javadoc-plugin - - com.acme,*.jmh - - http://docs.oracle.com/javase/8/docs/api/ - http://docs.oracle.com/javaee/7/api - http://junit.sourceforge.net/javadoc/ - - - - org.apache.xbean.XBean - X - - - - - - - - compact3 diff --git a/tests/test-distribution/src/main/java/org/eclipse/jetty/tests/distribution/DistributionTester.java b/tests/test-distribution/src/main/java/org/eclipse/jetty/tests/distribution/DistributionTester.java index 0661ca6f7db..44a2a9edda9 100644 --- a/tests/test-distribution/src/main/java/org/eclipse/jetty/tests/distribution/DistributionTester.java +++ b/tests/test-distribution/src/main/java/org/eclipse/jetty/tests/distribution/DistributionTester.java @@ -185,7 +185,7 @@ public class DistributionTester /** * Resolves an artifact given its Maven coordinates. * - * @param coordinates :[:[:]]: + * @param coordinates <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version> * @return the artifact * @see #installWarFile(File, String) */