Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x-fixed
This commit is contained in:
commit
e3e3f9eb0b
|
@ -5,12 +5,8 @@ Thank you for your interest in this project!
|
|||
Project description
|
||||
--------------------
|
||||
Jetty is a lightweight highly scalable java based web server and servlet engine.
|
||||
Our goal is to support web protocols like HTTP, HTTP/2, and WebSocket in a high
|
||||
volume, low latency way that provides maximum performance while retaining the ease
|
||||
of use and compatibility with years of servlet development.
|
||||
Jetty is a modern fully async web server that has a long history as a component
|
||||
oriented technology easily embedded into applications while still offering a solid
|
||||
traditional distribution for webapp deployment.
|
||||
Our goal is to support web protocols like HTTP, HTTP/2, and WebSocket in a high volume, low latency way that provides maximum performance while retaining the ease of use and compatibility with years of servlet development.
|
||||
Jetty is a modern fully async web server that has a long history as a component oriented technology easily embedded into applications while still offering a solid traditional distribution for webapp deployment.
|
||||
|
||||
- [https://projects.eclipse.org/projects/rt.jetty](https://projects.eclipse.org/projects/rt.jetty)
|
||||
|
||||
|
@ -21,8 +17,7 @@ Information regarding source code management, builds, coding standards, and more
|
|||
- [https://www.eclipse.org/jetty/documentation/current/advanced-contributing.html](https://www.eclipse.org/jetty/documentation/current/advanced-contributing.html)
|
||||
|
||||
The canonical Jetty git repository is located at [GitHub.](https://github.com/eclipse/jetty.project) Providing you have
|
||||
completed the contributors agreement mentioned below we will endeavor to pull
|
||||
your commit into Jetty proper.
|
||||
completed the contributors agreement mentioned below we will endeavor to pull your commit into Jetty proper.
|
||||
|
||||
Eclipse Contributor Agreement
|
||||
------------------------------
|
||||
|
@ -32,7 +27,11 @@ Before your contribution can be accepted by the project, you need to create and
|
|||
create an account with the Eclipse Foundation if you have not already done so.
|
||||
2. Click on "Eclipse ECA", and complete the form.
|
||||
|
||||
Be sure to use the same email address in your Eclipse account that you intend to use when you commit to Git.
|
||||
Be sure to use the same email address in your Eclipse account that you intend to use when you commit to GitHub.
|
||||
All committers, and all commits , are bound to the [Developer Certificate of Origin.](https://www.eclipse.org/legal/DCO.php)
|
||||
As such, all parties involved in a contribution must have valid ECAs and commits must include [valid "Signed-off-by" entries.](https://wiki.eclipse.org/Development_Resources/Contributing_via_Git)
|
||||
Commits can be signed off by included the `-s` attribute in your commit message, for example, `git commit -s -am 'Interesting Commit Message.`
|
||||
|
||||
|
||||
Contact
|
||||
--------
|
||||
|
|
|
@ -1,128 +1,164 @@
|
|||
#!groovy
|
||||
|
||||
node {
|
||||
// System Dependent Locations
|
||||
def mvntool = tool name: 'maven3', type: 'hudson.tasks.Maven$MavenInstallation'
|
||||
def jdktool = tool name: 'jdk8', type: 'hudson.model.JDK'
|
||||
|
||||
// Environment
|
||||
List mvnEnv = ["PATH+MVN=${mvntool}/bin", "PATH+JDK=${jdktool}/bin", "JAVA_HOME=${jdktool}/", "MAVEN_HOME=${mvntool}"]
|
||||
mvnEnv.add("MAVEN_OPTS=-Xms256m -Xmx1024m -Djava.awt.headless=true")
|
||||
|
||||
try
|
||||
{
|
||||
stage('Checkout') {
|
||||
checkout scm
|
||||
}
|
||||
} catch (Exception e) {
|
||||
notifyBuild("Checkout Failure")
|
||||
throw e
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stage('Compile') {
|
||||
withEnv(mvnEnv) {
|
||||
timeout(time: 15, unit: 'MINUTES') {
|
||||
sh "mvn -B clean install -Dtest=None"
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
notifyBuild("Compile Failure")
|
||||
throw e
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stage('Javadoc') {
|
||||
withEnv(mvnEnv) {
|
||||
timeout(time: 20, unit: 'MINUTES') {
|
||||
sh "mvn -B javadoc:javadoc"
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
notifyBuild("Javadoc Failure")
|
||||
throw e
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stage('Test') {
|
||||
withEnv(mvnEnv) {
|
||||
timeout(time: 90, unit: 'MINUTES') {
|
||||
// Run test phase / ignore test failures
|
||||
sh "mvn -B install -Dmaven.test.failure.ignore=true -Prun-its"
|
||||
// Report failures in the jenkins UI
|
||||
step([$class: 'JUnitResultArchiver',
|
||||
testResults: '**/target/surefire-reports/TEST-*.xml'])
|
||||
// Collect up the jacoco execution results
|
||||
def jacocoExcludes =
|
||||
// build tools
|
||||
"**/org/eclipse/jetty/ant/**" +
|
||||
",**/org/eclipse/jetty/maven/**" +
|
||||
",**/org/eclipse/jetty/jspc/**" +
|
||||
// example code / documentation
|
||||
",**/org/eclipse/jetty/embedded/**" +
|
||||
",**/org/eclipse/jetty/asyncrest/**" +
|
||||
",**/org/eclipse/jetty/demo/**" +
|
||||
// special environments / late integrations
|
||||
",**/org/eclipse/jetty/gcloud/**" +
|
||||
",**/org/eclipse/jetty/infinispan/**" +
|
||||
",**/org/eclipse/jetty/osgi/**" +
|
||||
",**/org/eclipse/jetty/spring/**" +
|
||||
",**/org/eclipse/jetty/http/spi/**" +
|
||||
// test classes
|
||||
",**/org/eclipse/jetty/tests/**" +
|
||||
",**/org/eclipse/jetty/test/**";
|
||||
step([$class: 'JacocoPublisher',
|
||||
inclusionPattern: '**/org/eclipse/jetty/**/*.class',
|
||||
exclusionPattern: jacocoExcludes,
|
||||
execPattern: '**/target/jacoco.exec',
|
||||
classPattern: '**/target/classes',
|
||||
sourcePattern: '**/src/main/java'])
|
||||
// Report on Maven and Javadoc warnings
|
||||
step([$class: 'WarningsPublisher',
|
||||
consoleParsers: [
|
||||
[parserName: 'Maven'],
|
||||
[parserName: 'JavaDoc'],
|
||||
[parserName: 'JavaC']
|
||||
]])
|
||||
}
|
||||
if(isUnstable())
|
||||
{
|
||||
notifyBuild("Unstable / Test Errors")
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
notifyBuild("Test Failure")
|
||||
throw e
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stage 'Compact3'
|
||||
|
||||
dir("aggregates/jetty-all-compact3") {
|
||||
withEnv(mvnEnv) {
|
||||
sh "mvn -B -Pcompact3 clean install"
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
notifyBuild("Compact3 Failure")
|
||||
throw e
|
||||
def jdks = ["jdk8", "jdk9"]
|
||||
def oss = ["linux"] //windows? ,"linux-docker"
|
||||
def builds = [:]
|
||||
for (def os in oss) {
|
||||
for (def jdk in jdks) {
|
||||
builds[os+"_"+jdk] = getFullBuild( jdk, os )
|
||||
}
|
||||
}
|
||||
|
||||
parallel builds
|
||||
|
||||
def getFullBuild(jdk, os) {
|
||||
return {
|
||||
node(os) {
|
||||
// System Dependent Locations
|
||||
def mvntool = tool name: 'maven3', type: 'hudson.tasks.Maven$MavenInstallation'
|
||||
def jdktool = tool name: "$jdk", type: 'hudson.model.JDK'
|
||||
|
||||
// Environment
|
||||
List mvnEnv = ["PATH+MVN=${mvntool}/bin", "PATH+JDK=${jdktool}/bin", "JAVA_HOME=${jdktool}/", "MAVEN_HOME=${mvntool}"]
|
||||
mvnEnv.add("MAVEN_OPTS=-Xms256m -Xmx1024m -Djava.awt.headless=true")
|
||||
|
||||
try
|
||||
{
|
||||
stage("Checkout - ${jdk}") {
|
||||
checkout scm
|
||||
}
|
||||
} catch (Exception e) {
|
||||
notifyBuild("Checkout Failure", jdk)
|
||||
throw e
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stage("Compile - ${jdk}") {
|
||||
withEnv(mvnEnv) {
|
||||
timeout(time: 15, unit: 'MINUTES') {
|
||||
withMaven(
|
||||
maven: 'maven3',
|
||||
jdk: "$jdk",
|
||||
publisherStrategy: 'EXPLICIT',
|
||||
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") {
|
||||
sh "mvn -V -B clean install -Dtest=None -T6"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
notifyBuild("Compile Failure", jdk)
|
||||
throw e
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stage("Javadoc - ${jdk}") {
|
||||
withEnv(mvnEnv) {
|
||||
timeout(time: 20, unit: 'MINUTES') {
|
||||
withMaven(
|
||||
maven: 'maven3',
|
||||
jdk: "$jdk",
|
||||
publisherStrategy: 'EXPLICIT',
|
||||
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") {
|
||||
sh "mvn -V -B javadoc:javadoc -T5"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
notifyBuild("Javadoc Failure", jdk)
|
||||
throw e
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stage("Test - ${jdk}") {
|
||||
withEnv(mvnEnv) {
|
||||
timeout(time: 90, unit: 'MINUTES') {
|
||||
// Run test phase / ignore test failures
|
||||
withMaven(
|
||||
maven: 'maven3',
|
||||
jdk: "$jdk",
|
||||
publisherStrategy: 'EXPLICIT',
|
||||
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") {
|
||||
//
|
||||
sh "mvn -V -B install -Dmaven.test.failure.ignore=true -Prun-its -T3 -e -Dmaven.repo.local=${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}"
|
||||
}
|
||||
// withMaven doesn't label..
|
||||
// Report failures in the jenkins UI
|
||||
junit testResults:'**/target/surefire-reports/TEST-*.xml'
|
||||
// Collect up the jacoco execution results
|
||||
def jacocoExcludes =
|
||||
// build tools
|
||||
"**/org/eclipse/jetty/ant/**" + ",**/org/eclipse/jetty/maven/**" +
|
||||
",**/org/eclipse/jetty/jspc/**" +
|
||||
// example code / documentation
|
||||
",**/org/eclipse/jetty/embedded/**" + ",**/org/eclipse/jetty/asyncrest/**" +
|
||||
",**/org/eclipse/jetty/demo/**" +
|
||||
// special environments / late integrations
|
||||
",**/org/eclipse/jetty/gcloud/**" + ",**/org/eclipse/jetty/infinispan/**" +
|
||||
",**/org/eclipse/jetty/osgi/**" + ",**/org/eclipse/jetty/spring/**" +
|
||||
",**/org/eclipse/jetty/http/spi/**" +
|
||||
// test classes
|
||||
",**/org/eclipse/jetty/tests/**" + ",**/org/eclipse/jetty/test/**";
|
||||
step( [$class : 'JacocoPublisher',
|
||||
inclusionPattern: '**/org/eclipse/jetty/**/*.class',
|
||||
exclusionPattern: jacocoExcludes,
|
||||
execPattern : '**/target/jacoco.exec',
|
||||
classPattern : '**/target/classes',
|
||||
sourcePattern : '**/src/main/java'] )
|
||||
// Report on Maven and Javadoc warnings
|
||||
step( [$class : 'WarningsPublisher',
|
||||
consoleParsers: [[parserName: 'Maven'],
|
||||
[parserName: 'JavaDoc'],
|
||||
[parserName: 'JavaC']]] )
|
||||
}
|
||||
if(isUnstable())
|
||||
{
|
||||
notifyBuild("Unstable / Test Errors", jdk)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
notifyBuild("Test Failure", jdk)
|
||||
throw e
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stage ("Compact3 - ${jdk}") {
|
||||
|
||||
dir("aggregates/jetty-all-compact3") {
|
||||
withEnv(mvnEnv) {
|
||||
withMaven(
|
||||
maven: 'maven3',
|
||||
jdk: "$jdk",
|
||||
publisherStrategy: 'EXPLICIT',
|
||||
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") {
|
||||
sh "mvn -V -B -Pcompact3 clean install -T5"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
notifyBuild("Compact3 Failure", jdk)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// True if this build is part of the "active" branches
|
||||
// for Jetty.
|
||||
def isActiveBranch()
|
||||
{
|
||||
def branchName = "${env.BRANCH_NAME}"
|
||||
return ( branchName == "master" ||
|
||||
branchName.startsWith("jetty-") );
|
||||
( branchName.startsWith("jetty-") && branchName.endsWith(".x") ) );
|
||||
}
|
||||
|
||||
// Test if the Jenkins Pipeline or Step has marked the
|
||||
|
@ -133,7 +169,7 @@ def isUnstable()
|
|||
}
|
||||
|
||||
// Send a notification about the build status
|
||||
def notifyBuild(String buildStatus)
|
||||
def notifyBuild(String buildStatus, String jdk)
|
||||
{
|
||||
if ( !isActiveBranch() )
|
||||
{
|
||||
|
@ -145,20 +181,20 @@ def notifyBuild(String buildStatus)
|
|||
buildStatus = buildStatus ?: "UNKNOWN"
|
||||
|
||||
def email = "${env.EMAILADDRESS}"
|
||||
def summary = "${env.JOB_NAME}#${env.BUILD_NUMBER} - ${buildStatus}"
|
||||
def summary = "${env.JOB_NAME}#${env.BUILD_NUMBER} - ${buildStatus} with jdk ${jdk}"
|
||||
def detail = """<h4>Job: <a href='${env.JOB_URL}'>${env.JOB_NAME}</a> [#${env.BUILD_NUMBER}]</h4>
|
||||
<p><b>${buildStatus}</b></p>
|
||||
<table>
|
||||
<tr><td>Build</td><td><a href='${env.BUILD_URL}'>${env.BUILD_URL}</a></td><tr>
|
||||
<tr><td>Console</td><td><a href='${env.BUILD_URL}console'>${env.BUILD_URL}console</a></td><tr>
|
||||
<tr><td>Test Report</td><td><a href='${env.BUILD_URL}testReport/'>${env.BUILD_URL}testReport/</a></td><tr>
|
||||
</table>
|
||||
"""
|
||||
<p><b>${buildStatus}</b></p>
|
||||
<table>
|
||||
<tr><td>Build</td><td><a href='${env.BUILD_URL}'>${env.BUILD_URL}</a></td><tr>
|
||||
<tr><td>Console</td><td><a href='${env.BUILD_URL}console'>${env.BUILD_URL}console</a></td><tr>
|
||||
<tr><td>Test Report</td><td><a href='${env.BUILD_URL}testReport/'>${env.BUILD_URL}testReport/</a></td><tr>
|
||||
</table>
|
||||
"""
|
||||
|
||||
emailext (
|
||||
to: email,
|
||||
subject: summary,
|
||||
body: detail
|
||||
to: email,
|
||||
subject: summary,
|
||||
body: detail
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -171,6 +171,9 @@ jetty-9.4.7.v20170914 - 14 September 2017
|
|||
+ 475546 ClosedChannelException when connection to HTTPS over HTTP proxy
|
||||
with CONNECT
|
||||
|
||||
jetty-9.2.24.v20180105 - 05 January 2018
|
||||
+ 2065 Backport #347 to Jetty 9.2.x
|
||||
|
||||
jetty-9.2.23.v20171218 - 18 December 2017
|
||||
+ 1556 Remove a timing channel in Password matching
|
||||
+ 1685 Update ALPN support for Java 8u141
|
||||
|
|
|
@ -121,6 +121,7 @@ public class AbstractRestServlet extends HttpServlet
|
|||
return w;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
doGet(request, response);
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.eclipse.jetty.util.ajax.JSON;
|
|||
*/
|
||||
public class SerialRestServlet extends AbstractRestServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
long start = System.nanoTime();
|
||||
|
@ -98,6 +99,7 @@ public class SerialRestServlet extends AbstractRestServlet
|
|||
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
|
||||
* response)
|
||||
*/
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
doGet(request, response);
|
||||
|
|
|
@ -49,6 +49,7 @@ public class HelloHandler extends AbstractHandler
|
|||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle( String target,
|
||||
Request baseRequest,
|
||||
HttpServletRequest request,
|
||||
|
|
|
@ -72,6 +72,7 @@ public class ManyHandlers
|
|||
*/
|
||||
public static class ParamHandler extends AbstractHandler
|
||||
{
|
||||
@Override
|
||||
public void handle( String target,
|
||||
Request baseRequest,
|
||||
HttpServletRequest request,
|
||||
|
|
|
@ -167,6 +167,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
_stat = stat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception
|
||||
{
|
||||
if (_stat != null)
|
||||
|
@ -275,6 +276,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
return _indexMap.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
if (_ordering == null)
|
||||
|
|
|
@ -61,6 +61,7 @@ public class AnnotationIntrospector
|
|||
_introspectAncestors = introspectAncestors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Class<?> clazz)
|
||||
{
|
||||
Class<?> c = clazz;
|
||||
|
|
|
@ -44,6 +44,7 @@ public class ClassInheritanceHandler extends AbstractHandler
|
|||
_inheritanceMap = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ClassInfo classInfo)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -49,6 +49,7 @@ public class ContainerInitializerAnnotationHandler extends AbstractHandler
|
|||
*
|
||||
* @see org.eclipse.jetty.annotations.AnnotationParser.Handler#handle(org.eclipse.jetty.annotations.AnnotationParser.ClassInfo, String)
|
||||
*/
|
||||
@Override
|
||||
public void handle(ClassInfo info, String annotationName)
|
||||
{
|
||||
if (annotationName == null || !_annotation.getName().equals(annotationName))
|
||||
|
@ -62,6 +63,7 @@ public class ContainerInitializerAnnotationHandler extends AbstractHandler
|
|||
*
|
||||
* @see org.eclipse.jetty.annotations.AnnotationParser.Handler#handle(org.eclipse.jetty.annotations.AnnotationParser.FieldInfo, String)
|
||||
*/
|
||||
@Override
|
||||
public void handle(FieldInfo info, String annotationName)
|
||||
{
|
||||
if (annotationName == null || !_annotation.getName().equals(annotationName))
|
||||
|
@ -74,6 +76,7 @@ public class ContainerInitializerAnnotationHandler extends AbstractHandler
|
|||
*
|
||||
* @see org.eclipse.jetty.annotations.AnnotationParser.Handler#handle(org.eclipse.jetty.annotations.AnnotationParser.MethodInfo, String)
|
||||
*/
|
||||
@Override
|
||||
public void handle(MethodInfo info, String annotationName)
|
||||
{
|
||||
if (annotationName == null || !_annotation.getName().equals(annotationName))
|
||||
|
|
|
@ -48,6 +48,7 @@ public class DeclareRolesAnnotationHandler extends AbstractIntrospectableAnnotat
|
|||
/**
|
||||
* @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public void doHandle(Class clazz)
|
||||
{
|
||||
if (!Servlet.class.isAssignableFrom(clazz))
|
||||
|
|
|
@ -46,6 +46,7 @@ public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnno
|
|||
/**
|
||||
* @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public void doHandle(Class clazz)
|
||||
{
|
||||
if (!Servlet.class.isAssignableFrom(clazz))
|
||||
|
|
|
@ -41,6 +41,7 @@ public class PostConstructAnnotationHandler extends AbstractIntrospectableAnnota
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void doHandle(Class clazz)
|
||||
{
|
||||
//Check that the PostConstruct is on a class that we're interested in
|
||||
|
|
|
@ -40,6 +40,7 @@ public class PreDestroyAnnotationHandler extends AbstractIntrospectableAnnotatio
|
|||
_context = wac;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doHandle(Class clazz)
|
||||
{
|
||||
//Check that the PreDestroy is on a class that we're interested in
|
||||
|
|
|
@ -61,6 +61,7 @@ public class ResourceAnnotationHandler extends AbstractIntrospectableAnnotationH
|
|||
* environment that will be looked up at runtime. They do
|
||||
* not specify an injection.
|
||||
*/
|
||||
@Override
|
||||
public void doHandle(Class<?> clazz)
|
||||
{
|
||||
if (supportsResourceInjection(clazz))
|
||||
|
|
|
@ -40,6 +40,7 @@ public class ResourcesAnnotationHandler extends AbstractIntrospectableAnnotation
|
|||
_wac = wac;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doHandle (Class<?> clazz)
|
||||
{
|
||||
Resources resources = (Resources)clazz.getAnnotation(Resources.class);
|
||||
|
|
|
@ -44,6 +44,7 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
|
|||
_context = wac;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doHandle (Class clazz)
|
||||
{
|
||||
if (!Servlet.class.isAssignableFrom(clazz))
|
||||
|
|
|
@ -48,6 +48,7 @@ public class ServletContainerInitializersStarter extends AbstractLifeCycle imple
|
|||
* Call the doStart method of the ServletContainerInitializers
|
||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
|
||||
*/
|
||||
@Override
|
||||
public void doStart()
|
||||
{
|
||||
List<ContainerInitializer> initializers = (List<ContainerInitializer>)_context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
|
||||
|
|
|
@ -69,6 +69,7 @@ public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnno
|
|||
/**
|
||||
* @see org.eclipse.jetty.annotations.AnnotationIntrospector.IntrospectableAnnotationHandler#handle(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public void doHandle(Class clazz)
|
||||
{
|
||||
if (!(_context.getSecurityHandler() instanceof ConstraintAware))
|
||||
|
|
|
@ -58,6 +58,7 @@ public class WebFilterAnnotation extends DiscoveredAnnotation
|
|||
/**
|
||||
* @see DiscoveredAnnotation#apply()
|
||||
*/
|
||||
@Override
|
||||
public void apply()
|
||||
{
|
||||
// TODO verify against rules for annotation v descriptor
|
||||
|
|
|
@ -58,6 +58,7 @@ public class WebListenerAnnotation extends DiscoveredAnnotation
|
|||
/**
|
||||
* @see DiscoveredAnnotation#apply()
|
||||
*/
|
||||
@Override
|
||||
public void apply()
|
||||
{
|
||||
Class<? extends java.util.EventListener> clazz = (Class<? extends EventListener>)getTargetClass();
|
||||
|
|
|
@ -34,6 +34,7 @@ public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotation
|
|||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ClassInfo info, String annotationName)
|
||||
{
|
||||
if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(annotationName))
|
||||
|
@ -43,6 +44,7 @@ public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotation
|
|||
addAnnotation(wlAnnotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(FieldInfo info, String annotationName)
|
||||
{
|
||||
if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(annotationName))
|
||||
|
@ -50,6 +52,7 @@ public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotation
|
|||
LOG.warn ("@WebListener is not applicable to fields: "+info.getClassInfo().getClassName()+"."+info.getFieldName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(MethodInfo info, String annotationName)
|
||||
{
|
||||
if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(annotationName))
|
||||
|
|
|
@ -65,6 +65,7 @@ public class WebServletAnnotation extends DiscoveredAnnotation
|
|||
/**
|
||||
* @see DiscoveredAnnotation#apply()
|
||||
*/
|
||||
@Override
|
||||
public void apply()
|
||||
{
|
||||
//TODO check this algorithm with new rules for applying descriptors and annotations in order
|
||||
|
|
|
@ -45,6 +45,7 @@ public class ClassB extends ClassA implements InterfaceD
|
|||
System.err.println("ClassB.package");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void l()
|
||||
{
|
||||
System.err.println("Overridden method l has no annotation");
|
||||
|
|
|
@ -57,6 +57,7 @@ public class FilterC implements Filter
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
|
@ -69,10 +70,12 @@ public class FilterC implements Filter
|
|||
arg2.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig arg0) throws ServletException
|
||||
{
|
||||
}
|
||||
|
|
|
@ -26,11 +26,13 @@ import javax.servlet.annotation.WebListener;
|
|||
public class ListenerC implements ServletContextListener
|
||||
{
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent arg0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent arg0)
|
||||
{
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ public class ServletC extends HttpServlet
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
response.setContentType("text/html");
|
||||
|
|
|
@ -54,6 +54,7 @@ public class TestAnnotationInheritance
|
|||
public final List<String> annotatedMethods = new ArrayList<String>();
|
||||
public final List<String> annotatedFields = new ArrayList<String>();
|
||||
|
||||
@Override
|
||||
public void handle(ClassInfo info, String annotation)
|
||||
{
|
||||
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
|
||||
|
@ -62,6 +63,7 @@ public class TestAnnotationInheritance
|
|||
annotatedClassNames.add(info.getClassName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(FieldInfo info, String annotation)
|
||||
{
|
||||
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
|
||||
|
@ -69,6 +71,7 @@ public class TestAnnotationInheritance
|
|||
annotatedFields.add(info.getClassInfo().getClassName()+"."+info.getFieldName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(MethodInfo info, String annotation)
|
||||
{
|
||||
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
|
||||
|
|
|
@ -116,6 +116,7 @@ public class TestAnnotationParser
|
|||
{
|
||||
private List<String> methods = Arrays.asList("a","b","c","d","l");
|
||||
|
||||
@Override
|
||||
public void handle(ClassInfo info, String annotation)
|
||||
{
|
||||
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
|
||||
|
@ -124,6 +125,7 @@ public class TestAnnotationParser
|
|||
assertEquals("org.eclipse.jetty.annotations.ClassA",info.getClassName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(FieldInfo info, String annotation)
|
||||
{
|
||||
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
|
||||
|
@ -132,6 +134,7 @@ public class TestAnnotationParser
|
|||
assertEquals(org.objectweb.asm.Type.OBJECT,org.objectweb.asm.Type.getType(info.getFieldType()).getSort());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(MethodInfo info, String annotation)
|
||||
{
|
||||
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
|
||||
|
@ -158,6 +161,7 @@ public class TestAnnotationParser
|
|||
|
||||
class MultiAnnotationHandler extends AnnotationParser.AbstractHandler
|
||||
{
|
||||
@Override
|
||||
public void handle(ClassInfo info, String annotation)
|
||||
{
|
||||
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))
|
||||
|
@ -165,6 +169,7 @@ public class TestAnnotationParser
|
|||
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(info.getClassName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(FieldInfo info, String annotation)
|
||||
{
|
||||
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))
|
||||
|
@ -173,6 +178,7 @@ public class TestAnnotationParser
|
|||
fail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(MethodInfo info, String annotation)
|
||||
{
|
||||
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))
|
||||
|
|
|
@ -591,6 +591,7 @@ public class AntWebAppContext extends WebAppContext
|
|||
/**
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void doStart()
|
||||
{
|
||||
try
|
||||
|
@ -627,6 +628,7 @@ public class AntWebAppContext extends WebAppContext
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doStop()
|
||||
{
|
||||
try
|
||||
|
|
|
@ -19,16 +19,8 @@
|
|||
package org.eclipse.jetty.ant;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.tools.ant.AntClassLoader;
|
||||
import org.eclipse.jetty.util.PatternMatcher;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.WebAppClassLoader;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
@ -50,6 +42,7 @@ public class AntWebInfConfiguration extends WebInfConfiguration
|
|||
*
|
||||
* @see WebXmlConfiguration#configure(WebAppContext)
|
||||
*/
|
||||
@Override
|
||||
public void configure(WebAppContext context) throws Exception
|
||||
{
|
||||
if (context instanceof AntWebAppContext)
|
||||
|
|
|
@ -189,6 +189,7 @@ public class JettyRunTask extends Task
|
|||
*
|
||||
* @throws BuildException if unable to build
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws BuildException
|
||||
{
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ public class JettyStopTask extends Task
|
|||
/**
|
||||
* @see org.apache.tools.ant.Task#execute()
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws BuildException
|
||||
{
|
||||
try
|
||||
|
|
|
@ -115,6 +115,7 @@ public class ServerProxyImpl implements ServerProxy
|
|||
this.awc = awc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filesChanged(List<String> changedFileNames)
|
||||
{
|
||||
boolean isScanned = false;
|
||||
|
@ -151,6 +152,7 @@ public class ServerProxyImpl implements ServerProxy
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addWebApplication(AntWebAppContext webApp)
|
||||
{
|
||||
webApplications.add(webApp);
|
||||
|
@ -242,6 +244,7 @@ public class ServerProxyImpl implements ServerProxy
|
|||
/**
|
||||
* @see org.eclipse.jetty.ant.utils.ServerProxy#start()
|
||||
*/
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
try
|
||||
|
@ -289,6 +292,7 @@ public class ServerProxyImpl implements ServerProxy
|
|||
/**
|
||||
* @see org.eclipse.jetty.ant.utils.ServerProxy#getProxiedObject()
|
||||
*/
|
||||
@Override
|
||||
public Object getProxiedObject()
|
||||
{
|
||||
return server;
|
||||
|
|
|
@ -265,6 +265,7 @@ public class AntBuild
|
|||
this.parser = connector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
String line;
|
||||
|
|
|
@ -172,6 +172,12 @@
|
|||
<version>10.0.0-SNAPSHOT</version>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-distribution</artifactId>
|
||||
<version>9.4.9-SNAPSHOT</version>
|
||||
<type>tar.gz</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||
<artifactId>fcgi-client</artifactId>
|
||||
|
@ -404,18 +410,6 @@
|
|||
<artifactId>jetty-xml</artifactId>
|
||||
<version>10.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-distribution</artifactId>
|
||||
<version>9.3.23-SNAPSHOT</version>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-distribution</artifactId>
|
||||
<version>9.3.23-SNAPSHOT</version>
|
||||
<type>tar.gz</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
|
|
@ -155,6 +155,7 @@ public class DuplexConnectionPool extends AbstractConnectionPool implements Swee
|
|||
return active(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean release(Connection connection)
|
||||
{
|
||||
boolean closed = isClosed();
|
||||
|
@ -184,6 +185,7 @@ public class DuplexConnectionPool extends AbstractConnectionPool implements Swee
|
|||
return idleConnections.offerFirst(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Connection connection)
|
||||
{
|
||||
return remove(connection, false);
|
||||
|
@ -212,6 +214,7 @@ public class DuplexConnectionPool extends AbstractConnectionPool implements Swee
|
|||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
super.close();
|
||||
|
|
|
@ -979,6 +979,8 @@ public class HttpClient extends ContainerLifeCycle
|
|||
/**
|
||||
* Gets the http compliance mode for parsing http responses.
|
||||
* The default http compliance level is {@link HttpCompliance#RFC7230} which is the latest HTTP/1.1 specification
|
||||
*
|
||||
* @return the HttpCompliance instance
|
||||
*/
|
||||
public HttpCompliance getHttpCompliance()
|
||||
{
|
||||
|
|
|
@ -361,6 +361,7 @@ public abstract class HttpDestination extends ContainerLifeCycle implements Dest
|
|||
|
||||
protected abstract SendFailure send(Connection connection, HttpExchange exchange);
|
||||
|
||||
@Override
|
||||
public void newConnection(Promise<Connection> promise)
|
||||
{
|
||||
createConnection(promise);
|
||||
|
@ -376,6 +377,7 @@ public abstract class HttpDestination extends ContainerLifeCycle implements Dest
|
|||
return exchanges.remove(exchange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
abort(new AsynchronousCloseException());
|
||||
|
|
|
@ -49,6 +49,7 @@ public class HttpResponse implements Response
|
|||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpVersion getVersion()
|
||||
{
|
||||
return version;
|
||||
|
@ -72,6 +73,7 @@ public class HttpResponse implements Response
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReason()
|
||||
{
|
||||
return reason;
|
||||
|
|
|
@ -263,6 +263,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
process();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abort(Throwable x)
|
||||
{
|
||||
failAndClose(x);
|
||||
|
|
|
@ -207,6 +207,7 @@ public class DeferredContentProvider implements AsyncContentProvider, Callback,
|
|||
* No more content will be added to this content provider
|
||||
* and notifies the listener that no more content is available.
|
||||
*/
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
if (closed.compareAndSet(false, true))
|
||||
|
|
|
@ -38,7 +38,7 @@ import org.junit.runners.Parameterized;
|
|||
@RunWith(Parameterized.class)
|
||||
public abstract class AbstractHttpClientServerTest
|
||||
{
|
||||
@Parameterized.Parameters
|
||||
@Parameterized.Parameters(name = "ssl={0}")
|
||||
public static Collection<SslContextFactory[]> parameters()
|
||||
{
|
||||
return Arrays.asList(new SslContextFactory[]{null}, new SslContextFactory[]{new SslContextFactory()});
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.eclipse.jetty.server.Handler;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.After;
|
||||
|
@ -58,7 +59,7 @@ public class HttpClientTLSTest
|
|||
|
||||
private void startServer(SslContextFactory sslContextFactory, Handler handler) throws Exception
|
||||
{
|
||||
QueuedThreadPool serverThreads = new QueuedThreadPool();
|
||||
ExecutorThreadPool serverThreads = new ExecutorThreadPool();
|
||||
serverThreads.setName("server");
|
||||
server = new Server(serverThreads);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -45,23 +46,39 @@ public class RoundRobinConnectionPoolTest extends AbstractHttpClientServerTest
|
|||
@Test
|
||||
public void testRoundRobin() throws Exception
|
||||
{
|
||||
AtomicBoolean record = new AtomicBoolean();
|
||||
List<Integer> remotePorts = new ArrayList<>();
|
||||
start(new EmptyServerHandler()
|
||||
{
|
||||
@Override
|
||||
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
remotePorts.add(request.getRemotePort());
|
||||
if (record.get())
|
||||
remotePorts.add(request.getRemotePort());
|
||||
}
|
||||
});
|
||||
|
||||
int maxConnections = 3;
|
||||
client.getTransport().setConnectionPoolFactory(destination -> new RoundRobinConnectionPool(destination, maxConnections, destination));
|
||||
|
||||
// Prime the connections, so that they are all opened
|
||||
// before we actually test the round robin behavior.
|
||||
String host = "localhost";
|
||||
int port = connector.getLocalPort();
|
||||
for (int i = 0; i < maxConnections; ++i)
|
||||
{
|
||||
ContentResponse response = client.newRequest(host, port)
|
||||
.scheme(scheme)
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
}
|
||||
|
||||
record.set(true);
|
||||
int requests = 2 * maxConnections - 1;
|
||||
for (int i = 0; i < requests; ++i)
|
||||
{
|
||||
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
ContentResponse response = client.newRequest(host, port)
|
||||
.scheme(scheme)
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
|
@ -74,7 +91,7 @@ public class RoundRobinConnectionPoolTest extends AbstractHttpClientServerTest
|
|||
int base = i % maxConnections;
|
||||
int expected = remotePorts.get(base);
|
||||
int candidate = remotePorts.get(i);
|
||||
Assert.assertThat(expected, Matchers.equalTo(candidate));
|
||||
Assert.assertThat(client.dump() + System.lineSeparator() + remotePorts.toString(), expected, Matchers.equalTo(candidate));
|
||||
if (i > 0)
|
||||
Assert.assertThat(remotePorts.get(i - 1), Matchers.not(Matchers.equalTo(candidate)));
|
||||
}
|
||||
|
|
|
@ -56,38 +56,43 @@ public class HttpDestinationOverHTTPTest extends AbstractHttpClientServerTest
|
|||
@Test
|
||||
public void test_FirstAcquire_WithEmptyQueue() throws Exception
|
||||
{
|
||||
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort()));
|
||||
destination.start();
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
Connection connection = connectionPool.acquire();
|
||||
if (connection == null)
|
||||
try(HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort())))
|
||||
{
|
||||
// There are no queued requests, so the newly created connection will be idle
|
||||
connection = timedPoll(connectionPool.getIdleConnections(), 5, TimeUnit.SECONDS);
|
||||
destination.start();
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
Connection connection = connectionPool.acquire();
|
||||
if (connection == null)
|
||||
{
|
||||
// There are no queued requests, so the newly created connection will be idle
|
||||
connection = timedPoll(connectionPool.getIdleConnections(), 5, TimeUnit.SECONDS);
|
||||
}
|
||||
Assert.assertNotNull(connection);
|
||||
}
|
||||
Assert.assertNotNull(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_SecondAcquire_AfterFirstAcquire_WithEmptyQueue_ReturnsSameConnection() throws Exception
|
||||
{
|
||||
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort()));
|
||||
destination.start();
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
Connection connection1 = connectionPool.acquire();
|
||||
if (connection1 == null)
|
||||
try(HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort())))
|
||||
{
|
||||
// There are no queued requests, so the newly created connection will be idle
|
||||
long start = System.nanoTime();
|
||||
while (connection1 == null && TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) < 5)
|
||||
{
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
connection1 = connectionPool.getIdleConnections().peek();
|
||||
}
|
||||
Assert.assertNotNull(connection1);
|
||||
destination.start();
|
||||
|
||||
Connection connection2 = connectionPool.acquire();
|
||||
Assert.assertSame(connection1, connection2);
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
Connection connection1 = connectionPool.acquire();
|
||||
if (connection1 == null)
|
||||
{
|
||||
// There are no queued requests, so the newly created connection will be idle
|
||||
long start = System.nanoTime();
|
||||
while (connection1 == null && TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) < 5)
|
||||
{
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
connection1 = connectionPool.getIdleConnections().peek();
|
||||
}
|
||||
Assert.assertNotNull(connection1);
|
||||
|
||||
Connection connection2 = connectionPool.acquire();
|
||||
Assert.assertSame(connection1, connection2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,55 +125,67 @@ public class HttpDestinationOverHTTPTest extends AbstractHttpClientServerTest
|
|||
};
|
||||
}
|
||||
};
|
||||
destination.start();
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
Connection connection1 = connectionPool.acquire();
|
||||
|
||||
try
|
||||
{
|
||||
destination.start();
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
Connection connection1 = connectionPool.acquire();
|
||||
|
||||
// Make sure we entered idleCreated().
|
||||
Assert.assertTrue(idleLatch.await(5, TimeUnit.SECONDS));
|
||||
// Make sure we entered idleCreated().
|
||||
Assert.assertTrue(idleLatch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
// There are no available existing connections, so acquire()
|
||||
// returns null because we delayed idleCreated() above
|
||||
Assert.assertNull(connection1);
|
||||
// There are no available existing connections, so acquire()
|
||||
// returns null because we delayed idleCreated() above
|
||||
Assert.assertNull(connection1);
|
||||
|
||||
// Second attempt also returns null because we delayed idleCreated() above.
|
||||
Connection connection2 = connectionPool.acquire();
|
||||
Assert.assertNull(connection2);
|
||||
// Second attempt also returns null because we delayed idleCreated() above.
|
||||
Connection connection2 = connectionPool.acquire();
|
||||
Assert.assertNull(connection2);
|
||||
|
||||
latch.countDown();
|
||||
latch.countDown();
|
||||
|
||||
// There must be 2 idle connections.
|
||||
Queue<Connection> idleConnections = connectionPool.getIdleConnections();
|
||||
Connection connection = timedPoll(idleConnections, 5, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(connection);
|
||||
connection = timedPoll(idleConnections, 5, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(connection);
|
||||
// There must be 2 idle connections.
|
||||
Queue<Connection> idleConnections = connectionPool.getIdleConnections();
|
||||
Connection connection = timedPoll(idleConnections, 5, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(connection);
|
||||
connection = timedPoll(idleConnections, 5, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(connection);
|
||||
}
|
||||
finally
|
||||
{
|
||||
destination.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Acquire_Process_Release_Acquire_ReturnsSameConnection() throws Exception
|
||||
{
|
||||
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort()));
|
||||
destination.start();
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
HttpConnectionOverHTTP connection1 = (HttpConnectionOverHTTP)connectionPool.acquire();
|
||||
|
||||
long start = System.nanoTime();
|
||||
while (connection1 == null && TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) < 5)
|
||||
try(HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort())))
|
||||
{
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
connection1 = (HttpConnectionOverHTTP)connectionPool.getIdleConnections().peek();
|
||||
destination.start();
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
HttpConnectionOverHTTP connection1 = (HttpConnectionOverHTTP)connectionPool.acquire();
|
||||
|
||||
Assert.assertNull(connection1);
|
||||
|
||||
long start = System.nanoTime();
|
||||
while (connection1 == null && TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) < 5)
|
||||
{
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
connection1 = (HttpConnectionOverHTTP)connectionPool.getIdleConnections().peek();
|
||||
}
|
||||
Assert.assertNotNull(connection1);
|
||||
|
||||
// Acquire the connection to make it active
|
||||
Assert.assertSame("From idle", connection1, connectionPool.acquire());
|
||||
|
||||
destination.process(connection1);
|
||||
destination.release(connection1);
|
||||
|
||||
Connection connection2 = connectionPool.acquire();
|
||||
Assert.assertSame("After release", connection1, connection2);
|
||||
}
|
||||
Assert.assertNotNull(connection1);
|
||||
|
||||
// Acquire the connection to make it active
|
||||
Assert.assertSame(connection1, connectionPool.acquire());
|
||||
|
||||
destination.process(connection1);
|
||||
destination.release(connection1);
|
||||
|
||||
Connection connection2 = connectionPool.acquire();
|
||||
Assert.assertSame(connection1, connection2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -177,25 +194,27 @@ public class HttpDestinationOverHTTPTest extends AbstractHttpClientServerTest
|
|||
long idleTimeout = 1000;
|
||||
client.setIdleTimeout(idleTimeout);
|
||||
|
||||
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort()));
|
||||
destination.start();
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
Connection connection1 = connectionPool.acquire();
|
||||
if (connection1 == null)
|
||||
try(HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort())))
|
||||
{
|
||||
// There are no queued requests, so the newly created connection will be idle
|
||||
long start = System.nanoTime();
|
||||
while (connection1 == null && TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) < 5)
|
||||
destination.start();
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
Connection connection1 = connectionPool.acquire();
|
||||
if (connection1 == null)
|
||||
{
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
connection1 = connectionPool.getIdleConnections().peek();
|
||||
// There are no queued requests, so the newly created connection will be idle
|
||||
long start = System.nanoTime();
|
||||
while (connection1 == null && TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) < 5)
|
||||
{
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
connection1 = connectionPool.getIdleConnections().peek();
|
||||
}
|
||||
Assert.assertNotNull(connection1);
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(2 * idleTimeout);
|
||||
|
||||
connection1 = connectionPool.getIdleConnections().poll();
|
||||
Assert.assertNull(connection1);
|
||||
}
|
||||
Assert.assertNotNull(connection1);
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(2 * idleTimeout);
|
||||
|
||||
connection1 = connectionPool.getIdleConnections().poll();
|
||||
Assert.assertNull(connection1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,7 @@ public abstract class SslBytesTest
|
|||
serverSocket.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Ref refid="DeploymentManager">
|
||||
<Call name="addLifeCycleBinding">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.deploy.bindings.GlobalWebappConfigBinding">
|
||||
<Set name="jettyXml">
|
||||
<Property>
|
||||
<Name>jetty.deploy.webappCommonConfig</Name>
|
||||
<Default>
|
||||
<Property name="jetty.base"/>/etc/webapp-common.xml
|
||||
</Default>
|
||||
</Property>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Ref>
|
||||
</Configure>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
|
||||
<!-- ===================================== -->
|
||||
<!-- Add common setup for all webapps here -->
|
||||
<!-- ===================================== -->
|
||||
|
||||
</Configure>
|
|
@ -0,0 +1,17 @@
|
|||
[description]
|
||||
Enables Deployer to apply common configuration to all webapp deployments
|
||||
|
||||
[depend]
|
||||
deploy
|
||||
|
||||
[xml]
|
||||
etc/global-webapp-common.xml
|
||||
|
||||
[files]
|
||||
basehome:modules/global-webapp-common.d/global-webapp-common.xml|etc/global-webapp-common.xml
|
||||
basehome:modules/global-webapp-common.d/webapp-common.xml|etc/webapp-common.xml
|
||||
|
||||
[ini-template]
|
||||
|
||||
# Location of webapp xml config file to apply after context xml
|
||||
# jetty.deploy.webappCommonConfig=${jetty.base}/etc/webapp-common.xml
|
|
@ -74,6 +74,7 @@ public class AppLifeCycle extends Graph
|
|||
public static final String STARTED = "started";
|
||||
public static final String STOPPING = "stopping";
|
||||
public static final String UNDEPLOYING = "undeploying";
|
||||
public static final String FAILED = "failed";
|
||||
|
||||
|
||||
private Map<String, List<Binding>> lifecyclebindings = new HashMap<String, List<Binding>>();
|
||||
|
@ -97,6 +98,9 @@ public class AppLifeCycle extends Graph
|
|||
// deployed -> undeployed
|
||||
addEdge(DEPLOYED,UNDEPLOYING);
|
||||
addEdge(UNDEPLOYING,UNDEPLOYED);
|
||||
|
||||
// failed (unconnected)
|
||||
addNode(new Node(FAILED));
|
||||
}
|
||||
|
||||
public void addBinding(AppLifeCycle.Binding binding)
|
||||
|
|
|
@ -507,6 +507,18 @@ public class DeploymentManager extends ContainerLifeCycle
|
|||
catch (Throwable t)
|
||||
{
|
||||
LOG.warn("Unable to reach node goal: " + nodeName,t);
|
||||
// migrate to FAILED node
|
||||
Node failed = _lifecycle.getNodeByName(AppLifeCycle.FAILED);
|
||||
appentry.setLifeCycleNode(failed);
|
||||
try
|
||||
{
|
||||
_lifecycle.runBindings(failed, appentry.app, this);
|
||||
}
|
||||
catch (Throwable ignore)
|
||||
{
|
||||
// The runBindings failed for 'failed' node
|
||||
LOG.ignore(ignore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,11 +40,13 @@ public class DebugBinding implements AppLifeCycle.Binding
|
|||
_targets=targets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getBindingTargets()
|
||||
{
|
||||
return _targets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processBinding(Node node, App app) throws Exception
|
||||
{
|
||||
LOG.info("processBinding {} {}",node,app.getContextHandler());
|
||||
|
|
|
@ -45,6 +45,7 @@ public class DebugListenerBinding extends DebugBinding
|
|||
return _debugListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processBinding(Node node, App app) throws Exception
|
||||
{
|
||||
app.getContextHandler().addEventListener(_debugListener);
|
||||
|
|
|
@ -62,11 +62,13 @@ public class GlobalWebappConfigBinding implements AppLifeCycle.Binding
|
|||
this._jettyXml = jettyXml;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getBindingTargets()
|
||||
{
|
||||
return new String[] { "deploying" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processBinding(Node node, App app) throws Exception
|
||||
{
|
||||
ContextHandler handler = app.getContextHandler();
|
||||
|
|
|
@ -63,11 +63,13 @@ public class OrderedGroupBinding implements AppLifeCycle.Binding
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getBindingTargets()
|
||||
{
|
||||
return _bindingTargets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processBinding(Node node, App app) throws Exception
|
||||
{
|
||||
for ( AppLifeCycle.Binding binding : _orderedBindings )
|
||||
|
|
|
@ -25,12 +25,14 @@ import org.eclipse.jetty.server.handler.ContextHandler;
|
|||
|
||||
public class StandardDeployer implements AppLifeCycle.Binding
|
||||
{
|
||||
@Override
|
||||
public String[] getBindingTargets()
|
||||
{
|
||||
return new String[]
|
||||
{ "deploying" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processBinding(Node node, App app) throws Exception
|
||||
{
|
||||
ContextHandler handler = app.getContextHandler();
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.eclipse.jetty.deploy.App;
|
|||
import org.eclipse.jetty.deploy.AppLifeCycle;
|
||||
import org.eclipse.jetty.deploy.graph.Node;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
|
||||
public class StandardStarter implements AppLifeCycle.Binding
|
||||
{
|
||||
|
@ -35,12 +36,17 @@ public class StandardStarter implements AppLifeCycle.Binding
|
|||
@Override
|
||||
public void processBinding(Node node, App app) throws Exception
|
||||
{
|
||||
ContextHandlerCollection contexts = app.getDeploymentManager().getContexts();
|
||||
|
||||
ContextHandler handler = app.getContextHandler();
|
||||
|
||||
// start the handler
|
||||
handler.start();
|
||||
|
||||
// After starting let the context manage state
|
||||
app.getDeploymentManager().getContexts().manage(handler);
|
||||
|
||||
if (contexts.isStarted() && handler.isStopped())
|
||||
{
|
||||
// start the handler manually
|
||||
handler.start();
|
||||
|
||||
// After starting let the context manage state
|
||||
contexts.manage(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ public class GraphOutputDot
|
|||
{
|
||||
private Collator collator = Collator.getInstance();
|
||||
|
||||
@Override
|
||||
public int compare(Node o1, Node o2)
|
||||
{
|
||||
if (o1.getName().equals(TOPNODE))
|
||||
|
|
|
@ -41,12 +41,14 @@ public class AppLifeCyclePathCollector implements AppLifeCycle.Binding
|
|||
return actualOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getBindingTargets()
|
||||
{
|
||||
return new String[]
|
||||
{ "*" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processBinding(Node node, App app) throws Exception
|
||||
{
|
||||
actualOrder.add(node);
|
||||
|
|
|
@ -33,6 +33,7 @@ public class MockAppProvider extends AbstractLifeCycle implements AppProvider
|
|||
private DeploymentManager deployMan;
|
||||
private File webappsDir;
|
||||
|
||||
@Override
|
||||
public void setDeploymentManager(DeploymentManager deploymentManager)
|
||||
{
|
||||
this.deployMan = deploymentManager;
|
||||
|
@ -50,6 +51,7 @@ public class MockAppProvider extends AbstractLifeCycle implements AppProvider
|
|||
this.deployMan.addApp(app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextHandler createContextHandler(App app) throws Exception
|
||||
{
|
||||
WebAppContext context = new WebAppContext();
|
||||
|
|
|
@ -80,6 +80,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
_providers++;
|
||||
((ScanningAppProvider)provider).addScannerListener(new Scanner.ScanListener()
|
||||
{
|
||||
@Override
|
||||
public void scan()
|
||||
{
|
||||
_scans.incrementAndGet();
|
||||
|
|
|
@ -23,48 +23,40 @@ Application Layer Protocol Negotiation (ALPN) is a TLS extension that allows cli
|
|||
|
||||
Any protocol can be negotiated by ALPN within a TLS connection; the protocols that are most commonly negotiated are HTTP/2 and HTTP/1.1.
|
||||
|
||||
Browsers only support HTTP/2 over TLS by negotiating the HTTP/2 protocol via ALPN.
|
||||
You need to configure the server to support TLS and ALPN if you want browsers to use
|
||||
the HTTP/2 protocol, otherwise they will default to HTTP/1.1.
|
||||
|
||||
In the Jetty project, ALPN is _used_ in two artifacts: `jetty-alpn-client` and `jetty-alpn-server`, respectively for the client and for the server.
|
||||
|
||||
When using Jetty as a standalone server via the Jetty distribution, the `jetty-alpn-server` artifact is automatically included in the server classpath by the Jetty module system.
|
||||
|
||||
When using Jetty embedded, the `jetty-alpn-client` and `jetty-alpn-server` artifacts must be included in the classpath, respectively for client and server use cases.
|
||||
|
||||
ALPN may be _provided_ to these two artifacts with the following three options:
|
||||
The ALPN implementation is _provided_ to these two artifacts with the following three options:
|
||||
|
||||
* For JDK 9 or later, a provider based on the ALPN APIs present in the JDK
|
||||
* For JDK 8 or later, a provider based on the link:#conscrypt[Conscrypt security provider]
|
||||
* For JDK 8 only, a provider based on modified OpenJDK classes
|
||||
** Only works with JDK 8, pure Java implementation
|
||||
** Requires the `-Xbootclasspath/p` option on command line
|
||||
* For JDK 8 or later, a provider based on the link:#conscrypt[Conscrypt security provider]
|
||||
** Works with JDK 8 or later and provides improved performance
|
||||
** Binds to the OpenSSL native library shipped by Conscrypt and is therefore only available on the platforms supported by Conscrypt
|
||||
* For JDK 9 or later, a provider based on the ALPN APIs present in the JDK
|
||||
** Works with JDK 9 or later, pure Java implementation
|
||||
** Lower performance than Conscrypt
|
||||
|
||||
The latter, although hosted under the umbrella of the Jetty project, is independent of Jetty (the Servlet Container); you can use it in any other Java network server.
|
||||
The first, although hosted under the umbrella of the Jetty project, is independent of Jetty (the Servlet Container); you can use it in any other Java network server.
|
||||
|
||||
Each provider above provides a _service_ implementation; Jetty uses the `ServiceLoader` mechanism to load these service implementations.
|
||||
The absence of implementations is an error at startup (see also the link:#alpn-troubleshooting[troubleshooting section]).
|
||||
Each provider above provides an ALPN _service_ implementation; Jetty uses the `ServiceLoader` mechanism to load these service implementations.
|
||||
At least one valid provider must be present in the server classpath.
|
||||
For example, using JDK 8 with the JDK 9 ALPN provider is an _invalid_ combination.
|
||||
The absence of valid implementations is an error at startup (see also the link:#alpn-troubleshooting[troubleshooting section]).
|
||||
|
||||
There may be multiple ALPN service providers in the server classpath.
|
||||
When a new connection is created, an `SSLEngine` instance is associated to it; each `SSLEngine` is passed all service implementations, until one accepts it.
|
||||
|
||||
It is therefore possible to have multiple providers active at the same time, for example the JDK 9 provider and the Conscrypt provider, and at runtime the correct one will be chosen by the Jetty runtime.
|
||||
|
||||
[[alpn-jdk9]]
|
||||
==== ALPN and JDK 9
|
||||
|
||||
When using JDK 9 or later and Jetty as a standalone server via the Jetty distribution, ALPN support is automatically enabled when the `http2` module is enabled.
|
||||
This enables transitively the `alpn-9` module which puts the `jetty-alpn-java-server` artifact in the server classpath, providing the ALPN JDK 9 service implementation.
|
||||
|
||||
When using JDK 9 or later and Jetty embedded, the ALPN service implementation is provided by the `jetty-alpn-java-client` and `jetty-alpn-java-server` artifacts, respectively for client usage and server usage, and must be added to the classpath.
|
||||
|
||||
[[alpn-conscrypt]]
|
||||
==== ALPN and Conscrypt
|
||||
|
||||
When using JDK 8 or later, you can use the https://conscrypt.org/[Conscrypt] security provider to provide the ALPN service implementation.
|
||||
|
||||
Conscrypt binds natively to BoringSSL (a fork of OpenSSL by Google), so ALPN will be supported via the support provided by BoringSSL (bundled together with Conscrypt).
|
||||
|
||||
When using Jetty as a standalone server via the Jetty distribution, ALPN is enabled by enabling the `conscrypt` module.
|
||||
|
||||
When using Jetty embedded, ALPN is enabled by the `jetty-alpn-conscrypt-client` and `jetty-alpn-conscrypt-server` artifacts, respectively for client usage and server usage.
|
||||
In addition, you also need the Conscrypt artifacts, typically the `org.conscrypt:conscrypt-openjdk-uber` artifact.
|
||||
All these artifacts must be added to the classpath.
|
||||
|
||||
[[alpn-openjdk8]]
|
||||
==== ALPN and OpenJDK 8
|
||||
|
||||
|
@ -94,6 +86,27 @@ Where `path_to_alpn_boot_jar` is the path on the file system for the `alpn-boot`
|
|||
|
||||
Be certain to get the link:#alpn-versions[ALPN boot artifact version that matches the version of your JRE].
|
||||
|
||||
[[alpn-conscrypt]]
|
||||
==== ALPN and Conscrypt
|
||||
|
||||
When using JDK 8 or later, you can use the https://conscrypt.org/[Conscrypt] security provider to provide the ALPN service implementation.
|
||||
|
||||
Conscrypt binds natively to BoringSSL (a fork of OpenSSL by Google), so ALPN will be supported via the support provided by BoringSSL (bundled together with Conscrypt).
|
||||
|
||||
When using Jetty as a standalone server via the Jetty distribution, ALPN is enabled by enabling the `conscrypt` module.
|
||||
|
||||
When using Jetty embedded, ALPN is enabled by the `jetty-alpn-conscrypt-client` and `jetty-alpn-conscrypt-server` artifacts, respectively for client usage and server usage.
|
||||
In addition, you also need the Conscrypt artifacts, typically the `org.conscrypt:conscrypt-openjdk-uber` artifact.
|
||||
All these artifacts must be added to the classpath.
|
||||
|
||||
[[alpn-jdk9]]
|
||||
==== ALPN and JDK 9
|
||||
|
||||
When using JDK 9 or later and Jetty as a standalone server via the Jetty distribution, ALPN support is automatically enabled when the `http2` module is enabled.
|
||||
This enables transitively the `alpn-9` module which puts the `jetty-alpn-java-server` artifact in the server classpath, providing the ALPN JDK 9 service implementation.
|
||||
|
||||
When using JDK 9 or later and Jetty embedded, the ALPN service implementation is provided by the `jetty-alpn-java-client` and `jetty-alpn-java-server` artifacts, respectively for client usage and server usage, and must be added to the classpath.
|
||||
|
||||
[[alpn-osgi]]
|
||||
===== Starting in OSGi
|
||||
|
||||
|
|
|
@ -19,12 +19,15 @@
|
|||
[[alpn-chapter]]
|
||||
== Application Layer Protocol Negotiation (ALPN)
|
||||
|
||||
The development of new web protocols such as HTTP/2 raised the need of protocol negotiation within a Transport Layer Security (TLS) handshake.
|
||||
A protocol negotiation called https://tools.ietf.org/html/rfc7301[ALPN] (Application Layer Protocol Negotiation) RFC7301 has been defined to accomplish this.
|
||||
The development of new web protocols such as HTTP/2 raised the need of protocol
|
||||
negotiation within a Transport Layer Security (TLS) handshake.
|
||||
A protocol negotiation called ALPN (Application Layer Protocol Negotiation -
|
||||
https://tools.ietf.org/html/rfc7301[RFC7301]) has been defined to accomplish this.
|
||||
|
||||
ALPN has now replaced the older (and now fully deprecated) NPN in the general Web of 2016.
|
||||
ALPN has now replaced the older (and now fully deprecated) NPN in the general Web
|
||||
as of 2016.
|
||||
|
||||
For those browsers that support HTTP/2, they all now support the ALPN negotiation layers for TLS.
|
||||
For those browsers that support HTTP/2, they all now support ALPN.
|
||||
Starting with Jetty 9.3.0, only ALPN is supported by Jetty.
|
||||
|
||||
include::alpn.adoc[]
|
||||
|
|
|
@ -23,7 +23,7 @@ Jetty itself has no temporary directories, but you can assign a directory for ea
|
|||
If you do not assign a specific temporary directory, Jetty will create one as needed when your web application starts.
|
||||
Whether you set the location of the temporary directory - or you let Jetty create one for you - you also have a choice to either keep or delete the temporary directory when the web application stops.
|
||||
|
||||
==== The default temp directory
|
||||
==== The Default Temp Directory
|
||||
|
||||
By default, Jetty will create a temporary directory for each web application. The name of the directory will be of the form:
|
||||
|
||||
|
@ -75,12 +75,13 @@ context.setWar("foo.war");
|
|||
context.setAttribute("org.eclipse.jetty.webapp.basetempdir", "/tmp/foo");
|
||||
----
|
||||
|
||||
==== Setting a specific temp directory
|
||||
==== Setting a Specific Temp Directory
|
||||
|
||||
There are several ways to use a particular directory as the temporary directory:
|
||||
|
||||
===== Call WebAppContext.setTempDirectory(String dir)
|
||||
As before this can be accomplished with an xml file or directly in code. Here's an example of setting the temp directory in xml:
|
||||
As before this can be accomplished with an XML file or directly in code.
|
||||
Here is an example of setting the temp directory in XML:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
@ -93,7 +94,7 @@ As before this can be accomplished with an xml file or directly in code. Here's
|
|||
</Configure>
|
||||
----
|
||||
|
||||
Here's an example of doing it with java code:
|
||||
And here is an example of doing it with java code:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
|
@ -103,8 +104,9 @@ context.setWar("foo.war");
|
|||
context.setTempDirectory(new File("/some/dir/foo"));
|
||||
----
|
||||
|
||||
===== Set the javax.servlet.context.tempdir context attribute
|
||||
You should set this context attribute with the name of directory you want to use as the temp directory. Again, you can do this in xml:
|
||||
===== Setting the javax.servlet.context.tempdir Context Attribute
|
||||
You should set this context attribute with the name of directory you want to use as the temp directory.
|
||||
Again, you can do this in XML:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
@ -139,13 +141,61 @@ Be wary of setting an explicit temp directory if you are likely to change the ja
|
|||
There is a JVM bug concerning link:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4774421[caching of jar contents.]
|
||||
____
|
||||
|
||||
==== The "work" directory
|
||||
===== Setting the Temp Directory on the Command Line
|
||||
You can set the location of the temp directory on the command line when Jetty starts up in two ways.
|
||||
First is the most straightforward, simply add it to your command line when starting Jetty.
|
||||
|
||||
Mostly for backward compatibility, from Jetty 9.1.1 onwards, it is possible to create a directory named "work" in the `$\{jetty.base}` directory.
|
||||
[source, screen, subs="{sub-order}"]
|
||||
----
|
||||
java -jar ../start.jar -Djava.io.tmpdir=/path/to/desired/directory
|
||||
----
|
||||
|
||||
Alternately, this can be defined in a link:#startup-modules[module.]
|
||||
The `jvm` module packaged with Jetty is set up to add additional JVM options.
|
||||
After enabling the module (using the `--add-to-start=jvm` command), edit the `jvm.ini` file and add the location to the temporary directory.
|
||||
You will also need verify the line including the `--exec` command is not commented out, as this is required for Jetty to start a new, forked JVM.
|
||||
Below is an example of the standard `jvm.ini` file altered to include a reference to a temp directory.
|
||||
|
||||
[source, screen, subs="{sub-order}"]
|
||||
....
|
||||
# ---------------------------------------
|
||||
# Module: jvm
|
||||
# A noop module that creates an ini template useful for
|
||||
# setting JVM arguments (eg -Xmx )
|
||||
# ---------------------------------------
|
||||
--module=jvm
|
||||
|
||||
## JVM Configuration
|
||||
## If JVM args are include in an ini file then --exec is needed
|
||||
## to start a new JVM from start.jar with the extra args.
|
||||
##
|
||||
## If you wish to avoid an extra JVM running, place JVM args
|
||||
## on the normal command line and do not use --exec
|
||||
--exec
|
||||
# -Xmx2000m
|
||||
# -Xmn512m
|
||||
# -XX:+UseConcMarkSweepGC
|
||||
# -XX:ParallelCMSThreads=2
|
||||
# -XX:+CMSClassUnloadingEnabled
|
||||
# -XX:+UseCMSCompactAtFullCollection
|
||||
# -XX:CMSInitiatingOccupancyFraction=80
|
||||
# -internal:gc
|
||||
# -XX:+PrintGCDateStamps
|
||||
# -XX:+PrintGCTimeStamps
|
||||
# -XX:+PrintGCDetails
|
||||
# -XX:+PrintTenuringDistribution
|
||||
# -XX:+PrintCommandLineFlags
|
||||
# -XX:+DisableExplicitGC
|
||||
-Djava.io.tmpdir=/path/to/desired/directory
|
||||
....
|
||||
|
||||
==== The "work" Directory
|
||||
|
||||
It is possible to create a directory named `work` in the `$\{jetty.base}` directory.
|
||||
If such a directory is found, it is assumed you want to use it as the parent directory for all of the temporary directories of the webapps in `$\{jetty.base}`.
|
||||
Moreover, as has historically been the case, these temp directories inside the work directory are not cleaned up when Jetty exits (or more correctly speaking, the `temp` directory corresponding to a context is not cleaned up when that context stops).
|
||||
|
||||
When a work directory is used, the algorithm for generating the name of the context-specific temp directories omits the random digit string.
|
||||
When a `work` directory is used, the algorithm for generating the name of the context-specific temp directories omits the random digit string.
|
||||
This ensures the name of the directory remains consistent across context restarts.
|
||||
|
||||
==== Persisting the temp directory
|
||||
|
|
|
@ -26,7 +26,7 @@ While many people continue to use older versions of Jetty, we generally recommen
|
|||
_____
|
||||
[IMPORTANT]
|
||||
It is important that only stable releases are used in production environments.
|
||||
Versions that have been deprecated or are released as Milestones (M) or Release Candidates (RC) are not suitable for production as they may contain security flaws or incomplete/non-functioning feature sets.
|
||||
Versions that have been deprecated or are released as Milestones (M) or Release Candidates (RC) are not suitable for production as they may contain security flaws or incomplete/non-functioning feature sets.
|
||||
_____
|
||||
|
||||
.Jetty Versions
|
||||
|
@ -35,7 +35,7 @@ _____
|
|||
|Version |Year |Home |JVM |Protocols |Servlet |JSP |Status
|
||||
|9.4 |2016- |Eclipse |1.8 |HTTP/1.1 (RFC 7230), HTTP/2 (RFC 7540), WebSocket (RFC 6455, JSR 356), FastCGI |3.1 |2.3 |Stable
|
||||
|9.3 |2015- |Eclipse |1.8 |HTTP/1.1 (RFC 7230), HTTP/2 (RFC 7540), WebSocket (RFC 6455, JSR 356), FastCGI |3.1 |2.3 |Stable
|
||||
|9.2 |2014- |Eclipse |1.7 |HTTP/1.1 RFC2616, javax.websocket, SPDY v3 |3.1 |2.3 |Stable
|
||||
|9.2 |2014- |Eclipse |1.7 |HTTP/1.1 RFC2616, javax.websocket, SPDY v3 |3.1 |2.3 |Deprecated / *End of Life January 2018*
|
||||
|8 |2009-2014 |Eclipse/Codehaus |1.6 |HTTP/1.1 RFC2616, WebSocket RFC 6455, SPDY v3 |3.0 |2.2 |Deprecated / *End of Life November 2014*
|
||||
|7 |2008-2014 |Eclipse/Codehaus |1.5 |HTTP/1.1 RFC2616, WebSocket RFC 6455, SPDY v3 |2.5 |2.1 |Deprecated / *End of Life November 2014*
|
||||
|6 |2006-2010 |Codehaus |1.4-1.5 |HTTP/1.1 RFC2616 |2.5 |2.0 |Deprecated / *End of Life November 2010*
|
||||
|
|
|
@ -23,10 +23,10 @@ Class loading in a web container is slightly more complex than a normal Java app
|
|||
The normal configuration is that each web context (web application or WAR file) has its own classloader, which has the system classloader as its parent.
|
||||
Such a classloader hierarchy is normal in Java, however the servlet specification complicates the hierarchy because it requires the following:
|
||||
|
||||
* Classes contained within WEB-INF/lib or WEB-INF/classes have priority over classes on the parent classloader.
|
||||
This is the opposite of the normal behaviour of a Java 2 classloader.
|
||||
* Classes contained within `WEB-INF/lib` or `WEB-INF/classes` have priority over classes on the parent classloader.
|
||||
This is the opposite of the normal behavior of a Java 2 classloader.
|
||||
* System classes such as `java.lang.String` are excluded from the webapp priority, and you may not replace them with classes in `WEB-INF/lib` or `WEB-INF/` classes.
|
||||
Unfortunately the specification does not clearly state what classes are _System_ classes, and it is unclear if all javax classes should be treated as System classes.
|
||||
Unfortunately the specification does not clearly state what classes are _System_ classes, and it is unclear if all `javax` classes should be treated as System classes.
|
||||
* Server implementation classes like link:{JDURL}/org/eclipse/jetty/server/Server.html[Server] should be hidden from the web application and should not be available in any classloader.
|
||||
Unfortunately the specification does not state what classes are _Server_ classes, and it is unclear if common libraries like the Xerces parser should be treated as Implementation classes.
|
||||
|
||||
|
@ -38,6 +38,7 @@ Jetty provides configuration options to control the three webapp class loading i
|
|||
You can configure webapp classloading by several methods on the link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[WebAppContext].
|
||||
You can call these methods directly if you are working with the Jetty API, or you can inject methods from a context XML file if you are using the Context Provider (xref:using-context-provider[]).
|
||||
You CANNOT set these methods from a `jetty-web.xml` file, as it executes after the classloader configuration is set.
|
||||
As a note, `jetty-web.xml` uses the webapp classpath and not the classpath of the server.
|
||||
|
||||
[[controlling-webapp-classloader-priority]]
|
||||
===== Controlling Webapp Classloader Priority
|
||||
|
@ -152,7 +153,7 @@ You can do so directly to the API via a context XML file such as the following:
|
|||
----
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
...
|
||||
<Set name="extraClasspath>../my/classes,../my/jars/special.jar,../my/jars/other.jar</Set>
|
||||
<Set name="extraClasspath">../my/classes,../my/jars/special.jar,../my/jars/other.jar</Set>
|
||||
...
|
||||
----
|
||||
|
||||
|
@ -178,8 +179,8 @@ You can also accomplish this in a context xml file.
|
|||
[[starting-jetty-custom-classloader]]
|
||||
==== Starting Jetty with a Custom ClassLoader
|
||||
|
||||
If you start a Jetty server using a custom class loader–consider the Jetty classes not being available to the system class loader, only your custom class loader–you may run into class loading issues when the WebAppClassLoader kicks in.
|
||||
By default the WebAppClassLoader uses the system class loader as its parent, hence the problem. This is easy to fix, like so:
|
||||
If you start a Jetty server using a custom class loader–consider the Jetty classes not being available to the system class loader, only your custom class loader–you may run into class loading issues when the `WebAppClassLoader` kicks in.
|
||||
By default the `WebAppClassLoader` uses the system class loader as its parent, hence the problem. This is easy to fix, like so:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
|
|
|
@ -50,6 +50,3 @@ Users are always welcome to come join our IRC channels and talk with us, other u
|
|||
irc.freenode.org - #jetty::
|
||||
Our primary location, we recommend that if your looking to find folks on IRC you try here.
|
||||
We also have commit notifications coming to this channel on the bottom and top of the hour.
|
||||
irc.codehaus.org - #jetty::
|
||||
Our prior location before the move to the eclipse foundation.
|
||||
We are idle on here.
|
||||
|
|
|
@ -42,7 +42,7 @@ For a more in-depth look at the syntax, see xref:jetty-xml-syntax[].
|
|||
|
||||
____
|
||||
[CAUTION]
|
||||
Make sure you are applying the configuration to an instance of the proper class. `jetty-web.xml` configures an instance of WebAppContext; `jetty.xml` configures an instance of Server.
|
||||
Make sure you are applying the configuration to an instance of the proper class. `jetty-web.xml` configures an instance of `WebAppContext`; `jetty.xml` configures an instance of `Server`.
|
||||
____
|
||||
|
||||
[[using-jetty-web-xml]]
|
||||
|
@ -52,10 +52,15 @@ Place the `jetty-web.xml` into your web application's `WEB-INF` folder.
|
|||
When Jetty deploys a web application, it looks for a file called `WEB-INF/jetty-web.xml` or `WEB-INF/web-jetty.xml` within the web application (or WAR) and applies the configuration found there.
|
||||
Be aware that `jetty-web.xml` is called _after_ all other configuration has been applied to the web application.
|
||||
|
||||
[[jetty-web-xml-examples]]
|
||||
==== `jetty-web.xml` Examples
|
||||
____
|
||||
[IMPORTANT]
|
||||
It is important to note that `jetty-web.xml` files utilize the webapp classpath, not the classpath of the server.
|
||||
____
|
||||
|
||||
The distribution contains an example of `jetty-web.xml` inside the WEB-INF folder of the test webapp war (`$JETTY_HOME/webapps/test.war/WEB-INF/jetty-web.xml`).
|
||||
[[jetty-web-xml-examples]]
|
||||
==== jetty-web.xml Examples
|
||||
|
||||
The distribution contains an example of `jetty-web.xml` inside the WEB-INF folder of the `test` webapp WAR (`$JETTY_HOME/demo-base/webapps/test.war/WEB-INF/jetty-web.xml`).
|
||||
|
||||
[[additional-jetty-web-xml-resources]]
|
||||
==== Additional `jetty-web.xml` Resources
|
||||
|
|
|
@ -27,11 +27,11 @@ If you would like to report a security issue please follow these link:#security-
|
|||
[width="99%",cols="11%,19%,14%,9%,14%,14%,19%",options="header",]
|
||||
|=======================================================================
|
||||
|yyyy/mm/dd |ID |Exploitable |Severity |Affects |Fixed Version |Comment
|
||||
|2016/05/31 |CVE-2016-4800 |high |high |>= 9.3.0, < = 9.3.8 |9.3.9
|
||||
|http://www.ocert.org/advisories/ocert-2016-001.html[Alias vulnerability allowing access to protected resources within a webapp on Windows.]
|
||||
|2016/05/31 |http://www.ocert.org/advisories/ocert-2016-001.html[CVE-2016-4800] |high |high |>= 9.3.0, < = 9.3.8 |9.3.9
|
||||
|Alias vulnerability allowing access to protected resources within a webapp on Windows.
|
||||
|
||||
|2015/02/24 |CVE-2015-2080 |high |high |>=9.2.3 <9.2.9 |9.2.9
|
||||
|http://blog.gdssecurity.com/labs/2015/2/25/jetleak-vulnerability-remote-leakage-of-shared-buffers-in-je.html[JetLeak exposure of past buffers during HttpParser error]
|
||||
|2015/02/24 |http://blog.gdssecurity.com/labs/2015/2/25/jetleak-vulnerability-remote-leakage-of-shared-buffers-in-je.html[CVE-2015-2080] |high |high |>=9.2.3 <9.2.9 |9.2.9
|
||||
|JetLeak exposure of past buffers during HttpParser error
|
||||
|
||||
|2013/11/27 |http://en.securitylab.ru/lab/PT-2013-65[PT-2013-65] |medium
|
||||
|high |>=9.0.0 <9.0.5 |9.0.6
|
||||
|
@ -55,7 +55,7 @@ https://bugs.eclipse.org/bugs/show_bug.cgi?id=367638[Jetty-367638]
|
|||
around by turning off SSL renegotiation in Jetty. If using JVM > 1.6u19
|
||||
setAllowRenegotiate(true) may be called on connectors.
|
||||
|
||||
|2009/06/18 |http://jira.codehaus.org/browse/JETTY-1042[Jetty-1042] |low
|
||||
|2009/06/18 |Jetty-1042 |low
|
||||
|high |< = 6.1.18, < = 7.0.0.M4 |6.1.19, 7.0.0.Rc0 |Cookie leak between
|
||||
requests sharing a connection.
|
||||
|
||||
|
@ -63,7 +63,7 @@ requests sharing a connection.
|
|||
|high |< = 6.1.16, < = 7.0.0.M2 a|
|
||||
5.1.15, 6.1.18, 7.0.0.M2
|
||||
|
||||
http://jira.codehaus.org/browse/JETTY-1004[Jetty-1004]
|
||||
Jetty-1004
|
||||
|
||||
|View arbitrary disk content in some specific configurations.
|
||||
|
||||
|
@ -72,7 +72,7 @@ http://jira.codehaus.org/browse/JETTY-1004[Jetty-1004]
|
|||
|high |medium |6.1.rrc0-6.1.6 a|
|
||||
6.1.7
|
||||
|
||||
http://jira.codehaus.org/browse/JETTY-386[CERT553235]
|
||||
CERT553235
|
||||
|
||||
|Static content visible in WEB-INF and past security constraints.
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ xmlns:date="http://exslt.org/dates-and-times"
|
|||
|
||||
</td>
|
||||
<td style="width: 50%">
|
||||
<script>
|
||||
<!-- <script>
|
||||
(function() {
|
||||
var cx = '005120552842603642412:peimxy9z8nu';
|
||||
var gcse = document.createElement('script');
|
||||
|
@ -140,7 +140,7 @@ xmlns:date="http://exslt.org/dates-and-times"
|
|||
s.parentNode.insertBefore(gcse, s);
|
||||
})();
|
||||
</script>
|
||||
<gcse:search></gcse:search>
|
||||
<gcse:search></gcse:search>-->
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -916,6 +916,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
|||
final AtomicReference<Exception> exception = new AtomicReference<Exception>();
|
||||
Runnable load = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run ()
|
||||
{
|
||||
try
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<name>Jetty :: Hazelcast Session Manager</name>
|
||||
|
||||
<properties>
|
||||
<hazelcast.version>3.8.2</hazelcast.version>
|
||||
<hazelcast.version>3.9.3</hazelcast.version>
|
||||
<bundle-symbolic-name>${project.groupId}.hazelcast</bundle-symbolic-name>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
<properties>
|
||||
<assembly-directory>${basedir}/target/jetty-home</assembly-directory>
|
||||
<source-assembly-directory>${basedir}/target/jetty-home-sources</source-assembly-directory>
|
||||
<jetty-setuid-version>1.0.3</jetty-setuid-version>
|
||||
</properties>
|
||||
|
||||
|
@ -150,6 +151,25 @@
|
|||
<outputDirectory>${assembly-directory}/lib</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-lib-src-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
|
||||
<excludeGroupIds>
|
||||
org.eclipse.jetty.orbit,org.eclipse.jetty.http2,org.eclipse.jetty.websocket,org.eclipse.jetty.fcgi,org.eclipse.jetty.toolchain,org.apache.taglibs
|
||||
</excludeGroupIds>
|
||||
<excludeArtifactIds>
|
||||
jetty-all,apache-jsp,apache-jstl,jetty-start,jetty-spring
|
||||
</excludeArtifactIds>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<classifier>sources</classifier>
|
||||
<outputDirectory>${source-assembly-directory}/lib</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-lib-websocket-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
|
@ -163,6 +183,20 @@
|
|||
<outputDirectory>${assembly-directory}/lib/websocket</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-lib-websocket-src-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>javax.websocket,org.eclipse.jetty.websocket</includeGroupIds>
|
||||
<excludeArtifactIds>javax.websocket-client-api</excludeArtifactIds>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<classifier>sources</classifier>
|
||||
<outputDirectory>${source-assembly-directory}/lib/websocket</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-lib-http2-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
|
@ -176,6 +210,20 @@
|
|||
<outputDirectory>${assembly-directory}/lib/http2</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-lib-http2-src-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>org.eclipse.jetty.http2</includeGroupIds>
|
||||
<includeArtifactIds>http2-hpack,http2-common,http2-server</includeArtifactIds>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<classifier>sources</classifier>
|
||||
<outputDirectory>${source-assembly-directory}/lib/http2</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-lib-fcgi-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
|
@ -188,6 +236,19 @@
|
|||
<outputDirectory>${assembly-directory}/lib/fcgi</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-lib-fcgi-src-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>org.eclipse.jetty.fcgi</includeGroupIds>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<classifier>sources</classifier>
|
||||
<outputDirectory>${source-assembly-directory}/lib/fcgi</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-lib-spring-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
|
@ -201,6 +262,20 @@
|
|||
<outputDirectory>${assembly-directory}/lib/spring</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-lib-spring-src-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
|
||||
<includeArtifactIds>jetty-spring</includeArtifactIds>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<classifier>sources</classifier>
|
||||
<outputDirectory>${source-assembly-directory}/lib/spring</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-servlet-api-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
|
@ -241,6 +316,20 @@
|
|||
<outputDirectory>${assembly-directory}/lib/annotations</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-annotations-src-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>javax.annotation,org.eclipse.jetty.orbit,org.ow2.asm</includeGroupIds>
|
||||
<includeArtifactIds>javax.annotation-api,asm,asm-commons</includeArtifactIds>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<classifier>sources</classifier>
|
||||
<outputDirectory>${source-assembly-directory}/lib/annotations</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-apache-jsp-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
|
@ -257,6 +346,23 @@
|
|||
<outputDirectory>${assembly-directory}/lib/apache-jsp</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-apache-jsp-src-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>
|
||||
org.eclipse.jetty,org.eclipse.jetty.toolchain,org.mortbay.jasper,org.eclipse.jdt
|
||||
</includeGroupIds>
|
||||
<includeArtifactIds>apache-jsp,apache-el,ecj</includeArtifactIds>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<classifier>sources</classifier>
|
||||
<prependGroupId>true</prependGroupId>
|
||||
<outputDirectory>${source-assembly-directory}/lib/apache-jsp</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-apache-jstl-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
|
@ -271,6 +377,21 @@
|
|||
<outputDirectory>${assembly-directory}/lib/apache-jstl</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-apache-jstl-src-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludeGroupIds>org.glassfish.web</excludeGroupIds>
|
||||
<includeArtifactIds>taglibs-standard-spec,taglibs-standard-impl</includeArtifactIds>
|
||||
<prependGroupId>true</prependGroupId>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<classifier>sources</classifier>
|
||||
<outputDirectory>${source-assembly-directory}/lib/apache-jstl</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-jaspi-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
|
@ -284,6 +405,20 @@
|
|||
<outputDirectory>${assembly-directory}/lib/jaspi</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-jaspi-src-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>org.eclipse.jetty.orbit</includeGroupIds>
|
||||
<includeArtifactIds>javax.security.auth.message</includeArtifactIds>
|
||||
<includeTypes>jar</includeTypes>
|
||||
<classifier>sources</classifier>
|
||||
<outputDirectory>${source-assembly-directory}/lib/jaspi</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>unpack-config-deps</id>
|
||||
<phase>generate-resources</phase>
|
||||
|
@ -322,18 +457,34 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/jetty-assembly.xml</descriptor>
|
||||
</descriptors>
|
||||
<tarLongFileMode>posix</tarLongFileMode>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>binary</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/jetty-assembly.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>sources</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/jetty-source-assembly.xml</descriptor>
|
||||
</descriptors>
|
||||
<appendAssemblyId>true</appendAssemblyId>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<assembly>
|
||||
<id>assembly</id>
|
||||
<id>binary-assembly</id>
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
<format>zip</format>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<assembly>
|
||||
<id>sources</id>
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${source-assembly-directory}</directory>
|
||||
<outputDirectory></outputDirectory>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
<!--
|
||||
<excludes>
|
||||
<exclude>**/META-INF/**</exclude>
|
||||
<exclude>*-config.jar</exclude>
|
||||
</excludes>
|
||||
-->
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
|
@ -176,6 +176,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void setPrincipal(HttpPrincipal principal)
|
||||
{
|
||||
_delegate.setPrincipal(principal);
|
||||
|
|
|
@ -67,7 +67,7 @@ public class JettyHttpServerProvider extends HttpServerProvider
|
|||
|
||||
JettyHttpServer jettyHttpServer = new JettyHttpServer(server, shared);
|
||||
if (addr != null)
|
||||
jettyHttpServer.bind(addr, backlog);
|
||||
jettyHttpServer.bind(addr, backlog);
|
||||
return jettyHttpServer;
|
||||
}
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ public class JettyHttpsExchange extends HttpsExchange implements JettyExchange
|
|||
return _delegate.getPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrincipal(HttpPrincipal principal)
|
||||
{
|
||||
_delegate.setPrincipal(principal);
|
||||
|
|
|
@ -74,6 +74,7 @@ public class TestSPIServer
|
|||
new HttpHandler()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException
|
||||
{
|
||||
Headers responseHeaders = exchange.getResponseHeaders();
|
||||
|
@ -163,6 +164,7 @@ public class TestSPIServer
|
|||
new HttpHandler()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException
|
||||
{
|
||||
Headers responseHeaders = exchange.getResponseHeaders();
|
||||
|
|
|
@ -947,11 +947,13 @@ public class HttpFields implements Iterable<HttpField>
|
|||
int _cursor; // index of next element to return
|
||||
int _last=-1;
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return _cursor != _size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpField next()
|
||||
{
|
||||
int i = _cursor;
|
||||
|
@ -961,6 +963,7 @@ public class HttpFields implements Iterable<HttpField>
|
|||
return _fields[_last=i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove()
|
||||
{
|
||||
if (_last<0)
|
||||
|
|
|
@ -719,6 +719,7 @@ public class HttpURI
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o==this)
|
||||
|
|
|
@ -123,6 +123,7 @@ public class MetaData implements Iterable<HttpField>
|
|||
* @return an iterator over the HTTP fields
|
||||
* @see #getFields()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<HttpField> iterator()
|
||||
{
|
||||
HttpFields fields = getFields();
|
||||
|
@ -180,6 +181,7 @@ public class MetaData implements Iterable<HttpField>
|
|||
this(request.getMethod(),new HttpURI(request.getURI()), request.getHttpVersion(), new HttpFields(request.getFields()), request.getContentLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recycle()
|
||||
{
|
||||
super.recycle();
|
||||
|
|
|
@ -135,6 +135,7 @@ public class QuotedQualityCSV extends QuotedCSV implements Iterable<String>
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getValues()
|
||||
{
|
||||
if (!_sorted)
|
||||
|
|
|
@ -39,7 +39,6 @@ import org.eclipse.jetty.io.EndPoint;
|
|||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.thread.ReservedThreadExecutor;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
||||
|
@ -69,36 +68,19 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
|||
HTTP2ClientSession session = new HTTP2ClientSession(scheduler, endPoint, generator, listener, flowControl);
|
||||
Parser parser = new Parser(byteBufferPool, session, 4096, 8192);
|
||||
|
||||
ReservedThreadExecutor reservedExecutor = provideReservedThreadExecutor(client, executor);
|
||||
|
||||
HTTP2ClientConnection connection = new HTTP2ClientConnection(client, byteBufferPool, reservedExecutor, endPoint,
|
||||
HTTP2ClientConnection connection = new HTTP2ClientConnection(client, byteBufferPool, executor, endPoint,
|
||||
parser, session, client.getInputBufferSize(), promise, listener);
|
||||
connection.addListener(connectionListener);
|
||||
return customize(connection, context);
|
||||
}
|
||||
|
||||
protected ReservedThreadExecutor provideReservedThreadExecutor(HTTP2Client client, Executor executor)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
ReservedThreadExecutor reservedExecutor = client.getBean(ReservedThreadExecutor.class);
|
||||
if (reservedExecutor == null)
|
||||
{
|
||||
// TODO: see HTTP2Connection.FillableCallback
|
||||
reservedExecutor = new ReservedThreadExecutor(executor, 0);
|
||||
client.addManaged(reservedExecutor);
|
||||
}
|
||||
return reservedExecutor;
|
||||
}
|
||||
}
|
||||
|
||||
private class HTTP2ClientConnection extends HTTP2Connection implements Callback
|
||||
{
|
||||
private final HTTP2Client client;
|
||||
private final Promise<Session> promise;
|
||||
private final Session.Listener listener;
|
||||
|
||||
private HTTP2ClientConnection(HTTP2Client client, ByteBufferPool byteBufferPool, ReservedThreadExecutor executor, EndPoint endpoint, Parser parser, ISession session, int bufferSize, Promise<Session> promise, Session.Listener listener)
|
||||
private HTTP2ClientConnection(HTTP2Client client, ByteBufferPool byteBufferPool, Executor executor, EndPoint endpoint, Parser parser, ISession session, int bufferSize, Promise<Session> promise, Session.Listener listener)
|
||||
{
|
||||
super(byteBufferPool, executor, endpoint, parser, session, bufferSize);
|
||||
this.client = client;
|
||||
|
|
|
@ -46,7 +46,16 @@ import org.eclipse.jetty.http2.api.server.ServerSessionListener;
|
|||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
import org.eclipse.jetty.http2.frames.GoAwayFrame;
|
||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.http2.frames.PingFrame;
|
||||
import org.eclipse.jetty.http2.frames.PriorityFrame;
|
||||
import org.eclipse.jetty.http2.frames.PushPromiseFrame;
|
||||
import org.eclipse.jetty.http2.frames.ResetFrame;
|
||||
import org.eclipse.jetty.http2.frames.SettingsFrame;
|
||||
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
||||
import org.eclipse.jetty.http2.parser.ServerParser;
|
||||
import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.FuturePromise;
|
||||
|
@ -678,6 +687,70 @@ public class HTTP2Test extends AbstractTest
|
|||
Assert.assertFalse(failureLatch.await(1, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGoAwayRespondedWithGoAway() throws Exception
|
||||
{
|
||||
ServerSessionListener.Adapter serverListener = new ServerSessionListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields());
|
||||
HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true);
|
||||
stream.headers(response, Callback.NOOP);
|
||||
stream.getSession().close(ErrorCode.NO_ERROR.code, null, Callback.NOOP);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
CountDownLatch goAwayLatch = new CountDownLatch(1);
|
||||
RawHTTP2ServerConnectionFactory connectionFactory = new RawHTTP2ServerConnectionFactory(new HttpConfiguration(), serverListener)
|
||||
{
|
||||
@Override
|
||||
protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener)
|
||||
{
|
||||
return super.newServerParser(connector, new ServerParserListenerWrapper(listener)
|
||||
{
|
||||
@Override
|
||||
public void onGoAway(GoAwayFrame frame)
|
||||
{
|
||||
super.onGoAway(frame);
|
||||
goAwayLatch.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
prepareServer(connectionFactory);
|
||||
server.start();
|
||||
|
||||
prepareClient();
|
||||
client.start();
|
||||
|
||||
CountDownLatch closeLatch = new CountDownLatch(1);
|
||||
Session session = newClient(new Session.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onClose(Session session, GoAwayFrame frame)
|
||||
{
|
||||
closeLatch.countDown();
|
||||
}
|
||||
});
|
||||
MetaData.Request metaData = newRequest("GET", new HttpFields());
|
||||
HeadersFrame request = new HeadersFrame(metaData, null, true);
|
||||
CountDownLatch responseLatch = new CountDownLatch(1);
|
||||
session.newStream(request, new Promise.Adapter<>(), new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
responseLatch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertTrue(responseLatch.await(5, TimeUnit.SECONDS));
|
||||
Assert.assertTrue(closeLatch.await(5, TimeUnit.SECONDS));
|
||||
Assert.assertTrue(goAwayLatch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
private static void sleep(long time)
|
||||
{
|
||||
try
|
||||
|
@ -689,4 +762,80 @@ public class HTTP2Test extends AbstractTest
|
|||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ServerParserListenerWrapper implements ServerParser.Listener
|
||||
{
|
||||
private final ServerParser.Listener listener;
|
||||
|
||||
private ServerParserListenerWrapper(ServerParser.Listener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreface()
|
||||
{
|
||||
listener.onPreface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onData(DataFrame frame)
|
||||
{
|
||||
listener.onData(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
{
|
||||
listener.onHeaders(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPriority(PriorityFrame frame)
|
||||
{
|
||||
listener.onPriority(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReset(ResetFrame frame)
|
||||
{
|
||||
listener.onReset(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettings(SettingsFrame frame)
|
||||
{
|
||||
listener.onSettings(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushPromise(PushPromiseFrame frame)
|
||||
{
|
||||
listener.onPushPromise(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPing(PingFrame frame)
|
||||
{
|
||||
listener.onPing(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGoAway(GoAwayFrame frame)
|
||||
{
|
||||
listener.onGoAway(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowUpdate(WindowUpdateFrame frame)
|
||||
{
|
||||
listener.onWindowUpdate(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionFailure(int error, String reason)
|
||||
{
|
||||
listener.onConnectionFailure(error, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -603,7 +603,7 @@ public class IdleTimeoutTest extends AbstractTest
|
|||
{
|
||||
long idleTimeout = 2000;
|
||||
// Use a small thread pool to cause request queueing.
|
||||
QueuedThreadPool serverExecutor = new QueuedThreadPool(4);
|
||||
QueuedThreadPool serverExecutor = new QueuedThreadPool(5);
|
||||
serverExecutor.setName("server");
|
||||
server = new Server(serverExecutor);
|
||||
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(new HttpConfiguration());
|
||||
|
|
|
@ -262,7 +262,7 @@ public class StreamResetTest extends AbstractTest
|
|||
try
|
||||
{
|
||||
// Wait for the reset to happen.
|
||||
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
|
||||
Assert.assertTrue(resetLatch.await(10, TimeUnit.SECONDS));
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
|
@ -273,9 +273,9 @@ public class StreamResetTest extends AbstractTest
|
|||
{
|
||||
// Write some content after the stream has
|
||||
// been reset, it should throw an exception.
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
Thread.sleep(500);
|
||||
Thread.sleep(100);
|
||||
response.getOutputStream().write(data);
|
||||
response.flushBuffer();
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ public class StreamResetTest extends AbstractTest
|
|||
}
|
||||
});
|
||||
|
||||
Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
|
||||
Assert.assertTrue(dataLatch.await(10, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -425,7 +425,7 @@ public class StreamResetTest extends AbstractTest
|
|||
public void testClientResetConsumesQueuedRequestWithData() throws Exception
|
||||
{
|
||||
// Use a small thread pool.
|
||||
QueuedThreadPool serverExecutor = new QueuedThreadPool(4);
|
||||
QueuedThreadPool serverExecutor = new QueuedThreadPool(5);
|
||||
serverExecutor.setName("server");
|
||||
serverExecutor.setDetailedDump(true);
|
||||
server = new Server(serverExecutor);
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.io.IOException;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.eclipse.jetty.http2.parser.Parser;
|
||||
|
@ -35,13 +36,16 @@ import org.eclipse.jetty.util.component.LifeCycle;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.ExecutionStrategy;
|
||||
import org.eclipse.jetty.util.thread.ReservedThreadExecutor;
|
||||
import org.eclipse.jetty.util.thread.TryExecutor;
|
||||
import org.eclipse.jetty.util.thread.strategy.EatWhatYouKill;
|
||||
|
||||
public class HTTP2Connection extends AbstractConnection implements WriteFlusher.Listener
|
||||
{
|
||||
protected static final Logger LOG = Log.getLogger(HTTP2Connection.class);
|
||||
|
||||
|
||||
// TODO remove this once we are sure EWYK is OK for http2
|
||||
private static final boolean PEC_MODE = Boolean.getBoolean("org.eclipse.jetty.http2.PEC_MODE");
|
||||
|
||||
private final Queue<Runnable> tasks = new ArrayDeque<>();
|
||||
private final HTTP2Producer producer = new HTTP2Producer();
|
||||
private final AtomicLong bytesIn = new AtomicLong();
|
||||
|
@ -51,14 +55,16 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
private final int bufferSize;
|
||||
private final ExecutionStrategy strategy;
|
||||
|
||||
public HTTP2Connection(ByteBufferPool byteBufferPool, ReservedThreadExecutor executor, EndPoint endPoint, Parser parser, ISession session, int bufferSize)
|
||||
public HTTP2Connection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, Parser parser, ISession session, int bufferSize)
|
||||
{
|
||||
super(endPoint, executor.getExecutor());
|
||||
super(endPoint, executor);
|
||||
this.byteBufferPool = byteBufferPool;
|
||||
this.parser = parser;
|
||||
this.session = session;
|
||||
this.bufferSize = bufferSize;
|
||||
this.strategy = new EatWhatYouKill(producer, executor.getExecutor(), executor);
|
||||
if (PEC_MODE)
|
||||
executor = new TryExecutor.NoTryExecutor(executor);
|
||||
this.strategy = new EatWhatYouKill(producer, executor);
|
||||
LifeCycle.start(strategy);
|
||||
}
|
||||
|
||||
|
@ -281,9 +287,7 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
@Override
|
||||
public InvocationType getInvocationType()
|
||||
{
|
||||
// TODO: see also AbstractHTTP2ServerConnectionFactory.reservedThreads.
|
||||
// TODO: it's non blocking here because reservedThreads=0.
|
||||
return InvocationType.NON_BLOCKING;
|
||||
return InvocationType.EITHER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
@ -404,7 +403,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
* <li>NOT_CLOSED: we move to REMOTELY_CLOSED and queue a disconnect, so
|
||||
* that the content of the queue is written, and then the connection
|
||||
* closed. We notify the application after being terminated.
|
||||
* See <code>HTTP2Session.ControlEntry#succeeded()</code></li>
|
||||
* See {@code HTTP2Session.ControlEntry#succeeded()}</li>
|
||||
* <li>In all other cases, we do nothing since other methods are already
|
||||
* performing their actions.</li>
|
||||
* </ul>
|
||||
|
@ -598,14 +597,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
{
|
||||
if (closed.compareAndSet(current, CloseState.LOCALLY_CLOSED))
|
||||
{
|
||||
byte[] payload = null;
|
||||
if (reason != null)
|
||||
{
|
||||
// Trim the reason to avoid attack vectors.
|
||||
reason = reason.substring(0, Math.min(reason.length(), 32));
|
||||
payload = reason.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
GoAwayFrame frame = new GoAwayFrame(lastStreamId.get(), error, payload);
|
||||
GoAwayFrame frame = newGoAwayFrame(error, reason);
|
||||
control(null, callback, frame);
|
||||
return true;
|
||||
}
|
||||
|
@ -622,6 +614,18 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
}
|
||||
}
|
||||
|
||||
private GoAwayFrame newGoAwayFrame(int error, String reason)
|
||||
{
|
||||
byte[] payload = null;
|
||||
if (reason != null)
|
||||
{
|
||||
// Trim the reason to avoid attack vectors.
|
||||
reason = reason.substring(0, Math.min(reason.length(), 32));
|
||||
payload = reason.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
return new GoAwayFrame(lastStreamId.get(), error, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed()
|
||||
{
|
||||
|
@ -771,9 +775,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
@Override
|
||||
public Collection<Stream> getStreams()
|
||||
{
|
||||
List<Stream> result = new ArrayList<>();
|
||||
result.addAll(streams.values());
|
||||
return result;
|
||||
return new ArrayList<>(streams.values());
|
||||
}
|
||||
|
||||
@ManagedAttribute("The number of active streams")
|
||||
|
@ -1156,6 +1158,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
frameBytes -= bytesFlushed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean generate(ByteBufferPool.Lease lease)
|
||||
{
|
||||
bytes = frameBytes = generator.control(lease, frame);
|
||||
|
@ -1251,6 +1254,14 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
}
|
||||
super.succeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
if (frame.getType() == FrameType.DISCONNECT)
|
||||
terminate(new ClosedChannelException());
|
||||
super.failed(x);
|
||||
}
|
||||
}
|
||||
|
||||
private class DataEntry extends HTTP2Flusher.Entry
|
||||
|
@ -1289,6 +1300,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
return dataBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean generate(ByteBufferPool.Lease lease)
|
||||
{
|
||||
int dataBytes = getDataBytesRemaining();
|
||||
|
@ -1441,7 +1453,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
|
||||
private void complete()
|
||||
{
|
||||
control(null, Callback.NOOP, new DisconnectFrame());
|
||||
frames(null, Callback.NOOP, newGoAwayFrame(ErrorCode.NO_ERROR.code, null), new DisconnectFrame());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,60 +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 org.eclipse.jetty.http2.api;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class UsageTest
|
||||
{
|
||||
@Ignore
|
||||
@Test
|
||||
public void test() throws Exception
|
||||
{
|
||||
// HTTP2Client client = new HTTP2Client();
|
||||
// client.connect("localhost", 8080, new Promise.Adapter<Session>()
|
||||
// {
|
||||
// @Override
|
||||
// public void succeeded(Session session)
|
||||
// {
|
||||
// session.newStream(new HeadersFrame(info, null, true), new Stream.Listener.Adapter()
|
||||
// {
|
||||
// @Override
|
||||
// public void onData(Stream stream, DataFrame frame)
|
||||
// {
|
||||
// System.out.println("received frame = " + frame);
|
||||
// }
|
||||
// }, new Adapter<Stream>()
|
||||
// {
|
||||
// @Override
|
||||
// public void succeeded(Stream stream)
|
||||
// {
|
||||
// DataFrame frame = new DataFrame(stream.getId(), ByteBuffer.wrap("HELLO".getBytes(StandardCharsets.UTF_8)), true);
|
||||
// stream.data(frame, new Callback.Adapter());
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
|
||||
// KINDA CALLBACK HELL ABOVE.
|
||||
// BELOW USING COMPLETABLES:
|
||||
|
||||
// client.connect("localhost", 8080).then(session -> session.newStream(...)).then(stream -> stream.data(...));
|
||||
}
|
||||
}
|
|
@ -430,6 +430,7 @@ public class HpackContext
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("{%s,%d,%s,%x}",isStatic()?"S":"D",_slot,_field,hashCode());
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.http2.hpack;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.DateGenerator;
|
||||
|
@ -42,7 +43,7 @@ public class HpackTest
|
|||
{
|
||||
final static HttpField ServerJetty = new PreEncodedHttpField(HttpHeader.SERVER,"jetty");
|
||||
final static HttpField XPowerJetty = new PreEncodedHttpField(HttpHeader.X_POWERED_BY,"jetty");
|
||||
final static HttpField Date = new PreEncodedHttpField(HttpHeader.DATE,DateGenerator.formatDate(System.currentTimeMillis()));
|
||||
final static HttpField Date = new PreEncodedHttpField(HttpHeader.DATE,DateGenerator.formatDate(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())));
|
||||
|
||||
@Test
|
||||
public void encodeDecodeResponseTest()
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
<Set name="maxConcurrentStreams"><Property name="jetty.http2.maxConcurrentStreams" default="128"/></Set>
|
||||
<Set name="initialStreamRecvWindow"><Property name="jetty.http2.initialStreamRecvWindow" default="524288"/></Set>
|
||||
<Set name="initialSessionRecvWindow"><Property name="jetty.http2.initialSessionRecvWindow" default="1048576"/></Set>
|
||||
<Set name="reservedThreads"><Property name="jetty.http2.reservedThreads" default="-1"/></Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
|
|
@ -27,7 +27,3 @@ etc/jetty-http2.xml
|
|||
|
||||
## Initial session receive window (client to server)
|
||||
# jetty.http2.initialSessionRecvWindow=1048576
|
||||
|
||||
## Reserve threads for high priority tasks (-1 use number of Selectors, 0 no reserved threads)
|
||||
# jetty.http2.reservedThreads=-1
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
|||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.thread.ReservedThreadExecutor;
|
||||
|
||||
@ManagedObject
|
||||
public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
|
||||
|
@ -49,7 +48,6 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
private int maxHeaderBlockFragment = 0;
|
||||
private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F);
|
||||
private long streamIdleTimeout;
|
||||
private int reservedThreads;
|
||||
|
||||
public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
|
||||
{
|
||||
|
@ -143,20 +141,24 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
}
|
||||
|
||||
/**
|
||||
* @see ReservedThreadExecutor
|
||||
* @return The number of reserved threads
|
||||
* @return -1
|
||||
* @deprecated feature removed, no replacement
|
||||
*/
|
||||
@ManagedAttribute("The number of threads reserved for high priority tasks")
|
||||
@Deprecated
|
||||
public int getReservedThreads()
|
||||
{
|
||||
return reservedThreads;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param threads ignored
|
||||
* @deprecated feature removed, no replacement
|
||||
* @throws UnsupportedOperationException when invoked
|
||||
*/
|
||||
@Deprecated
|
||||
public void setReservedThreads(int threads)
|
||||
{
|
||||
// TODO: see also HTTP2Connection.FillableCallback.
|
||||
// TODO: currently disabled since the only value that works is 0.
|
||||
// this.reservedThreads = threads;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public HttpConfiguration getHttpConfiguration()
|
||||
|
@ -183,30 +185,14 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
streamIdleTimeout = endPoint.getIdleTimeout();
|
||||
session.setStreamIdleTimeout(streamIdleTimeout);
|
||||
session.setInitialSessionRecvWindow(getInitialSessionRecvWindow());
|
||||
|
||||
ReservedThreadExecutor executor = provideReservedThreadExecutor(connector);
|
||||
|
||||
ServerParser parser = newServerParser(connector, session);
|
||||
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), executor,
|
||||
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
|
||||
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
|
||||
connection.addListener(connectionListener);
|
||||
return configure(connection, connector, endPoint);
|
||||
}
|
||||
|
||||
protected ReservedThreadExecutor provideReservedThreadExecutor(Connector connector)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
ReservedThreadExecutor executor = getBean(ReservedThreadExecutor.class);
|
||||
if (executor == null)
|
||||
{
|
||||
executor = new ReservedThreadExecutor(connector.getExecutor(), getReservedThreads());
|
||||
addManaged(executor);
|
||||
}
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract ServerSessionListener newSessionListener(Connector connector, EndPoint endPoint);
|
||||
|
||||
protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener)
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
|
@ -58,7 +59,6 @@ import org.eclipse.jetty.util.BufferUtil;
|
|||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.CountingCallback;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.thread.ReservedThreadExecutor;
|
||||
|
||||
public class HTTP2ServerConnection extends HTTP2Connection implements Connection.UpgradeTo
|
||||
{
|
||||
|
@ -94,7 +94,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
private final HttpConfiguration httpConfig;
|
||||
private boolean recycleHttpChannels;
|
||||
|
||||
public HTTP2ServerConnection(ByteBufferPool byteBufferPool, ReservedThreadExecutor executor, EndPoint endPoint, HttpConfiguration httpConfig, ServerParser parser, ISession session, int inputBufferSize, ServerSessionListener listener)
|
||||
public HTTP2ServerConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, HttpConfiguration httpConfig, ServerParser parser, ISession session, int inputBufferSize, ServerSessionListener listener)
|
||||
{
|
||||
super(byteBufferPool, executor, endPoint, parser, session, inputBufferSize);
|
||||
this.listener = listener;
|
||||
|
|
|
@ -393,10 +393,8 @@ public class HttpChannelOverHTTP2 extends HttpChannel implements Closeable, Writ
|
|||
public String toString()
|
||||
{
|
||||
IStream stream = getStream();
|
||||
long streamId = -1;
|
||||
if (stream != null)
|
||||
streamId = stream.getId();
|
||||
return String.format("%s#%d", super.toString(), getStream() == null ? -1 : streamId);
|
||||
long streamId = stream == null ? -1 : stream.getId();
|
||||
return String.format("%s#%d", super.toString(), streamId);
|
||||
}
|
||||
|
||||
private class FailureTask implements Runnable
|
||||
|
|
|
@ -89,6 +89,7 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
|
|||
|
||||
Runnable load = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run ()
|
||||
{
|
||||
try
|
||||
|
@ -269,6 +270,7 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
|
|||
|
||||
Runnable load = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run ()
|
||||
{
|
||||
try
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue