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

This commit is contained in:
Joakim Erdfelt 2018-03-06 11:16:25 -06:00
commit e3e3f9eb0b
508 changed files with 6059 additions and 2293 deletions

View File

@ -5,12 +5,8 @@ Thank you for your interest in this project!
Project description Project description
-------------------- --------------------
Jetty is a lightweight highly scalable java based web server and servlet engine. 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 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.
volume, low latency way that provides maximum performance while retaining the ease 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.
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) - [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) - [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 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 completed the contributors agreement mentioned below we will endeavor to pull your commit into Jetty proper.
your commit into Jetty proper.
Eclipse Contributor Agreement 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. create an account with the Eclipse Foundation if you have not already done so.
2. Click on "Eclipse ECA", and complete the form. 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 Contact
-------- --------

288
Jenkinsfile vendored
View File

@ -1,128 +1,164 @@
#!groovy #!groovy
node { def jdks = ["jdk8", "jdk9"]
// System Dependent Locations def oss = ["linux"] //windows? ,"linux-docker"
def mvntool = tool name: 'maven3', type: 'hudson.tasks.Maven$MavenInstallation' def builds = [:]
def jdktool = tool name: 'jdk8', type: 'hudson.model.JDK' for (def os in oss) {
for (def jdk in jdks) {
// Environment builds[os+"_"+jdk] = getFullBuild( jdk, os )
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
} }
} }
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 // True if this build is part of the "active" branches
// for Jetty. // for Jetty.
def isActiveBranch() def isActiveBranch()
{ {
def branchName = "${env.BRANCH_NAME}" def branchName = "${env.BRANCH_NAME}"
return ( branchName == "master" || return ( branchName == "master" ||
branchName.startsWith("jetty-") ); ( branchName.startsWith("jetty-") && branchName.endsWith(".x") ) );
} }
// Test if the Jenkins Pipeline or Step has marked the // Test if the Jenkins Pipeline or Step has marked the
@ -133,7 +169,7 @@ def isUnstable()
} }
// Send a notification about the build status // Send a notification about the build status
def notifyBuild(String buildStatus) def notifyBuild(String buildStatus, String jdk)
{ {
if ( !isActiveBranch() ) if ( !isActiveBranch() )
{ {
@ -145,20 +181,20 @@ def notifyBuild(String buildStatus)
buildStatus = buildStatus ?: "UNKNOWN" buildStatus = buildStatus ?: "UNKNOWN"
def email = "${env.EMAILADDRESS}" 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> def detail = """<h4>Job: <a href='${env.JOB_URL}'>${env.JOB_NAME}</a> [#${env.BUILD_NUMBER}]</h4>
<p><b>${buildStatus}</b></p> <p><b>${buildStatus}</b></p>
<table> <table>
<tr><td>Build</td><td><a href='${env.BUILD_URL}'>${env.BUILD_URL}</a></td><tr> <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>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> <tr><td>Test Report</td><td><a href='${env.BUILD_URL}testReport/'>${env.BUILD_URL}testReport/</a></td><tr>
</table> </table>
""" """
emailext ( emailext (
to: email, to: email,
subject: summary, subject: summary,
body: detail body: detail
) )
} }

View File

@ -171,6 +171,9 @@ jetty-9.4.7.v20170914 - 14 September 2017
+ 475546 ClosedChannelException when connection to HTTPS over HTTP proxy + 475546 ClosedChannelException when connection to HTTPS over HTTP proxy
with CONNECT 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 jetty-9.2.23.v20171218 - 18 December 2017
+ 1556 Remove a timing channel in Password matching + 1556 Remove a timing channel in Password matching
+ 1685 Update ALPN support for Java 8u141 + 1685 Update ALPN support for Java 8u141

View File

@ -121,6 +121,7 @@ public class AbstractRestServlet extends HttpServlet
return w; return w;
} }
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{ {
doGet(request, response); doGet(request, response);

View File

@ -40,6 +40,7 @@ import org.eclipse.jetty.util.ajax.JSON;
*/ */
public class SerialRestServlet extends AbstractRestServlet public class SerialRestServlet extends AbstractRestServlet
{ {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{ {
long start = System.nanoTime(); long start = System.nanoTime();
@ -98,6 +99,7 @@ public class SerialRestServlet extends AbstractRestServlet
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response) * response)
*/ */
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{ {
doGet(request, response); doGet(request, response);

View File

@ -49,6 +49,7 @@ public class HelloHandler extends AbstractHandler
this.body = body; this.body = body;
} }
@Override
public void handle( String target, public void handle( String target,
Request baseRequest, Request baseRequest,
HttpServletRequest request, HttpServletRequest request,

View File

@ -72,6 +72,7 @@ public class ManyHandlers
*/ */
public static class ParamHandler extends AbstractHandler public static class ParamHandler extends AbstractHandler
{ {
@Override
public void handle( String target, public void handle( String target,
Request baseRequest, Request baseRequest,
HttpServletRequest request, HttpServletRequest request,

View File

@ -167,6 +167,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
_stat = stat; _stat = stat;
} }
@Override
public Void call() throws Exception public Void call() throws Exception
{ {
if (_stat != null) if (_stat != null)
@ -275,6 +276,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
return _indexMap.size(); return _indexMap.size();
} }
@Override
public String toString() public String toString()
{ {
if (_ordering == null) if (_ordering == null)

View File

@ -61,6 +61,7 @@ public class AnnotationIntrospector
_introspectAncestors = introspectAncestors; _introspectAncestors = introspectAncestors;
} }
@Override
public void handle(Class<?> clazz) public void handle(Class<?> clazz)
{ {
Class<?> c = clazz; Class<?> c = clazz;

View File

@ -44,6 +44,7 @@ public class ClassInheritanceHandler extends AbstractHandler
_inheritanceMap = map; _inheritanceMap = map;
} }
@Override
public void handle(ClassInfo classInfo) public void handle(ClassInfo classInfo)
{ {
try try

View File

@ -49,6 +49,7 @@ public class ContainerInitializerAnnotationHandler extends AbstractHandler
* *
* @see org.eclipse.jetty.annotations.AnnotationParser.Handler#handle(org.eclipse.jetty.annotations.AnnotationParser.ClassInfo, String) * @see org.eclipse.jetty.annotations.AnnotationParser.Handler#handle(org.eclipse.jetty.annotations.AnnotationParser.ClassInfo, String)
*/ */
@Override
public void handle(ClassInfo info, String annotationName) public void handle(ClassInfo info, String annotationName)
{ {
if (annotationName == null || !_annotation.getName().equals(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) * @see org.eclipse.jetty.annotations.AnnotationParser.Handler#handle(org.eclipse.jetty.annotations.AnnotationParser.FieldInfo, String)
*/ */
@Override
public void handle(FieldInfo info, String annotationName) public void handle(FieldInfo info, String annotationName)
{ {
if (annotationName == null || !_annotation.getName().equals(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) * @see org.eclipse.jetty.annotations.AnnotationParser.Handler#handle(org.eclipse.jetty.annotations.AnnotationParser.MethodInfo, String)
*/ */
@Override
public void handle(MethodInfo info, String annotationName) public void handle(MethodInfo info, String annotationName)
{ {
if (annotationName == null || !_annotation.getName().equals(annotationName)) if (annotationName == null || !_annotation.getName().equals(annotationName))

View File

@ -48,6 +48,7 @@ public class DeclareRolesAnnotationHandler extends AbstractIntrospectableAnnotat
/** /**
* @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class) * @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class)
*/ */
@Override
public void doHandle(Class clazz) public void doHandle(Class clazz)
{ {
if (!Servlet.class.isAssignableFrom(clazz)) if (!Servlet.class.isAssignableFrom(clazz))

View File

@ -46,6 +46,7 @@ public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnno
/** /**
* @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class) * @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class)
*/ */
@Override
public void doHandle(Class clazz) public void doHandle(Class clazz)
{ {
if (!Servlet.class.isAssignableFrom(clazz)) if (!Servlet.class.isAssignableFrom(clazz))

View File

@ -41,6 +41,7 @@ public class PostConstructAnnotationHandler extends AbstractIntrospectableAnnota
} }
@Override
public void doHandle(Class clazz) public void doHandle(Class clazz)
{ {
//Check that the PostConstruct is on a class that we're interested in //Check that the PostConstruct is on a class that we're interested in

View File

@ -40,6 +40,7 @@ public class PreDestroyAnnotationHandler extends AbstractIntrospectableAnnotatio
_context = wac; _context = wac;
} }
@Override
public void doHandle(Class clazz) public void doHandle(Class clazz)
{ {
//Check that the PreDestroy is on a class that we're interested in //Check that the PreDestroy is on a class that we're interested in

View File

@ -61,6 +61,7 @@ public class ResourceAnnotationHandler extends AbstractIntrospectableAnnotationH
* environment that will be looked up at runtime. They do * environment that will be looked up at runtime. They do
* not specify an injection. * not specify an injection.
*/ */
@Override
public void doHandle(Class<?> clazz) public void doHandle(Class<?> clazz)
{ {
if (supportsResourceInjection(clazz)) if (supportsResourceInjection(clazz))

View File

@ -40,6 +40,7 @@ public class ResourcesAnnotationHandler extends AbstractIntrospectableAnnotation
_wac = wac; _wac = wac;
} }
@Override
public void doHandle (Class<?> clazz) public void doHandle (Class<?> clazz)
{ {
Resources resources = (Resources)clazz.getAnnotation(Resources.class); Resources resources = (Resources)clazz.getAnnotation(Resources.class);

View File

@ -44,6 +44,7 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
_context = wac; _context = wac;
} }
@Override
public void doHandle (Class clazz) public void doHandle (Class clazz)
{ {
if (!Servlet.class.isAssignableFrom(clazz)) if (!Servlet.class.isAssignableFrom(clazz))

View File

@ -48,6 +48,7 @@ public class ServletContainerInitializersStarter extends AbstractLifeCycle imple
* Call the doStart method of the ServletContainerInitializers * Call the doStart method of the ServletContainerInitializers
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
*/ */
@Override
public void doStart() public void doStart()
{ {
List<ContainerInitializer> initializers = (List<ContainerInitializer>)_context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS); List<ContainerInitializer> initializers = (List<ContainerInitializer>)_context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);

View File

@ -69,6 +69,7 @@ public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnno
/** /**
* @see org.eclipse.jetty.annotations.AnnotationIntrospector.IntrospectableAnnotationHandler#handle(java.lang.Class) * @see org.eclipse.jetty.annotations.AnnotationIntrospector.IntrospectableAnnotationHandler#handle(java.lang.Class)
*/ */
@Override
public void doHandle(Class clazz) public void doHandle(Class clazz)
{ {
if (!(_context.getSecurityHandler() instanceof ConstraintAware)) if (!(_context.getSecurityHandler() instanceof ConstraintAware))

View File

@ -58,6 +58,7 @@ public class WebFilterAnnotation extends DiscoveredAnnotation
/** /**
* @see DiscoveredAnnotation#apply() * @see DiscoveredAnnotation#apply()
*/ */
@Override
public void apply() public void apply()
{ {
// TODO verify against rules for annotation v descriptor // TODO verify against rules for annotation v descriptor

View File

@ -58,6 +58,7 @@ public class WebListenerAnnotation extends DiscoveredAnnotation
/** /**
* @see DiscoveredAnnotation#apply() * @see DiscoveredAnnotation#apply()
*/ */
@Override
public void apply() public void apply()
{ {
Class<? extends java.util.EventListener> clazz = (Class<? extends EventListener>)getTargetClass(); Class<? extends java.util.EventListener> clazz = (Class<? extends EventListener>)getTargetClass();

View File

@ -34,6 +34,7 @@ public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotation
super(context); super(context);
} }
@Override
public void handle(ClassInfo info, String annotationName) public void handle(ClassInfo info, String annotationName)
{ {
if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(annotationName)) if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(annotationName))
@ -43,6 +44,7 @@ public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotation
addAnnotation(wlAnnotation); addAnnotation(wlAnnotation);
} }
@Override
public void handle(FieldInfo info, String annotationName) public void handle(FieldInfo info, String annotationName)
{ {
if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(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()); LOG.warn ("@WebListener is not applicable to fields: "+info.getClassInfo().getClassName()+"."+info.getFieldName());
} }
@Override
public void handle(MethodInfo info, String annotationName) public void handle(MethodInfo info, String annotationName)
{ {
if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(annotationName)) if (annotationName == null || !"javax.servlet.annotation.WebListener".equals(annotationName))

View File

@ -65,6 +65,7 @@ public class WebServletAnnotation extends DiscoveredAnnotation
/** /**
* @see DiscoveredAnnotation#apply() * @see DiscoveredAnnotation#apply()
*/ */
@Override
public void apply() public void apply()
{ {
//TODO check this algorithm with new rules for applying descriptors and annotations in order //TODO check this algorithm with new rules for applying descriptors and annotations in order

View File

@ -45,6 +45,7 @@ public class ClassB extends ClassA implements InterfaceD
System.err.println("ClassB.package"); System.err.println("ClassB.package");
} }
@Override
public void l() public void l()
{ {
System.err.println("Overridden method l has no annotation"); System.err.println("Overridden method l has no annotation");

View File

@ -57,6 +57,7 @@ public class FilterC implements Filter
} }
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException throws IOException, ServletException
{ {
@ -69,10 +70,12 @@ public class FilterC implements Filter
arg2.doFilter(request, response); arg2.doFilter(request, response);
} }
@Override
public void destroy() public void destroy()
{ {
} }
@Override
public void init(FilterConfig arg0) throws ServletException public void init(FilterConfig arg0) throws ServletException
{ {
} }

View File

@ -26,11 +26,13 @@ import javax.servlet.annotation.WebListener;
public class ListenerC implements ServletContextListener public class ListenerC implements ServletContextListener
{ {
@Override
public void contextDestroyed(ServletContextEvent arg0) public void contextDestroyed(ServletContextEvent arg0)
{ {
} }
@Override
public void contextInitialized(ServletContextEvent arg0) public void contextInitialized(ServletContextEvent arg0)
{ {

View File

@ -58,6 +58,7 @@ public class ServletC extends HttpServlet
} }
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{ {
response.setContentType("text/html"); response.setContentType("text/html");

View File

@ -54,6 +54,7 @@ public class TestAnnotationInheritance
public final List<String> annotatedMethods = new ArrayList<String>(); public final List<String> annotatedMethods = new ArrayList<String>();
public final List<String> annotatedFields = new ArrayList<String>(); public final List<String> annotatedFields = new ArrayList<String>();
@Override
public void handle(ClassInfo info, String annotation) public void handle(ClassInfo info, String annotation)
{ {
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation)) if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
@ -62,6 +63,7 @@ public class TestAnnotationInheritance
annotatedClassNames.add(info.getClassName()); annotatedClassNames.add(info.getClassName());
} }
@Override
public void handle(FieldInfo info, String annotation) public void handle(FieldInfo info, String annotation)
{ {
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(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()); annotatedFields.add(info.getClassInfo().getClassName()+"."+info.getFieldName());
} }
@Override
public void handle(MethodInfo info, String annotation) public void handle(MethodInfo info, String annotation)
{ {
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation)) if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))

View File

@ -116,6 +116,7 @@ public class TestAnnotationParser
{ {
private List<String> methods = Arrays.asList("a","b","c","d","l"); private List<String> methods = Arrays.asList("a","b","c","d","l");
@Override
public void handle(ClassInfo info, String annotation) public void handle(ClassInfo info, String annotation)
{ {
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(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()); assertEquals("org.eclipse.jetty.annotations.ClassA",info.getClassName());
} }
@Override
public void handle(FieldInfo info, String annotation) public void handle(FieldInfo info, String annotation)
{ {
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(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()); assertEquals(org.objectweb.asm.Type.OBJECT,org.objectweb.asm.Type.getType(info.getFieldType()).getSort());
} }
@Override
public void handle(MethodInfo info, String annotation) public void handle(MethodInfo info, String annotation)
{ {
if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation)) if (annotation == null || !"org.eclipse.jetty.annotations.Sample".equals(annotation))
@ -158,6 +161,7 @@ public class TestAnnotationParser
class MultiAnnotationHandler extends AnnotationParser.AbstractHandler class MultiAnnotationHandler extends AnnotationParser.AbstractHandler
{ {
@Override
public void handle(ClassInfo info, String annotation) public void handle(ClassInfo info, String annotation)
{ {
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(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())); assertTrue("org.eclipse.jetty.annotations.ClassB".equals(info.getClassName()));
} }
@Override
public void handle(FieldInfo info, String annotation) public void handle(FieldInfo info, String annotation)
{ {
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation)) if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))
@ -173,6 +178,7 @@ public class TestAnnotationParser
fail(); fail();
} }
@Override
public void handle(MethodInfo info, String annotation) public void handle(MethodInfo info, String annotation)
{ {
if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation)) if (annotation == null || ! "org.eclipse.jetty.annotations.Multi".equals(annotation))

View File

@ -591,6 +591,7 @@ public class AntWebAppContext extends WebAppContext
/** /**
* *
*/ */
@Override
public void doStart() public void doStart()
{ {
try try
@ -627,6 +628,7 @@ public class AntWebAppContext extends WebAppContext
} }
} }
@Override
public void doStop() public void doStop()
{ {
try try

View File

@ -19,16 +19,8 @@
package org.eclipse.jetty.ant; package org.eclipse.jetty.ant;
import java.io.File; 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.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.Configuration;
import org.eclipse.jetty.webapp.WebAppClassLoader; import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
@ -50,6 +42,7 @@ public class AntWebInfConfiguration extends WebInfConfiguration
* *
* @see WebXmlConfiguration#configure(WebAppContext) * @see WebXmlConfiguration#configure(WebAppContext)
*/ */
@Override
public void configure(WebAppContext context) throws Exception public void configure(WebAppContext context) throws Exception
{ {
if (context instanceof AntWebAppContext) if (context instanceof AntWebAppContext)

View File

@ -189,6 +189,7 @@ public class JettyRunTask extends Task
* *
* @throws BuildException if unable to build * @throws BuildException if unable to build
*/ */
@Override
public void execute() throws BuildException public void execute() throws BuildException
{ {

View File

@ -56,6 +56,7 @@ public class JettyStopTask extends Task
/** /**
* @see org.apache.tools.ant.Task#execute() * @see org.apache.tools.ant.Task#execute()
*/ */
@Override
public void execute() throws BuildException public void execute() throws BuildException
{ {
try try

View File

@ -115,6 +115,7 @@ public class ServerProxyImpl implements ServerProxy
this.awc = awc; this.awc = awc;
} }
@Override
public void filesChanged(List<String> changedFileNames) public void filesChanged(List<String> changedFileNames)
{ {
boolean isScanned = false; boolean isScanned = false;
@ -151,6 +152,7 @@ public class ServerProxyImpl implements ServerProxy
} }
@Override
public void addWebApplication(AntWebAppContext webApp) public void addWebApplication(AntWebAppContext webApp)
{ {
webApplications.add(webApp); webApplications.add(webApp);
@ -242,6 +244,7 @@ public class ServerProxyImpl implements ServerProxy
/** /**
* @see org.eclipse.jetty.ant.utils.ServerProxy#start() * @see org.eclipse.jetty.ant.utils.ServerProxy#start()
*/ */
@Override
public void start() public void start()
{ {
try try
@ -289,6 +292,7 @@ public class ServerProxyImpl implements ServerProxy
/** /**
* @see org.eclipse.jetty.ant.utils.ServerProxy#getProxiedObject() * @see org.eclipse.jetty.ant.utils.ServerProxy#getProxiedObject()
*/ */
@Override
public Object getProxiedObject() public Object getProxiedObject()
{ {
return server; return server;

View File

@ -265,6 +265,7 @@ public class AntBuild
this.parser = connector; this.parser = connector;
} }
@Override
public void run() public void run()
{ {
String line; String line;

View File

@ -172,6 +172,12 @@
<version>10.0.0-SNAPSHOT</version> <version>10.0.0-SNAPSHOT</version>
<type>zip</type> <type>zip</type>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-distribution</artifactId>
<version>9.4.9-SNAPSHOT</version>
<type>tar.gz</type>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty.fcgi</groupId> <groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-client</artifactId> <artifactId>fcgi-client</artifactId>
@ -404,18 +410,6 @@
<artifactId>jetty-xml</artifactId> <artifactId>jetty-xml</artifactId>
<version>10.0.0-SNAPSHOT</version> <version>10.0.0-SNAPSHOT</version>
</dependency> </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> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -155,6 +155,7 @@ public class DuplexConnectionPool extends AbstractConnectionPool implements Swee
return active(connection); return active(connection);
} }
@Override
public boolean release(Connection connection) public boolean release(Connection connection)
{ {
boolean closed = isClosed(); boolean closed = isClosed();
@ -184,6 +185,7 @@ public class DuplexConnectionPool extends AbstractConnectionPool implements Swee
return idleConnections.offerFirst(connection); return idleConnections.offerFirst(connection);
} }
@Override
public boolean remove(Connection connection) public boolean remove(Connection connection)
{ {
return remove(connection, false); return remove(connection, false);
@ -212,6 +214,7 @@ public class DuplexConnectionPool extends AbstractConnectionPool implements Swee
return removed; return removed;
} }
@Override
public void close() public void close()
{ {
super.close(); super.close();

View File

@ -979,6 +979,8 @@ public class HttpClient extends ContainerLifeCycle
/** /**
* Gets the http compliance mode for parsing http responses. * 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 * The default http compliance level is {@link HttpCompliance#RFC7230} which is the latest HTTP/1.1 specification
*
* @return the HttpCompliance instance
*/ */
public HttpCompliance getHttpCompliance() public HttpCompliance getHttpCompliance()
{ {

View File

@ -361,6 +361,7 @@ public abstract class HttpDestination extends ContainerLifeCycle implements Dest
protected abstract SendFailure send(Connection connection, HttpExchange exchange); protected abstract SendFailure send(Connection connection, HttpExchange exchange);
@Override
public void newConnection(Promise<Connection> promise) public void newConnection(Promise<Connection> promise)
{ {
createConnection(promise); createConnection(promise);
@ -376,6 +377,7 @@ public abstract class HttpDestination extends ContainerLifeCycle implements Dest
return exchanges.remove(exchange); return exchanges.remove(exchange);
} }
@Override
public void close() public void close()
{ {
abort(new AsynchronousCloseException()); abort(new AsynchronousCloseException());

View File

@ -49,6 +49,7 @@ public class HttpResponse implements Response
return request; return request;
} }
@Override
public HttpVersion getVersion() public HttpVersion getVersion()
{ {
return version; return version;
@ -72,6 +73,7 @@ public class HttpResponse implements Response
return this; return this;
} }
@Override
public String getReason() public String getReason()
{ {
return reason; return reason;

View File

@ -263,6 +263,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
process(); process();
} }
@Override
public void abort(Throwable x) public void abort(Throwable x)
{ {
failAndClose(x); failAndClose(x);

View File

@ -207,6 +207,7 @@ public class DeferredContentProvider implements AsyncContentProvider, Callback,
* No more content will be added to this content provider * No more content will be added to this content provider
* and notifies the listener that no more content is available. * and notifies the listener that no more content is available.
*/ */
@Override
public void close() public void close()
{ {
if (closed.compareAndSet(false, true)) if (closed.compareAndSet(false, true))

View File

@ -38,7 +38,7 @@ import org.junit.runners.Parameterized;
@RunWith(Parameterized.class) @RunWith(Parameterized.class)
public abstract class AbstractHttpClientServerTest public abstract class AbstractHttpClientServerTest
{ {
@Parameterized.Parameters @Parameterized.Parameters(name = "ssl={0}")
public static Collection<SslContextFactory[]> parameters() public static Collection<SslContextFactory[]> parameters()
{ {
return Arrays.asList(new SslContextFactory[]{null}, new SslContextFactory[]{new SslContextFactory()}); return Arrays.asList(new SslContextFactory[]{null}, new SslContextFactory[]{new SslContextFactory()});

View File

@ -44,6 +44,7 @@ import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.After; import org.junit.After;
@ -58,7 +59,7 @@ public class HttpClientTLSTest
private void startServer(SslContextFactory sslContextFactory, Handler handler) throws Exception private void startServer(SslContextFactory sslContextFactory, Handler handler) throws Exception
{ {
QueuedThreadPool serverThreads = new QueuedThreadPool(); ExecutorThreadPool serverThreads = new ExecutorThreadPool();
serverThreads.setName("server"); serverThreads.setName("server");
server = new Server(serverThreads); server = new Server(serverThreads);

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -45,23 +46,39 @@ public class RoundRobinConnectionPoolTest extends AbstractHttpClientServerTest
@Test @Test
public void testRoundRobin() throws Exception public void testRoundRobin() throws Exception
{ {
AtomicBoolean record = new AtomicBoolean();
List<Integer> remotePorts = new ArrayList<>(); List<Integer> remotePorts = new ArrayList<>();
start(new EmptyServerHandler() start(new EmptyServerHandler()
{ {
@Override @Override
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException 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; int maxConnections = 3;
client.getTransport().setConnectionPoolFactory(destination -> new RoundRobinConnectionPool(destination, maxConnections, destination)); 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; int requests = 2 * maxConnections - 1;
for (int i = 0; i < requests; ++i) for (int i = 0; i < requests; ++i)
{ {
ContentResponse response = client.newRequest("localhost", connector.getLocalPort()) ContentResponse response = client.newRequest(host, port)
.scheme(scheme) .scheme(scheme)
.timeout(5, TimeUnit.SECONDS) .timeout(5, TimeUnit.SECONDS)
.send(); .send();
@ -74,7 +91,7 @@ public class RoundRobinConnectionPoolTest extends AbstractHttpClientServerTest
int base = i % maxConnections; int base = i % maxConnections;
int expected = remotePorts.get(base); int expected = remotePorts.get(base);
int candidate = remotePorts.get(i); 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) if (i > 0)
Assert.assertThat(remotePorts.get(i - 1), Matchers.not(Matchers.equalTo(candidate))); Assert.assertThat(remotePorts.get(i - 1), Matchers.not(Matchers.equalTo(candidate)));
} }

View File

@ -56,38 +56,43 @@ public class HttpDestinationOverHTTPTest extends AbstractHttpClientServerTest
@Test @Test
public void test_FirstAcquire_WithEmptyQueue() throws Exception public void test_FirstAcquire_WithEmptyQueue() throws Exception
{ {
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort())); try(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)
{ {
// There are no queued requests, so the newly created connection will be idle destination.start();
connection = timedPoll(connectionPool.getIdleConnections(), 5, TimeUnit.SECONDS); 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 @Test
public void test_SecondAcquire_AfterFirstAcquire_WithEmptyQueue_ReturnsSameConnection() throws Exception public void test_SecondAcquire_AfterFirstAcquire_WithEmptyQueue_ReturnsSameConnection() throws Exception
{ {
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort())); try(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)
{ {
// There are no queued requests, so the newly created connection will be idle destination.start();
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(); DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
Assert.assertSame(connection1, connection2); 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();
// Make sure we entered idleCreated(). try
Assert.assertTrue(idleLatch.await(5, TimeUnit.SECONDS)); {
destination.start();
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
Connection connection1 = connectionPool.acquire();
// There are no available existing connections, so acquire() // Make sure we entered idleCreated().
// returns null because we delayed idleCreated() above Assert.assertTrue(idleLatch.await(5, TimeUnit.SECONDS));
Assert.assertNull(connection1);
// Second attempt also returns null because we delayed idleCreated() above. // There are no available existing connections, so acquire()
Connection connection2 = connectionPool.acquire(); // returns null because we delayed idleCreated() above
Assert.assertNull(connection2); Assert.assertNull(connection1);
latch.countDown(); // Second attempt also returns null because we delayed idleCreated() above.
Connection connection2 = connectionPool.acquire();
Assert.assertNull(connection2);
// There must be 2 idle connections. latch.countDown();
Queue<Connection> idleConnections = connectionPool.getIdleConnections();
Connection connection = timedPoll(idleConnections, 5, TimeUnit.SECONDS); // There must be 2 idle connections.
Assert.assertNotNull(connection); Queue<Connection> idleConnections = connectionPool.getIdleConnections();
connection = timedPoll(idleConnections, 5, TimeUnit.SECONDS); Connection connection = timedPoll(idleConnections, 5, TimeUnit.SECONDS);
Assert.assertNotNull(connection); Assert.assertNotNull(connection);
connection = timedPoll(idleConnections, 5, TimeUnit.SECONDS);
Assert.assertNotNull(connection);
}
finally
{
destination.close();
}
} }
@Test @Test
public void test_Acquire_Process_Release_Acquire_ReturnsSameConnection() throws Exception public void test_Acquire_Process_Release_Acquire_ReturnsSameConnection() throws Exception
{ {
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort())); try(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)
{ {
TimeUnit.MILLISECONDS.sleep(50); destination.start();
connection1 = (HttpConnectionOverHTTP)connectionPool.getIdleConnections().peek(); 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 @Test
@ -177,25 +194,27 @@ public class HttpDestinationOverHTTPTest extends AbstractHttpClientServerTest
long idleTimeout = 1000; long idleTimeout = 1000;
client.setIdleTimeout(idleTimeout); client.setIdleTimeout(idleTimeout);
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", connector.getLocalPort())); try(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)
{ {
// There are no queued requests, so the newly created connection will be idle destination.start();
long start = System.nanoTime(); DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
while (connection1 == null && TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) < 5) Connection connection1 = connectionPool.acquire();
if (connection1 == null)
{ {
TimeUnit.MILLISECONDS.sleep(50); // There are no queued requests, so the newly created connection will be idle
connection1 = connectionPool.getIdleConnections().peek(); 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);
} }
} }

View File

@ -140,6 +140,7 @@ public abstract class SslBytesTest
serverSocket.close(); serverSocket.close();
} }
@Override
public void run() public void run()
{ {
try try

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -74,6 +74,7 @@ public class AppLifeCycle extends Graph
public static final String STARTED = "started"; public static final String STARTED = "started";
public static final String STOPPING = "stopping"; public static final String STOPPING = "stopping";
public static final String UNDEPLOYING = "undeploying"; public static final String UNDEPLOYING = "undeploying";
public static final String FAILED = "failed";
private Map<String, List<Binding>> lifecyclebindings = new HashMap<String, List<Binding>>(); private Map<String, List<Binding>> lifecyclebindings = new HashMap<String, List<Binding>>();
@ -97,6 +98,9 @@ public class AppLifeCycle extends Graph
// deployed -> undeployed // deployed -> undeployed
addEdge(DEPLOYED,UNDEPLOYING); addEdge(DEPLOYED,UNDEPLOYING);
addEdge(UNDEPLOYING,UNDEPLOYED); addEdge(UNDEPLOYING,UNDEPLOYED);
// failed (unconnected)
addNode(new Node(FAILED));
} }
public void addBinding(AppLifeCycle.Binding binding) public void addBinding(AppLifeCycle.Binding binding)

View File

@ -507,6 +507,18 @@ public class DeploymentManager extends ContainerLifeCycle
catch (Throwable t) catch (Throwable t)
{ {
LOG.warn("Unable to reach node goal: " + nodeName,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);
}
} }
} }

View File

@ -40,11 +40,13 @@ public class DebugBinding implements AppLifeCycle.Binding
_targets=targets; _targets=targets;
} }
@Override
public String[] getBindingTargets() public String[] getBindingTargets()
{ {
return _targets; return _targets;
} }
@Override
public void processBinding(Node node, App app) throws Exception public void processBinding(Node node, App app) throws Exception
{ {
LOG.info("processBinding {} {}",node,app.getContextHandler()); LOG.info("processBinding {} {}",node,app.getContextHandler());

View File

@ -45,6 +45,7 @@ public class DebugListenerBinding extends DebugBinding
return _debugListener; return _debugListener;
} }
@Override
public void processBinding(Node node, App app) throws Exception public void processBinding(Node node, App app) throws Exception
{ {
app.getContextHandler().addEventListener(_debugListener); app.getContextHandler().addEventListener(_debugListener);

View File

@ -62,11 +62,13 @@ public class GlobalWebappConfigBinding implements AppLifeCycle.Binding
this._jettyXml = jettyXml; this._jettyXml = jettyXml;
} }
@Override
public String[] getBindingTargets() public String[] getBindingTargets()
{ {
return new String[] { "deploying" }; return new String[] { "deploying" };
} }
@Override
public void processBinding(Node node, App app) throws Exception public void processBinding(Node node, App app) throws Exception
{ {
ContextHandler handler = app.getContextHandler(); ContextHandler handler = app.getContextHandler();

View File

@ -63,11 +63,13 @@ public class OrderedGroupBinding implements AppLifeCycle.Binding
} }
} }
@Override
public String[] getBindingTargets() public String[] getBindingTargets()
{ {
return _bindingTargets; return _bindingTargets;
} }
@Override
public void processBinding(Node node, App app) throws Exception public void processBinding(Node node, App app) throws Exception
{ {
for ( AppLifeCycle.Binding binding : _orderedBindings ) for ( AppLifeCycle.Binding binding : _orderedBindings )

View File

@ -25,12 +25,14 @@ import org.eclipse.jetty.server.handler.ContextHandler;
public class StandardDeployer implements AppLifeCycle.Binding public class StandardDeployer implements AppLifeCycle.Binding
{ {
@Override
public String[] getBindingTargets() public String[] getBindingTargets()
{ {
return new String[] return new String[]
{ "deploying" }; { "deploying" };
} }
@Override
public void processBinding(Node node, App app) throws Exception public void processBinding(Node node, App app) throws Exception
{ {
ContextHandler handler = app.getContextHandler(); ContextHandler handler = app.getContextHandler();

View File

@ -22,6 +22,7 @@ import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.AppLifeCycle;
import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.deploy.graph.Node;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
public class StandardStarter implements AppLifeCycle.Binding public class StandardStarter implements AppLifeCycle.Binding
{ {
@ -35,12 +36,17 @@ public class StandardStarter implements AppLifeCycle.Binding
@Override @Override
public void processBinding(Node node, App app) throws Exception public void processBinding(Node node, App app) throws Exception
{ {
ContextHandlerCollection contexts = app.getDeploymentManager().getContexts();
ContextHandler handler = app.getContextHandler(); ContextHandler handler = app.getContextHandler();
// start the handler if (contexts.isStarted() && handler.isStopped())
handler.start(); {
// start the handler manually
handler.start();
// After starting let the context manage state // After starting let the context manage state
app.getDeploymentManager().getContexts().manage(handler); contexts.manage(handler);
}
} }
} }

View File

@ -50,6 +50,7 @@ public class GraphOutputDot
{ {
private Collator collator = Collator.getInstance(); private Collator collator = Collator.getInstance();
@Override
public int compare(Node o1, Node o2) public int compare(Node o1, Node o2)
{ {
if (o1.getName().equals(TOPNODE)) if (o1.getName().equals(TOPNODE))

View File

@ -41,12 +41,14 @@ public class AppLifeCyclePathCollector implements AppLifeCycle.Binding
return actualOrder; return actualOrder;
} }
@Override
public String[] getBindingTargets() public String[] getBindingTargets()
{ {
return new String[] return new String[]
{ "*" }; { "*" };
} }
@Override
public void processBinding(Node node, App app) throws Exception public void processBinding(Node node, App app) throws Exception
{ {
actualOrder.add(node); actualOrder.add(node);

View File

@ -33,6 +33,7 @@ public class MockAppProvider extends AbstractLifeCycle implements AppProvider
private DeploymentManager deployMan; private DeploymentManager deployMan;
private File webappsDir; private File webappsDir;
@Override
public void setDeploymentManager(DeploymentManager deploymentManager) public void setDeploymentManager(DeploymentManager deploymentManager)
{ {
this.deployMan = deploymentManager; this.deployMan = deploymentManager;
@ -50,6 +51,7 @@ public class MockAppProvider extends AbstractLifeCycle implements AppProvider
this.deployMan.addApp(app); this.deployMan.addApp(app);
} }
@Override
public ContextHandler createContextHandler(App app) throws Exception public ContextHandler createContextHandler(App app) throws Exception
{ {
WebAppContext context = new WebAppContext(); WebAppContext context = new WebAppContext();

View File

@ -80,6 +80,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
_providers++; _providers++;
((ScanningAppProvider)provider).addScannerListener(new Scanner.ScanListener() ((ScanningAppProvider)provider).addScannerListener(new Scanner.ScanListener()
{ {
@Override
public void scan() public void scan()
{ {
_scans.incrementAndGet(); _scans.incrementAndGet();

View File

@ -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. 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. 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 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. 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 * 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. Each provider above provides an ALPN _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]). 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. 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. 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-openjdk8]]
==== ALPN and OpenJDK 8 ==== 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]. 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]] [[alpn-osgi]]
===== Starting in OSGi ===== Starting in OSGi

View File

@ -19,12 +19,15 @@
[[alpn-chapter]] [[alpn-chapter]]
== Application Layer Protocol Negotiation (ALPN) == 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. The development of new web protocols such as HTTP/2 raised the need of protocol
A protocol negotiation called https://tools.ietf.org/html/rfc7301[ALPN] (Application Layer Protocol Negotiation) RFC7301 has been defined to accomplish this. 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. Starting with Jetty 9.3.0, only ALPN is supported by Jetty.
include::alpn.adoc[] include::alpn.adoc[]

View File

@ -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. 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. 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: 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"); 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: There are several ways to use a particular directory as the temporary directory:
===== Call WebAppContext.setTempDirectory(String dir) ===== 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}"] [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> </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}"] [source, java, subs="{sub-order}"]
---- ----
@ -103,8 +104,9 @@ context.setWar("foo.war");
context.setTempDirectory(new File("/some/dir/foo")); context.setTempDirectory(new File("/some/dir/foo"));
---- ----
===== Set the javax.servlet.context.tempdir context attribute ===== 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: 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}"] [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.] 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}`. 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). 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. This ensures the name of the directory remains consistent across context restarts.
==== Persisting the temp directory ==== Persisting the temp directory

View File

@ -35,7 +35,7 @@ _____
|Version |Year |Home |JVM |Protocols |Servlet |JSP |Status |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.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.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* |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* |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* |6 |2006-2010 |Codehaus |1.4-1.5 |HTTP/1.1 RFC2616 |2.5 |2.0 |Deprecated / *End of Life November 2010*

View File

@ -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. 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: 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. * 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. 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. * 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. * 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. 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 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 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. 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]]
===== 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"> <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-custom-classloader]]
==== Starting Jetty with a Custom ClassLoader ==== Starting Jetty with a Custom ClassLoader
If you start a Jetty server using a custom class loaderconsider the Jetty classes not being available to the system class loader, only your custom class loaderyou may run into class loading issues when the WebAppClassLoader kicks in. If you start a Jetty server using a custom class loaderconsider the Jetty classes not being available to the system class loader, only your custom class loaderyou 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: 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}"] [source, java, subs="{sub-order}"]
---- ----

View File

@ -50,6 +50,3 @@ Users are always welcome to come join our IRC channels and talk with us, other u
irc.freenode.org - #jetty:: irc.freenode.org - #jetty::
Our primary location, we recommend that if your looking to find folks on IRC you try here. 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. 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.

View File

@ -42,7 +42,7 @@ For a more in-depth look at the syntax, see xref:jetty-xml-syntax[].
____ ____
[CAUTION] [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]] [[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. 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. 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]]
==== Additional `jetty-web.xml` Resources ==== Additional `jetty-web.xml` Resources

View File

@ -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",] [width="99%",cols="11%,19%,14%,9%,14%,14%,19%",options="header",]
|======================================================================= |=======================================================================
|yyyy/mm/dd |ID |Exploitable |Severity |Affects |Fixed Version |Comment |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 |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
|http://www.ocert.org/advisories/ocert-2016-001.html[Alias vulnerability allowing access to protected resources within a webapp on Windows.] |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 |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
|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] |JetLeak exposure of past buffers during HttpParser error
|2013/11/27 |http://en.securitylab.ru/lab/PT-2013-65[PT-2013-65] |medium |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 |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 around by turning off SSL renegotiation in Jetty. If using JVM > 1.6u19
setAllowRenegotiate(true) may be called on connectors. 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 |high |< = 6.1.18, < = 7.0.0.M4 |6.1.19, 7.0.0.Rc0 |Cookie leak between
requests sharing a connection. requests sharing a connection.
@ -63,7 +63,7 @@ requests sharing a connection.
|high |< = 6.1.16, < = 7.0.0.M2 a| |high |< = 6.1.16, < = 7.0.0.M2 a|
5.1.15, 6.1.18, 7.0.0.M2 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. |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| |high |medium |6.1.rrc0-6.1.6 a|
6.1.7 6.1.7
http://jira.codehaus.org/browse/JETTY-386[CERT553235] CERT553235
|Static content visible in WEB-INF and past security constraints. |Static content visible in WEB-INF and past security constraints.

View File

@ -129,7 +129,7 @@ xmlns:date="http://exslt.org/dates-and-times"
</td> </td>
<td style="width: 50%"> <td style="width: 50%">
<script> <!-- <script>
(function() { (function() {
var cx = '005120552842603642412:peimxy9z8nu'; var cx = '005120552842603642412:peimxy9z8nu';
var gcse = document.createElement('script'); var gcse = document.createElement('script');
@ -140,7 +140,7 @@ xmlns:date="http://exslt.org/dates-and-times"
s.parentNode.insertBefore(gcse, s); s.parentNode.insertBefore(gcse, s);
})(); })();
</script> </script>
<gcse:search></gcse:search> <gcse:search></gcse:search>-->
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -916,6 +916,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
final AtomicReference<Exception> exception = new AtomicReference<Exception>(); final AtomicReference<Exception> exception = new AtomicReference<Exception>();
Runnable load = new Runnable() Runnable load = new Runnable()
{ {
@Override
public void run () public void run ()
{ {
try try

View File

@ -12,7 +12,7 @@
<name>Jetty :: Hazelcast Session Manager</name> <name>Jetty :: Hazelcast Session Manager</name>
<properties> <properties>
<hazelcast.version>3.8.2</hazelcast.version> <hazelcast.version>3.9.3</hazelcast.version>
<bundle-symbolic-name>${project.groupId}.hazelcast</bundle-symbolic-name> <bundle-symbolic-name>${project.groupId}.hazelcast</bundle-symbolic-name>
</properties> </properties>

View File

@ -12,6 +12,7 @@
<properties> <properties>
<assembly-directory>${basedir}/target/jetty-home</assembly-directory> <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> <jetty-setuid-version>1.0.3</jetty-setuid-version>
</properties> </properties>
@ -150,6 +151,25 @@
<outputDirectory>${assembly-directory}/lib</outputDirectory> <outputDirectory>${assembly-directory}/lib</outputDirectory>
</configuration> </configuration>
</execution> </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> <execution>
<id>copy-lib-websocket-deps</id> <id>copy-lib-websocket-deps</id>
<phase>generate-resources</phase> <phase>generate-resources</phase>
@ -163,6 +183,20 @@
<outputDirectory>${assembly-directory}/lib/websocket</outputDirectory> <outputDirectory>${assembly-directory}/lib/websocket</outputDirectory>
</configuration> </configuration>
</execution> </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> <execution>
<id>copy-lib-http2-deps</id> <id>copy-lib-http2-deps</id>
<phase>generate-resources</phase> <phase>generate-resources</phase>
@ -176,6 +210,20 @@
<outputDirectory>${assembly-directory}/lib/http2</outputDirectory> <outputDirectory>${assembly-directory}/lib/http2</outputDirectory>
</configuration> </configuration>
</execution> </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> <execution>
<id>copy-lib-fcgi-deps</id> <id>copy-lib-fcgi-deps</id>
<phase>generate-resources</phase> <phase>generate-resources</phase>
@ -188,6 +236,19 @@
<outputDirectory>${assembly-directory}/lib/fcgi</outputDirectory> <outputDirectory>${assembly-directory}/lib/fcgi</outputDirectory>
</configuration> </configuration>
</execution> </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> <execution>
<id>copy-lib-spring-deps</id> <id>copy-lib-spring-deps</id>
<phase>generate-resources</phase> <phase>generate-resources</phase>
@ -201,6 +262,20 @@
<outputDirectory>${assembly-directory}/lib/spring</outputDirectory> <outputDirectory>${assembly-directory}/lib/spring</outputDirectory>
</configuration> </configuration>
</execution> </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> <execution>
<id>copy-servlet-api-deps</id> <id>copy-servlet-api-deps</id>
<phase>generate-resources</phase> <phase>generate-resources</phase>
@ -241,6 +316,20 @@
<outputDirectory>${assembly-directory}/lib/annotations</outputDirectory> <outputDirectory>${assembly-directory}/lib/annotations</outputDirectory>
</configuration> </configuration>
</execution> </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> <execution>
<id>copy-apache-jsp-deps</id> <id>copy-apache-jsp-deps</id>
<phase>generate-resources</phase> <phase>generate-resources</phase>
@ -257,6 +346,23 @@
<outputDirectory>${assembly-directory}/lib/apache-jsp</outputDirectory> <outputDirectory>${assembly-directory}/lib/apache-jsp</outputDirectory>
</configuration> </configuration>
</execution> </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> <execution>
<id>copy-apache-jstl-deps</id> <id>copy-apache-jstl-deps</id>
<phase>generate-resources</phase> <phase>generate-resources</phase>
@ -271,6 +377,21 @@
<outputDirectory>${assembly-directory}/lib/apache-jstl</outputDirectory> <outputDirectory>${assembly-directory}/lib/apache-jstl</outputDirectory>
</configuration> </configuration>
</execution> </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> <execution>
<id>copy-jaspi-deps</id> <id>copy-jaspi-deps</id>
<phase>generate-resources</phase> <phase>generate-resources</phase>
@ -284,6 +405,20 @@
<outputDirectory>${assembly-directory}/lib/jaspi</outputDirectory> <outputDirectory>${assembly-directory}/lib/jaspi</outputDirectory>
</configuration> </configuration>
</execution> </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> <execution>
<id>unpack-config-deps</id> <id>unpack-config-deps</id>
<phase>generate-resources</phase> <phase>generate-resources</phase>
@ -322,18 +457,34 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<configuration> <configuration>
<descriptors>
<descriptor>src/main/assembly/jetty-assembly.xml</descriptor>
</descriptors>
<tarLongFileMode>posix</tarLongFileMode> <tarLongFileMode>posix</tarLongFileMode>
<appendAssemblyId>false</appendAssemblyId> <appendAssemblyId>false</appendAssemblyId>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
<id>binary</id>
<phase>package</phase> <phase>package</phase>
<goals> <goals>
<goal>single</goal> <goal>single</goal>
</goals> </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> </execution>
</executions> </executions>
</plugin> </plugin>

View File

@ -1,5 +1,5 @@
<assembly> <assembly>
<id>assembly</id> <id>binary-assembly</id>
<formats> <formats>
<format>tar.gz</format> <format>tar.gz</format>
<format>zip</format> <format>zip</format>

View File

@ -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>

View File

@ -176,6 +176,7 @@ public class JettyHttpExchange extends HttpExchange implements JettyExchange
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override
public void setPrincipal(HttpPrincipal principal) public void setPrincipal(HttpPrincipal principal)
{ {
_delegate.setPrincipal(principal); _delegate.setPrincipal(principal);

View File

@ -67,7 +67,7 @@ public class JettyHttpServerProvider extends HttpServerProvider
JettyHttpServer jettyHttpServer = new JettyHttpServer(server, shared); JettyHttpServer jettyHttpServer = new JettyHttpServer(server, shared);
if (addr != null) if (addr != null)
jettyHttpServer.bind(addr, backlog); jettyHttpServer.bind(addr, backlog);
return jettyHttpServer; return jettyHttpServer;
} }

View File

@ -160,6 +160,7 @@ public class JettyHttpsExchange extends HttpsExchange implements JettyExchange
return _delegate.getPrincipal(); return _delegate.getPrincipal();
} }
@Override
public void setPrincipal(HttpPrincipal principal) public void setPrincipal(HttpPrincipal principal)
{ {
_delegate.setPrincipal(principal); _delegate.setPrincipal(principal);

View File

@ -74,6 +74,7 @@ public class TestSPIServer
new HttpHandler() new HttpHandler()
{ {
@Override
public void handle(HttpExchange exchange) throws IOException public void handle(HttpExchange exchange) throws IOException
{ {
Headers responseHeaders = exchange.getResponseHeaders(); Headers responseHeaders = exchange.getResponseHeaders();
@ -163,6 +164,7 @@ public class TestSPIServer
new HttpHandler() new HttpHandler()
{ {
@Override
public void handle(HttpExchange exchange) throws IOException public void handle(HttpExchange exchange) throws IOException
{ {
Headers responseHeaders = exchange.getResponseHeaders(); Headers responseHeaders = exchange.getResponseHeaders();

View File

@ -947,11 +947,13 @@ public class HttpFields implements Iterable<HttpField>
int _cursor; // index of next element to return int _cursor; // index of next element to return
int _last=-1; int _last=-1;
@Override
public boolean hasNext() public boolean hasNext()
{ {
return _cursor != _size; return _cursor != _size;
} }
@Override
public HttpField next() public HttpField next()
{ {
int i = _cursor; int i = _cursor;
@ -961,6 +963,7 @@ public class HttpFields implements Iterable<HttpField>
return _fields[_last=i]; return _fields[_last=i];
} }
@Override
public void remove() public void remove()
{ {
if (_last<0) if (_last<0)

View File

@ -719,6 +719,7 @@ public class HttpURI
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override
public boolean equals(Object o) public boolean equals(Object o)
{ {
if (o==this) if (o==this)

View File

@ -123,6 +123,7 @@ public class MetaData implements Iterable<HttpField>
* @return an iterator over the HTTP fields * @return an iterator over the HTTP fields
* @see #getFields() * @see #getFields()
*/ */
@Override
public Iterator<HttpField> iterator() public Iterator<HttpField> iterator()
{ {
HttpFields fields = getFields(); 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()); this(request.getMethod(),new HttpURI(request.getURI()), request.getHttpVersion(), new HttpFields(request.getFields()), request.getContentLength());
} }
@Override
public void recycle() public void recycle()
{ {
super.recycle(); super.recycle();

View File

@ -135,6 +135,7 @@ public class QuotedQualityCSV extends QuotedCSV implements Iterable<String>
} }
} }
@Override
public List<String> getValues() public List<String> getValues()
{ {
if (!_sorted) if (!_sorted)

View File

@ -39,7 +39,6 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise; import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.thread.ReservedThreadExecutor;
import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.Scheduler;
public class HTTP2ClientConnectionFactory implements ClientConnectionFactory public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
@ -69,36 +68,19 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
HTTP2ClientSession session = new HTTP2ClientSession(scheduler, endPoint, generator, listener, flowControl); HTTP2ClientSession session = new HTTP2ClientSession(scheduler, endPoint, generator, listener, flowControl);
Parser parser = new Parser(byteBufferPool, session, 4096, 8192); Parser parser = new Parser(byteBufferPool, session, 4096, 8192);
ReservedThreadExecutor reservedExecutor = provideReservedThreadExecutor(client, executor); HTTP2ClientConnection connection = new HTTP2ClientConnection(client, byteBufferPool, executor, endPoint,
HTTP2ClientConnection connection = new HTTP2ClientConnection(client, byteBufferPool, reservedExecutor, endPoint,
parser, session, client.getInputBufferSize(), promise, listener); parser, session, client.getInputBufferSize(), promise, listener);
connection.addListener(connectionListener); connection.addListener(connectionListener);
return customize(connection, context); 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 class HTTP2ClientConnection extends HTTP2Connection implements Callback
{ {
private final HTTP2Client client; private final HTTP2Client client;
private final Promise<Session> promise; private final Promise<Session> promise;
private final Session.Listener listener; 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); super(byteBufferPool, executor, endpoint, parser, session, bufferSize);
this.client = client; this.client = client;

View File

@ -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.DataFrame;
import org.eclipse.jetty.http2.frames.GoAwayFrame; import org.eclipse.jetty.http2.frames.GoAwayFrame;
import org.eclipse.jetty.http2.frames.HeadersFrame; 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.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.BufferUtil;
import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FuturePromise; import org.eclipse.jetty.util.FuturePromise;
@ -678,6 +687,70 @@ public class HTTP2Test extends AbstractTest
Assert.assertFalse(failureLatch.await(1, TimeUnit.SECONDS)); 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) private static void sleep(long time)
{ {
try try
@ -689,4 +762,80 @@ public class HTTP2Test extends AbstractTest
throw new RuntimeException(); 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);
}
}
} }

View File

@ -603,7 +603,7 @@ public class IdleTimeoutTest extends AbstractTest
{ {
long idleTimeout = 2000; long idleTimeout = 2000;
// Use a small thread pool to cause request queueing. // Use a small thread pool to cause request queueing.
QueuedThreadPool serverExecutor = new QueuedThreadPool(4); QueuedThreadPool serverExecutor = new QueuedThreadPool(5);
serverExecutor.setName("server"); serverExecutor.setName("server");
server = new Server(serverExecutor); server = new Server(serverExecutor);
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(new HttpConfiguration()); HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(new HttpConfiguration());

View File

@ -262,7 +262,7 @@ public class StreamResetTest extends AbstractTest
try try
{ {
// Wait for the reset to happen. // Wait for the reset to happen.
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(resetLatch.await(10, TimeUnit.SECONDS));
} }
catch (InterruptedException x) catch (InterruptedException x)
{ {
@ -273,9 +273,9 @@ public class StreamResetTest extends AbstractTest
{ {
// Write some content after the stream has // Write some content after the stream has
// been reset, it should throw an exception. // 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.getOutputStream().write(data);
response.flushBuffer(); 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 @Test
@ -425,7 +425,7 @@ public class StreamResetTest extends AbstractTest
public void testClientResetConsumesQueuedRequestWithData() throws Exception public void testClientResetConsumesQueuedRequestWithData() throws Exception
{ {
// Use a small thread pool. // Use a small thread pool.
QueuedThreadPool serverExecutor = new QueuedThreadPool(4); QueuedThreadPool serverExecutor = new QueuedThreadPool(5);
serverExecutor.setName("server"); serverExecutor.setName("server");
serverExecutor.setDetailedDump(true); serverExecutor.setDetailedDump(true);
server = new Server(serverExecutor); server = new Server(serverExecutor);

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jetty.http2.parser.Parser; 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.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ExecutionStrategy; 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; import org.eclipse.jetty.util.thread.strategy.EatWhatYouKill;
public class HTTP2Connection extends AbstractConnection implements WriteFlusher.Listener public class HTTP2Connection extends AbstractConnection implements WriteFlusher.Listener
{ {
protected static final Logger LOG = Log.getLogger(HTTP2Connection.class); 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 Queue<Runnable> tasks = new ArrayDeque<>();
private final HTTP2Producer producer = new HTTP2Producer(); private final HTTP2Producer producer = new HTTP2Producer();
private final AtomicLong bytesIn = new AtomicLong(); private final AtomicLong bytesIn = new AtomicLong();
@ -51,14 +55,16 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
private final int bufferSize; private final int bufferSize;
private final ExecutionStrategy strategy; 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.byteBufferPool = byteBufferPool;
this.parser = parser; this.parser = parser;
this.session = session; this.session = session;
this.bufferSize = bufferSize; 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); LifeCycle.start(strategy);
} }
@ -281,9 +287,7 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
@Override @Override
public InvocationType getInvocationType() public InvocationType getInvocationType()
{ {
// TODO: see also AbstractHTTP2ServerConnectionFactory.reservedThreads. return InvocationType.EITHER;
// TODO: it's non blocking here because reservedThreads=0.
return InvocationType.NON_BLOCKING;
} }
} }
} }

View File

@ -24,7 +24,6 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; 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 * <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 * that the content of the queue is written, and then the connection
* closed. We notify the application after being terminated. * 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 * <li>In all other cases, we do nothing since other methods are already
* performing their actions.</li> * performing their actions.</li>
* </ul> * </ul>
@ -598,14 +597,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
{ {
if (closed.compareAndSet(current, CloseState.LOCALLY_CLOSED)) if (closed.compareAndSet(current, CloseState.LOCALLY_CLOSED))
{ {
byte[] payload = null; GoAwayFrame frame = newGoAwayFrame(error, reason);
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);
control(null, callback, frame); control(null, callback, frame);
return true; 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 @Override
public boolean isClosed() public boolean isClosed()
{ {
@ -771,9 +775,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
@Override @Override
public Collection<Stream> getStreams() public Collection<Stream> getStreams()
{ {
List<Stream> result = new ArrayList<>(); return new ArrayList<>(streams.values());
result.addAll(streams.values());
return result;
} }
@ManagedAttribute("The number of active streams") @ManagedAttribute("The number of active streams")
@ -1156,6 +1158,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
frameBytes -= bytesFlushed; frameBytes -= bytesFlushed;
} }
@Override
protected boolean generate(ByteBufferPool.Lease lease) protected boolean generate(ByteBufferPool.Lease lease)
{ {
bytes = frameBytes = generator.control(lease, frame); bytes = frameBytes = generator.control(lease, frame);
@ -1251,6 +1254,14 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
} }
super.succeeded(); 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 private class DataEntry extends HTTP2Flusher.Entry
@ -1289,6 +1300,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
return dataBytes; return dataBytes;
} }
@Override
protected boolean generate(ByteBufferPool.Lease lease) protected boolean generate(ByteBufferPool.Lease lease)
{ {
int dataBytes = getDataBytesRemaining(); int dataBytes = getDataBytesRemaining();
@ -1441,7 +1453,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
private void complete() private void complete()
{ {
control(null, Callback.NOOP, new DisconnectFrame()); frames(null, Callback.NOOP, newGoAwayFrame(ErrorCode.NO_ERROR.code, null), new DisconnectFrame());
} }
} }

View File

@ -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(...));
}
}

View File

@ -430,6 +430,7 @@ public class HpackContext
return null; return null;
} }
@Override
public String toString() public String toString()
{ {
return String.format("{%s,%d,%s,%x}",isStatic()?"S":"D",_slot,_field,hashCode()); return String.format("{%s,%d,%s,%x}",isStatic()?"S":"D",_slot,_field,hashCode());

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.http2.hpack; package org.eclipse.jetty.http2.hpack;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.DateGenerator; 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 ServerJetty = new PreEncodedHttpField(HttpHeader.SERVER,"jetty");
final static HttpField XPowerJetty = new PreEncodedHttpField(HttpHeader.X_POWERED_BY,"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 @Test
public void encodeDecodeResponseTest() public void encodeDecodeResponseTest()

View File

@ -12,7 +12,6 @@
<Set name="maxConcurrentStreams"><Property name="jetty.http2.maxConcurrentStreams" default="128"/></Set> <Set name="maxConcurrentStreams"><Property name="jetty.http2.maxConcurrentStreams" default="128"/></Set>
<Set name="initialStreamRecvWindow"><Property name="jetty.http2.initialStreamRecvWindow" default="524288"/></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="initialSessionRecvWindow"><Property name="jetty.http2.initialSessionRecvWindow" default="1048576"/></Set>
<Set name="reservedThreads"><Property name="jetty.http2.reservedThreads" default="-1"/></Set>
</New> </New>
</Arg> </Arg>
</Call> </Call>

View File

@ -27,7 +27,3 @@ etc/jetty-http2.xml
## Initial session receive window (client to server) ## Initial session receive window (client to server)
# jetty.http2.initialSessionRecvWindow=1048576 # jetty.http2.initialSessionRecvWindow=1048576
## Reserve threads for high priority tasks (-1 use number of Selectors, 0 no reserved threads)
# jetty.http2.reservedThreads=-1

View File

@ -35,7 +35,6 @@ import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.Name; import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.thread.ReservedThreadExecutor;
@ManagedObject @ManagedObject
public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
@ -49,7 +48,6 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
private int maxHeaderBlockFragment = 0; private int maxHeaderBlockFragment = 0;
private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F); private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F);
private long streamIdleTimeout; private long streamIdleTimeout;
private int reservedThreads;
public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration) public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
{ {
@ -143,20 +141,24 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
} }
/** /**
* @see ReservedThreadExecutor * @return -1
* @return The number of reserved threads * @deprecated feature removed, no replacement
*/ */
@ManagedAttribute("The number of threads reserved for high priority tasks") @Deprecated
public int getReservedThreads() 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) public void setReservedThreads(int threads)
{ {
// TODO: see also HTTP2Connection.FillableCallback. throw new UnsupportedOperationException();
// TODO: currently disabled since the only value that works is 0.
// this.reservedThreads = threads;
} }
public HttpConfiguration getHttpConfiguration() public HttpConfiguration getHttpConfiguration()
@ -184,29 +186,13 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
session.setStreamIdleTimeout(streamIdleTimeout); session.setStreamIdleTimeout(streamIdleTimeout);
session.setInitialSessionRecvWindow(getInitialSessionRecvWindow()); session.setInitialSessionRecvWindow(getInitialSessionRecvWindow());
ReservedThreadExecutor executor = provideReservedThreadExecutor(connector);
ServerParser parser = newServerParser(connector, session); 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); endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
connection.addListener(connectionListener); connection.addListener(connectionListener);
return configure(connection, connector, endPoint); 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 abstract ServerSessionListener newSessionListener(Connector connector, EndPoint endPoint);
protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener) protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener)

View File

@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jetty.http.BadMessageException; 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.Callback;
import org.eclipse.jetty.util.CountingCallback; import org.eclipse.jetty.util.CountingCallback;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.thread.ReservedThreadExecutor;
public class HTTP2ServerConnection extends HTTP2Connection implements Connection.UpgradeTo public class HTTP2ServerConnection extends HTTP2Connection implements Connection.UpgradeTo
{ {
@ -94,7 +94,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
private final HttpConfiguration httpConfig; private final HttpConfiguration httpConfig;
private boolean recycleHttpChannels; 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); super(byteBufferPool, executor, endPoint, parser, session, inputBufferSize);
this.listener = listener; this.listener = listener;

View File

@ -393,10 +393,8 @@ public class HttpChannelOverHTTP2 extends HttpChannel implements Closeable, Writ
public String toString() public String toString()
{ {
IStream stream = getStream(); IStream stream = getStream();
long streamId = -1; long streamId = stream == null ? -1 : stream.getId();
if (stream != null) return String.format("%s#%d", super.toString(), streamId);
streamId = stream.getId();
return String.format("%s#%d", super.toString(), getStream() == null ? -1 : streamId);
} }
private class FailureTask implements Runnable private class FailureTask implements Runnable

View File

@ -89,6 +89,7 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
Runnable load = new Runnable() Runnable load = new Runnable()
{ {
@Override
public void run () public void run ()
{ {
try try
@ -269,6 +270,7 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
Runnable load = new Runnable() Runnable load = new Runnable()
{ {
@Override
public void run () public void run ()
{ {
try try

Some files were not shown because too many files have changed in this diff Show More