Merge branch 'jetty-10.0.x' into getter

This commit is contained in:
Greg Wilkins 2023-07-07 11:18:47 +02:00 committed by GitHub
commit db843866e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 269 additions and 106 deletions

View File

@ -17,7 +17,7 @@
<maven.deploy.plugin.version>3.0.0-M2</maven.deploy.plugin.version>
<maven.javadoc.plugin.version>3.4.0</maven.javadoc.plugin.version>
<maven.remote-resources.plugin.version>3.1.0</maven.remote-resources.plugin.version>
<maven.surefire.plugin.version>3.1.0</maven.surefire.plugin.version>
<maven.surefire.plugin.version>3.1.2</maven.surefire.plugin.version>
<maven.deploy.skip>true</maven.deploy.skip>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>

View File

@ -12,7 +12,7 @@
<packaging>pom</packaging>
<properties>
<osgi-version>3.18.300</osgi-version>
<osgi-version>3.18.400</osgi-version>
<osgi-services-version>3.11.100</osgi-services-version>
<osgi-service-cm-version>1.6.1</osgi-service-cm-version>
<osgi-service-component-version>1.5.0</osgi-service-component-version>

View File

@ -12,7 +12,7 @@
<description>Generates a (maven based) P2 Updatesite</description>
<packaging>pom</packaging>
<properties>
<tycho-version>3.0.4</tycho-version>
<tycho-version>4.0.0</tycho-version>
</properties>
<build>
<plugins>

View File

@ -427,7 +427,6 @@ class AsyncContentProducer implements ContentProducer
{
try
{
int remainingBeforeInterception = _rawContent.remaining();
HttpInput.Content content = _interceptor.readFrom(_rawContent);
if (content != null && content.isSpecial() && !_rawContent.isSpecial())
{
@ -444,24 +443,6 @@ class AsyncContentProducer implements ContentProducer
if (LOG.isDebugEnabled())
LOG.debug("interceptor generated special content {}", this);
}
else if (content != _rawContent && !_rawContent.isSpecial() && !_rawContent.isEmpty() && _rawContent.remaining() == remainingBeforeInterception)
{
IOException failure = new IOException("Interceptor " + _interceptor + " did not consume any of the " + _rawContent.remaining() + " remaining byte(s) of content");
if (content != null)
content.failed(failure);
failCurrentContent(failure);
// Set the _error flag to mark the content as definitive, i.e.:
// do not try to produce new raw content to get a fresher error
// when the special content was caused by the interceptor not
// consuming the raw content.
_error = true;
Response response = _httpChannel.getResponse();
if (response.isCommitted())
_httpChannel.abort(failure);
if (LOG.isDebugEnabled())
LOG.debug("interceptor did not consume content {}", this);
content = _transformedContent;
}
if (LOG.isDebugEnabled())
LOG.debug("intercepted raw content {}", this);

View File

@ -282,44 +282,6 @@ public class AsyncContentProducerTest
assertThat(contentFailedCount.get(), is(1));
}
@Test
public void testAsyncContentProducerInterceptorDoesNotConsume()
{
AtomicInteger contentFailedCount = new AtomicInteger();
AtomicInteger interceptorContentFailedCount = new AtomicInteger();
ContentProducer contentProducer = new AsyncContentProducer(new ContentListHttpChannel(List.of(new HttpInput.Content(ByteBuffer.allocate(1))
{
@Override
public void failed(Throwable x)
{
contentFailedCount.incrementAndGet();
}
}), new HttpInput.EofContent()));
try (AutoLock lock = contentProducer.lock())
{
contentProducer.setInterceptor(content -> new HttpInput.Content(ByteBuffer.allocate(1))
{
@Override
public void failed(Throwable x)
{
interceptorContentFailedCount.incrementAndGet();
}
});
assertThat(contentProducer.isReady(), is(true));
HttpInput.Content content1 = contentProducer.nextContent();
assertThat(content1.isSpecial(), is(true));
assertThat(content1.getError().getMessage(), endsWith("did not consume any of the 1 remaining byte(s) of content"));
HttpInput.Content content2 = contentProducer.nextContent();
assertThat(content2.isSpecial(), is(true));
assertThat(content2.getError().getMessage(), endsWith("did not consume any of the 1 remaining byte(s) of content"));
}
assertThat(contentFailedCount.get(), is(1));
assertThat(interceptorContentFailedCount.get(), is(1));
}
@Test
public void testAsyncContentProducerInterceptorDoesNotConsumeEmptyContent()
{

View File

@ -279,33 +279,6 @@ public class BlockingContentProducerTest
assertThat(contentFailedCount.get(), is(1));
}
@Test
public void testBlockingContentProducerInterceptorDoesNotConsume()
{
AtomicInteger contentFailedCount = new AtomicInteger();
ContentProducer contentProducer = new BlockingContentProducer(new AsyncContentProducer(new StaticContentHttpChannel(new HttpInput.Content(ByteBuffer.allocate(1))
{
@Override
public void failed(Throwable x)
{
contentFailedCount.incrementAndGet();
}
})));
try (AutoLock lock = contentProducer.lock())
{
contentProducer.setInterceptor(content -> null);
HttpInput.Content content1 = contentProducer.nextContent();
assertThat(content1.isSpecial(), is(true));
assertThat(content1.getError().getMessage(), endsWith("did not consume any of the 1 remaining byte(s) of content"));
HttpInput.Content content2 = contentProducer.nextContent();
assertThat(content2.isSpecial(), is(true));
assertThat(content2.getError().getMessage(), endsWith("did not consume any of the 1 remaining byte(s) of content"));
}
assertThat(contentFailedCount.get(), is(1));
}
@Test
public void testBlockingContentProducerInterceptorDoesNotConsumeEmptyContent()
{

View File

@ -1423,8 +1423,6 @@ public class ServletContextHandler extends ContextHandler
@Override
public int getSessionTimeout()
{
if (!isStarting())
throw new IllegalStateException();
if (!_enabled)
throw new UnsupportedOperationException();

View File

@ -0,0 +1,178 @@
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.servlet;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.util.BytesRequestContent;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.util.component.LifeCycle;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
/**
* Tests of GzipHandler behavior with gzip compressed Request content.
*/
public class GzipHandlerInputTest
{
private Server server;
private HttpClient client;
@BeforeEach
public void init() throws Exception
{
server = new Server();
ServerConnector connector = new ServerConnector(server);
server.addConnector(connector);
GzipHandler gzipHandler = new GzipHandler();
gzipHandler.setInflateBufferSize(8192); // enable request inflation
ServletContextHandler servletContextHandler = new ServletContextHandler();
servletContextHandler.setContextPath("/");
servletContextHandler.addServlet(ReadAllInputServlet.class, "/inflate");
gzipHandler.setHandler(servletContextHandler);
server.setHandler(gzipHandler);
server.start();
client = new HttpClient();
client.start();
}
@AfterEach
public void stop()
{
LifeCycle.stop(server);
LifeCycle.stop(client);
}
public static Stream<Arguments> transferScenarios()
{
int[] sizes = {
0, 1, 8191, 8192, 8193, 8194, 8195, 8226, 8227, 8260, 8261, 8262, 8263, 8264,
8192, 8193, 8194, 8195, 8226, 8227, 8228, 8259, 8260, 8261, 8262, 8263, 8515,
8516, 8517, 8518, 8773, 8774, 8775, 9216
};
List<Arguments> scenarios = new ArrayList<>();
// Scenarios 1: use Content-Length on request
for (int size : sizes)
{
scenarios.add(Arguments.of(size, true));
}
// Scenarios 2: use Transfer-Encoding: chunked on request
for (int size : sizes)
{
scenarios.add(Arguments.of(size, false));
}
return scenarios.stream();
}
@ParameterizedTest
@MethodSource("transferScenarios")
public void testReadGzippedInput(int testLength, boolean sendContentLength) throws Exception
{
byte[] rawBuf = new byte[testLength];
Arrays.fill(rawBuf, (byte)'x');
byte[] gzipBuf;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzipOut = new GZIPOutputStream(baos))
{
gzipOut.write(rawBuf, 0, rawBuf.length);
gzipOut.flush();
gzipOut.finish();
gzipBuf = baos.toByteArray();
}
URI destURI = server.getURI().resolve("/inflate");
BytesRequestContent bytesRequestContent = new BytesRequestContent(gzipBuf, new byte[0])
{
@Override
public long getLength()
{
if (sendContentLength)
return super.getLength();
return -1; // we want chunked transfer-encoding
}
};
Request request = client.newRequest(destURI)
.method(HttpMethod.POST)
.headers((headers) -> headers.put(HttpHeader.CONTENT_ENCODING, "gzip"))
.body(bytesRequestContent);
ContentResponse response = request.send();
assertThat(response.getStatus(), is(200));
String responseBody = response.getContentAsString();
if (sendContentLength)
assertThat(responseBody, containsString(String.format("[X-Content-Length]: %d", gzipBuf.length)));
else
assertThat(responseBody, containsString("[Transfer-Encoding]: chunked"));
assertThat(responseBody, containsString("[X-Content-Encoding]: gzip"));
assertThat(responseBody, containsString(String.format("Read %d bytes", rawBuf.length)));
}
public static class ReadAllInputServlet extends HttpServlet
{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
InputStream input = req.getInputStream();
byte[] buf = input.readAllBytes();
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/plain");
PrintWriter out = resp.getWriter();
// dump header names & values
List<String> headerNames = Collections.list(req.getHeaderNames());
Collections.sort(headerNames);
for (String headerName : headerNames)
{
List<String> headerValues = Collections.list(req.getHeaders(headerName));
out.printf("header [%s]: %s%n", headerName, String.join(", ", headerValues));
}
// dump number of bytes read
out.printf("Read %d bytes%n", buf.length);
}
}
}

View File

@ -767,6 +767,7 @@ public class ServletContextHandlerTest
Integer timeout = Integer.valueOf(100);
ServletContextHandler root = new ServletContextHandler(contexts, "/", ServletContextHandler.SESSIONS);
root.getSessionHandler().setMaxInactiveInterval((int)TimeUnit.MINUTES.toSeconds(startMin));
root.addServlet(new ServletHolder(TestSessionTimeoutServlet.class), "/");
root.addBean(new MySCIStarter(root.getServletContext(), new MySCI(true, timeout.intValue())), true);
_server.start();
@ -781,6 +782,17 @@ public class ServletContextHandlerTest
assertTrue((Boolean)root.getServletContext().getAttribute("MyContextListener.getSessionTimeout"));
//test can't set session timeout from ContextListener that is not from annotation or web.xml
assertTrue((Boolean)root.getServletContext().getAttribute("MyContextListener.setSessionTimeout"));
//test accessing timeout from a servlet
StringBuilder rawRequest = new StringBuilder();
rawRequest.append("GET / HTTP/1.1\r\n");
rawRequest.append("Host: local\r\n");
rawRequest.append("Connection: close\r\n");
rawRequest.append("\r\n");
String rawResponse = _connector.getResponse(rawRequest.toString());
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
assertEquals(200, response.getStatus(), "response status");
assertEquals("SessionTimeout = " + timeout, response.getContent(), "response content");
}
@Test
@ -2066,6 +2078,20 @@ public class ServletContextHandlerTest
}
}
public static class TestSessionTimeoutServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
int t = req.getServletContext().getSessionTimeout();
resp.setStatus(HttpServletResponse.SC_OK);
PrintWriter writer = resp.getWriter();
writer.write("SessionTimeout = " + t);
}
}
public static class TestServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;

View File

@ -66,7 +66,7 @@ public class XmlParser
*/
public XmlParser()
{
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParserFactory factory = newSAXParserFactory();
boolean validatingDefault = factory.getClass().toString().contains("org.apache.xerces.");
String validatingProp = System.getProperty("org.eclipse.jetty.xml.XmlParser.Validating", validatingDefault ? "true" : "false");
boolean validating = Boolean.valueOf(validatingProp).booleanValue();
@ -83,11 +83,16 @@ public class XmlParser
return _lock.lock();
}
protected SAXParserFactory newSAXParserFactory()
{
return SAXParserFactory.newInstance();
}
public void setValidating(boolean validating)
{
try
{
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParserFactory factory = newSAXParserFactory();
factory.setValidating(validating);
_parser = factory.newSAXParser();
@ -129,6 +134,11 @@ public class XmlParser
return _parser.isValidating();
}
public SAXParser getSAXParser()
{
return _parser;
}
public void redirectEntity(String name, URL entity)
{
if (entity != null)

View File

@ -14,10 +14,17 @@
package org.eclipse.jetty.xml;
import java.net.URL;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.jupiter.api.Test;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
public class XmlParserTest
{
@ -38,4 +45,32 @@ public class XmlParserTest
assertTrue(testDocStr.startsWith("<Configure"));
assertTrue(testDocStr.endsWith("</Configure>"));
}
/**
* Customize SAXParserFactory behavior.
*/
@Test
public void testNewSAXParserFactory() throws SAXException
{
XmlParser xmlParser = new XmlParser()
{
@Override
protected SAXParserFactory newSAXParserFactory()
{
SAXParserFactory saxParserFactory = super.newSAXParserFactory();
// Configure at factory level
saxParserFactory.setXIncludeAware(false);
return saxParserFactory;
}
};
SAXParser saxParser = xmlParser.getSAXParser();
assertNotNull(saxParser);
XMLReader xmlReader = saxParser.getXMLReader();
// Only run testcase if Xerces is being used.
assumeTrue(xmlReader.getClass().getName().contains("org.apache.xerces."));
// look to see it was set at XMLReader level
assertFalse(xmlReader.getFeature("http://apache.org/xml/features/xinclude"));
}
}

30
pom.xml
View File

@ -28,17 +28,17 @@
<apache.avro.version>1.11.1</apache.avro.version>
<apache.httpclient.version>4.5.14</apache.httpclient.version>
<apache.httpcore.version>4.4.16</apache.httpcore.version>
<asciidoctorj-diagram.version>2.2.8</asciidoctorj-diagram.version>
<asciidoctorj-diagram.version>2.2.9</asciidoctorj-diagram.version>
<asciidoctorj.version>2.5.6</asciidoctorj.version>
<mina.core.version>2.2.1</mina.core.version>
<mina.core.version>2.2.2</mina.core.version>
<asm.version>9.5</asm.version>
<awaitility.version>4.2.0</awaitility.version>
<bndlib.version>6.3.1</bndlib.version>
<build-support.version>1.5</build-support.version>
<checkstyle.version>10.3.4</checkstyle.version>
<commons-codec.version>1.15</commons-codec.version>
<commons-codec.version>1.16.0</commons-codec.version>
<commons.compress.version>1.23.0</commons.compress.version>
<commons.io.version>2.12.0</commons.io.version>
<commons.io.version>2.13.0</commons.io.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<conscrypt.version>2.5.2</conscrypt.version>
<disruptor.version>3.4.2</disruptor.version>
@ -79,7 +79,7 @@
<javax.servlet.jsp.jstl.impl.version>1.2.5</javax.servlet.jsp.jstl.impl.version>
<jboss.logging.annotations.version>2.2.1.Final</jboss.logging.annotations.version>
<jboss.logging.processor.version>2.2.1.Final</jboss.logging.processor.version>
<jboss.logging.version>3.5.0.Final</jboss.logging.version>
<jboss.logging.version>3.5.3.Final</jboss.logging.version>
<jboss-logmanager.version>2.1.19.Final</jboss-logmanager.version>
<jboss-threads.version>3.5.0.Final</jboss-threads.version>
<jetty-assembly-descriptors.version>1.1</jetty-assembly-descriptors.version>
@ -102,10 +102,10 @@
<junit.version>5.9.1</junit.version>
<kerb-simplekdc.version>2.0.3</kerb-simplekdc.version>
<log4j2.version>2.20.0</log4j2.version>
<logback.version>1.3.7</logback.version>
<logback.version>1.3.8</logback.version>
<mariadb.version>3.0.8</mariadb.version>
<mariadb.docker.version>10.3.6</mariadb.docker.version>
<maven.resolver.version>1.9.10</maven.resolver.version>
<maven.resolver.version>1.9.13</maven.resolver.version>
<maven.version>3.9.0</maven.version>
<mongodb.version>3.12.11</mongodb.version>
<openpojo.version>0.9.1</openpojo.version>
@ -115,7 +115,7 @@
<org.osgi.util.promise.version>1.2.0</org.osgi.util.promise.version>
<plexus-component-annotations.version>2.1.1</plexus-component-annotations.version>
<plexus-utils.version>4.0.0</plexus-utils.version>
<plexus-xml.version>4.0.0</plexus-xml.version>
<plexus-xml.version>4.0.2</plexus-xml.version>
<slf4j.version>2.0.5</slf4j.version>
<springboot.version>2.1.1.RELEASE</springboot.version>
<taglibs-standard-impl.version>1.2.5</taglibs-standard-impl.version>
@ -123,7 +123,7 @@
<testcontainers.version>1.18.3</testcontainers.version>
<weld.version>3.1.9.Final</weld.version>
<wildfly.common.version>1.6.0.Final</wildfly.common.version>
<wildfly.elytron.version>2.2.0.Final</wildfly.elytron.version>
<wildfly.elytron.version>2.2.1.Final</wildfly.elytron.version>
<xmemcached.version>2.4.7</xmemcached.version>
<!-- some maven plugins versions -->
@ -139,7 +139,7 @@
<maven.antrun.plugin.version>3.1.0</maven.antrun.plugin.version>
<maven.assembly.plugin.version>3.6.0</maven.assembly.plugin.version>
<maven.bundle.plugin.version>5.1.9</maven.bundle.plugin.version>
<maven.clean.plugin.version>3.2.0</maven.clean.plugin.version>
<maven.clean.plugin.version>3.3.1</maven.clean.plugin.version>
<maven.checkstyle.plugin.version>3.3.0</maven.checkstyle.plugin.version>
<maven.compiler.plugin.version>3.11.0</maven.compiler.plugin.version>
<maven.dependency.plugin.version>3.6.0</maven.dependency.plugin.version>
@ -148,19 +148,19 @@
<maven.exec.plugin.version>3.1.0</maven.exec.plugin.version>
<maven.gpg.plugin.version>3.1.0</maven.gpg.plugin.version>
<maven.install.plugin.version>3.1.1</maven.install.plugin.version>
<maven.invoker.plugin.version>3.5.1</maven.invoker.plugin.version>
<maven.invoker.plugin.version>3.6.0</maven.invoker.plugin.version>
<groovy.version>4.0.6</groovy.version>
<maven.jar.plugin.version>3.3.0</maven.jar.plugin.version>
<maven.javadoc.plugin.version>3.5.0</maven.javadoc.plugin.version>
<maven.plugin-tools.version>3.9.0</maven.plugin-tools.version>
<maven-plugin.plugin.version>3.9.0</maven-plugin.plugin.version>
<maven.release.plugin.version>3.0.0</maven.release.plugin.version>
<maven.release.plugin.version>3.0.1</maven.release.plugin.version>
<maven.remote-resources-plugin.version>3.1.0</maven.remote-resources-plugin.version>
<maven.resources.plugin.version>3.3.1</maven.resources.plugin.version>
<maven.shade.plugin.version>3.4.1</maven.shade.plugin.version>
<maven.surefire.plugin.version>3.1.0</maven.surefire.plugin.version>
<maven.shade.plugin.version>3.5.0</maven.shade.plugin.version>
<maven.surefire.plugin.version>3.1.2</maven.surefire.plugin.version>
<maven.source.plugin.version>3.3.0</maven.source.plugin.version>
<maven.war.plugin.version>3.3.2</maven.war.plugin.version>
<maven.war.plugin.version>3.4.0</maven.war.plugin.version>
<spotbugs.maven.plugin.version>4.7.2.0</spotbugs.maven.plugin.version>
<versions.maven.plugin.version>2.12.0</versions.maven.plugin.version>