Merge branch 'jetty-9.4.x' of https://github.com/eclipse/jetty.project into jetty-9.4.x
This commit is contained in:
commit
c73352b1f0
|
@ -1,7 +1,7 @@
|
|||
#!groovy
|
||||
|
||||
def jdks = ["jdk8", "jdk9"]
|
||||
def oss = ["linux"] //windows? ,"linux-docker"
|
||||
def jdks = ["jdk8","jdk9","jdk10","jdk11"]
|
||||
def oss = ["linux"]
|
||||
def builds = [:]
|
||||
for (def os in oss) {
|
||||
for (def jdk in jdks) {
|
||||
|
@ -15,8 +15,11 @@ def getFullBuild(jdk, os) {
|
|||
return {
|
||||
node(os) {
|
||||
// System Dependent Locations
|
||||
def mvntool = tool name: 'maven3', type: 'hudson.tasks.Maven$MavenInstallation'
|
||||
def mvntool = tool name: 'maven3.5', type: 'hudson.tasks.Maven$MavenInstallation'
|
||||
def jdktool = tool name: "$jdk", type: 'hudson.model.JDK'
|
||||
def mvnName = 'maven3.5'
|
||||
def localRepo = "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}" // ".repository" //
|
||||
def settingsName = 'oss-settings.xml'
|
||||
|
||||
// Environment
|
||||
List mvnEnv = ["PATH+MVN=${mvntool}/bin", "PATH+JDK=${jdktool}/bin", "JAVA_HOME=${jdktool}/", "MAVEN_HOME=${mvntool}"]
|
||||
|
@ -38,11 +41,11 @@ def getFullBuild(jdk, os) {
|
|||
withEnv(mvnEnv) {
|
||||
timeout(time: 15, unit: 'MINUTES') {
|
||||
withMaven(
|
||||
maven: 'maven3',
|
||||
maven: mvnName,
|
||||
jdk: "$jdk",
|
||||
publisherStrategy: 'EXPLICIT',
|
||||
globalMavenSettingsConfig: 'oss-settings.xml',
|
||||
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") {
|
||||
globalMavenSettingsConfig: settingsName,
|
||||
mavenLocalRepo: localRepo) {
|
||||
sh "mvn -V -B clean install -DskipTests -T6"
|
||||
}
|
||||
|
||||
|
@ -60,12 +63,12 @@ def getFullBuild(jdk, os) {
|
|||
withEnv(mvnEnv) {
|
||||
timeout(time: 20, unit: 'MINUTES') {
|
||||
withMaven(
|
||||
maven: 'maven3',
|
||||
maven: mvnName,
|
||||
jdk: "$jdk",
|
||||
publisherStrategy: 'EXPLICIT',
|
||||
globalMavenSettingsConfig: 'oss-settings.xml',
|
||||
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") {
|
||||
sh "mvn -V -B javadoc:javadoc -T5"
|
||||
globalMavenSettingsConfig: settingsName,
|
||||
mavenLocalRepo: localRepo) {
|
||||
sh "mvn -V -B javadoc:javadoc -T6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,14 +85,12 @@ def getFullBuild(jdk, os) {
|
|||
timeout(time: 90, unit: 'MINUTES') {
|
||||
// Run test phase / ignore test failures
|
||||
withMaven(
|
||||
maven: 'maven3',
|
||||
maven: mvnName,
|
||||
jdk: "$jdk",
|
||||
publisherStrategy: 'EXPLICIT',
|
||||
//options: [invokerPublisher(disabled: false)],
|
||||
globalMavenSettingsConfig: 'oss-settings.xml',
|
||||
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} -Pmongodb"
|
||||
globalMavenSettingsConfig: settingsName,
|
||||
mavenLocalRepo: localRepo) {
|
||||
sh "mvn -V -B install -Dmaven.test.failure.ignore=true -Prun-its -e -Pmongodb -T3"
|
||||
}
|
||||
// withMaven doesn't label..
|
||||
// Report failures in the jenkins UI
|
||||
|
@ -134,17 +135,14 @@ def getFullBuild(jdk, os) {
|
|||
try
|
||||
{
|
||||
stage ("Compact3 - ${jdk}") {
|
||||
|
||||
dir("aggregates/jetty-all-compact3") {
|
||||
withEnv(mvnEnv) {
|
||||
withMaven(
|
||||
maven: 'maven3',
|
||||
jdk: "$jdk",
|
||||
publisherStrategy: 'EXPLICIT',
|
||||
globalMavenSettingsConfig: 'oss-settings.xml',
|
||||
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") {
|
||||
sh "mvn -V -B -Pcompact3 clean install -T5"
|
||||
}
|
||||
withEnv(mvnEnv) {
|
||||
withMaven(
|
||||
maven: mvnName,
|
||||
jdk: "$jdk",
|
||||
publisherStrategy: 'EXPLICIT',
|
||||
globalMavenSettingsConfig: settingsName,
|
||||
mavenLocalRepo: localRepo) {
|
||||
sh "mvn -f aggregates/jetty-all-compact3 -V -B -Pcompact3 clean install -T5"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
==============================================================
|
||||
Jetty Web Container
|
||||
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
|
||||
Copyright 1995-2018 Mort Bay Consulting Pty Ltd.
|
||||
==============================================================
|
||||
|
||||
The Jetty Web Container is Copyright Mort Bay Consulting Pty Ltd
|
||||
|
|
58
VERSION.txt
58
VERSION.txt
|
@ -1,4 +1,56 @@
|
|||
jetty-9.4.10-SNAPSHOT
|
||||
jetty-9.4.11-SNAPSHOT
|
||||
|
||||
jetty-9.4.10.v20180503 - 03 May 2018
|
||||
+ 110 Jetty JAASLoginService should not use getContextClassLoader to load role
|
||||
class name under OSGi
|
||||
+ 1027 MultiPartInputStreamParser is slow for largish files
|
||||
+ 1555 AuthenticationProtocolHandler unable to parse Digest WWW Header
|
||||
+ 2018 No HttpClient API for receiving Server Sent Events
|
||||
+ 2145 Enabled h2, http/1.1 + https failed with invalid preface
|
||||
+ 2152 Produce jetty-home-source artifacts for Eclipse Jetty source jars
|
||||
+ 2164 Ensure all jetty modules that use ServiceLoader have correct OSGi
|
||||
manifest headers
|
||||
+ 2205 100% CPU usage in Selector using Jetty on Windows
|
||||
+ 2311 TimeoutException when server sends unexpected content
|
||||
+ 2337 ServletUpgradeRequest getSubProtocols() creates an ArrayList even if
|
||||
sub protocols is absent in WebSocket Upgrade Request.
|
||||
+ 2349 Review HTTP/2 max streams enforcement
|
||||
+ 2350 Support multiplexing in RoundRobinConnectionPool
|
||||
+ 2361 CachingWebAppClassLoader is not using cache properly
|
||||
+ 2366 Review HTTP/2 interleaving
|
||||
+ 2376 Relax ContextHandler and ServletContextHandler requirements in
|
||||
WebSocket to allow SpringBoot's MockMVC to function
|
||||
+ 2387 NPE in URIUtil.equalsIgnoreEncodings when working with jar:file:// URIs
|
||||
+ 2388 AtomicBiInteger.compareAndSet(long,int,int) not using encoded parameter
|
||||
+ 2391 Allow for optional "\u####" escaping in
|
||||
org.eclipse.jetty.util.ajax.JSON.toString()
|
||||
+ 2398 MultiPartFormInputStream parsing should default to UTF-8, but allowed
|
||||
to be overridden by Request.setCharacterEncoding()
|
||||
+ 2403 allow --add-to-start to specify maven repository location
|
||||
+ 2409 Ensure no duplicate config classes are assigned to WebApps in OSGi
|
||||
environments
|
||||
+ 2413 Server log timestamp is inconsistent
|
||||
+ 2420 Simplify HttpTransportOverHTTP2
|
||||
+ 2425 Review BufferUtil.isMappedBuffer()
|
||||
+ 2427 SessionInactivityTimeout does not stop upon expiration
|
||||
+ 2430 CDI version mismatch with jetty-maven-plugin:run-forked and Weld
|
||||
+ 2435 Class.newInstance() is deprecated in Java 9+
|
||||
+ 2445 Add HttpServletRequest support to DefaultCallbackHandler
|
||||
+ 2446 AttributeNormalizer does not support "user.home" to be "/"
|
||||
+ 2451 ReservedThreadExecutor.getAvailable() is not atomic and can return
|
||||
incorrect value
|
||||
+ 2454 Avoid sending empty DATA frame in case of HTTP/2 trailers
|
||||
+ 2464 NPE when constructing subclasses of ExecutorThreadPool
|
||||
+ 2468 EWYK concurrent produce can fail SSL connections
|
||||
+ 2472 Default Maven Central Repository URL used to download artifacts in
|
||||
start.jar should use https
|
||||
+ 2474 HTTP/2 client not handling invalid servers correctly
|
||||
+ 2478 ThreadPoolExecutor does nto reap Idle threads
|
||||
+ 2482 Possible NPE in MemcachedSessionDataMapFactory
|
||||
+ 2491 WebSocket FragmentExtension can produce an invalid stream of frames
|
||||
+ 2495 FileSessionDataStore: private save method
|
||||
+ 2496 Jetty Maven Plugin should skip execution on projects it cannot support
|
||||
+ 2498 Add QueuedThreadPool.removeThread(Thread) for extendability reasons
|
||||
|
||||
jetty-9.4.9.v20180320 - 20 March 2018
|
||||
+ 347 Avoid sending request using a connection that is idle timing out
|
||||
|
@ -20,8 +72,8 @@ jetty-9.4.9.v20180320 - 20 March 2018
|
|||
+ 1970 ManagedSelector can lose selector thread under high concurrent load
|
||||
+ 1973 Implement minimum response data rate
|
||||
+ 1983 Improve warning for incompatible ALPN processor
|
||||
+ 1986 ServletContextHandler.Context addListener() methods support
|
||||
session listeners
|
||||
+ 1986 ServletContextHandler.Context addListener() methods support session
|
||||
listeners
|
||||
+ 2003 Do not submit blocking tasks as managed selector actions
|
||||
+ 2006 ServletInputStream.isReady not registering interest when it should
|
||||
+ 2010 SniX509ExtendedKeyManager causes exception: "FIPS mode: only SunJSSE
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>apache-jsp</artifactId>
|
||||
|
@ -24,7 +24,7 @@
|
|||
<Export-Package>org.eclipse.jetty.apache.jsp.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}",
|
||||
org.eclipse.jetty.jsp.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}"
|
||||
</Export-Package>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||
<Provide-Capability>osgi.serviceloader;osgi.serviceloader=javax.servlet.ServletContainerInitializer,osgi.serviceloader;osgi.serviceloader=org.apache.juli.logging.Log</Provide-Capability>
|
||||
<_nouses>true</_nouses>
|
||||
</instructions>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>apache-jstl</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>example-async-rest</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.example-async-rest</groupId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>example-async-rest</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.example-async-rest</groupId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.examples</groupId>
|
||||
<artifactId>examples-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.examples</groupId>
|
||||
<artifactId>examples-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -4,13 +4,16 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<groupId>org.eclipse.jetty.examples</groupId>
|
||||
<artifactId>examples-parent</artifactId>
|
||||
<name>Jetty Examples :: Parent</name>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<sonar.skip>true</sonar.skip>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-alpn-client</artifactId>
|
||||
|
@ -24,7 +24,7 @@
|
|||
<configuration>
|
||||
<instructions>
|
||||
<Import-Package>org.eclipse.jetty.alpn;resolution:=optional,*</Import-Package>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)", osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Client)";cardinality:=multiple</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)";resolution:=optional, osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Client)";resolution:=optional;cardinality:=multiple</Require-Capability>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -46,7 +46,7 @@
|
|||
<Bundle-Description>Conscrypt Client ALPN</Bundle-Description>
|
||||
<Import-Package>org.conscrypt;version="${conscrypt.version}",*</Import-Package>
|
||||
<Export-Package>*</Export-Package>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||
<Provide-Capability>osgi.serviceloader; osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Client</Provide-Capability>
|
||||
<_nouses>true</_nouses>
|
||||
</instructions>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -49,7 +49,7 @@
|
|||
<instructions>
|
||||
<Bundle-Description>Conscrypt ALPN</Bundle-Description>
|
||||
<Import-Package>org.conscrypt;version="${conscrypt.version}",*</Import-Package>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||
<Provide-Capability>osgi.serviceloader;osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Server</Provide-Capability>
|
||||
<_nouses>true</_nouses>
|
||||
</instructions>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -35,7 +35,7 @@
|
|||
<instructions>
|
||||
<Bundle-Description>JDK9 Client ALPN</Bundle-Description>
|
||||
<Export-Package>*</Export-Package>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||
<Provide-Capability>osgi.serviceloader; osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Client</Provide-Capability>
|
||||
<_nouses>true</_nouses>
|
||||
</instructions>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -33,7 +33,7 @@
|
|||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-Description>JDK9 Server ALPN</Bundle-Description>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||
<Provide-Capability>osgi.serviceloader;osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Server</Provide-Capability>
|
||||
<_nouses>true</_nouses>
|
||||
</instructions>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -62,7 +62,7 @@
|
|||
<Bundle-Description>OpenJDK8 Client ALPN</Bundle-Description>
|
||||
<Import-Package>org.eclipse.jetty.alpn;version="${alpn.majorVersion}.${alpn.minorVersion}.${alpn.incrementalVersion}",*</Import-Package>
|
||||
<Export-Package>*</Export-Package>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||
<Provide-Capability>osgi.serviceloader; osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Client</Provide-Capability>
|
||||
<_nouses>true</_nouses>
|
||||
</instructions>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -67,7 +67,7 @@
|
|||
<Bundle-Description>OpenJDK8 Server ALPN</Bundle-Description>
|
||||
<Export-Package>*</Export-Package>
|
||||
<Import-Package>org.eclipse.jetty.alpn;version="${alpn.majorVersion}.${alpn.minorVersion}.${alpn.incrementalVersion}",*</Import-Package>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||
<Provide-Capability>osgi.serviceloader; osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Server</Provide-Capability>
|
||||
<_nouses>true</_nouses>
|
||||
</instructions>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-alpn-server</artifactId>
|
||||
|
@ -49,7 +49,7 @@
|
|||
<Bundle-SymbolicName>${bundle-symbolic-name};singleton:=true</Bundle-SymbolicName>
|
||||
<Export-Package>org.eclipse.jetty.alpn.server,*</Export-Package>
|
||||
<Import-Package>org.eclipse.jetty.alpn;version="${alpn.majorVersion}.${alpn.minorVersion}.${alpn.incrementalVersion}",*</Import-Package>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)", osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Server)";resolution:=optional;cardinality:=multiple</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)";resolution:=optional, osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Server)";resolution:=optional;cardinality:=multiple</Require-Capability>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
|
||||
|
||||
[files]
|
||||
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.12.v20180117/alpn-boot-8.1.12.v20180117.jar|lib/alpn/alpn-boot-8.1.12.v20180117.jar
|
||||
|
||||
[exec]
|
||||
-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.12.v20180117.jar
|
|
@ -0,0 +1,7 @@
|
|||
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
|
||||
|
||||
[files]
|
||||
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.12.v20180117/alpn-boot-8.1.12.v20180117.jar|lib/alpn/alpn-boot-8.1.12.v20180117.jar
|
||||
|
||||
[exec]
|
||||
-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.12.v20180117.jar
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-annotations</artifactId>
|
||||
|
@ -21,7 +21,7 @@
|
|||
<configuration>
|
||||
<instructions>
|
||||
<Import-Package>org.objectweb.asm;version="[5.0,7)",*</Import-Package>
|
||||
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=javax.servlet.ServletContainerInitializer)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)"</Require-Capability>
|
||||
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=javax.servlet.ServletContainerInitializer)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)";resolution:=optional</Require-Capability>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-ant</artifactId>
|
||||
|
|
|
@ -47,7 +47,7 @@ public class JettyRunTask extends Task
|
|||
private File tempDirectory;
|
||||
|
||||
/** List of web applications to be deployed. */
|
||||
private List<AntWebAppContext> webapps = new ArrayList<AntWebAppContext>();
|
||||
private List<AntWebAppContext> webapps = new ArrayList<>();
|
||||
|
||||
/** Location of jetty.xml file. */
|
||||
private File jettyXml;
|
||||
|
@ -147,20 +147,17 @@ public class JettyRunTask extends Task
|
|||
{
|
||||
try
|
||||
{
|
||||
this.requestLog = (RequestLog) Class.forName(className).newInstance();
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
throw new BuildException("Request logger instantiation exception: " + e);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new BuildException("Request logger instantiation exception: " + e);
|
||||
this.requestLog = (RequestLog) Class.forName(className).getDeclaredConstructor().newInstance();
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
throw new BuildException("Unknown request logger class: " + className);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new BuildException("Request logger instantiation exception: " + e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getRequestLog()
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<groupId>org.eclipse.jetty</groupId>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-bom</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
<name>Jetty :: Bom</name>
|
||||
<description>Jetty BOM artifact</description>
|
||||
<url>http://www.eclipse.org/jetty</url>
|
||||
|
@ -94,331 +94,331 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>apache-jsp</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>apache-jstl</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-client</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-java-client</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-java-server</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-openjdk8-client</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-openjdk8-server</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-conscrypt-client</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-conscrypt-server</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-server</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-annotations</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-ant</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||
<artifactId>cdi-core</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||
<artifactId>cdi-servlet</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-continuation</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-deploy</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-distribution</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-distribution</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
<type>tar.gz</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||
<artifactId>fcgi-client</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||
<artifactId>fcgi-server</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.gcloud</groupId>
|
||||
<artifactId>jetty-gcloud-session-manager</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-home</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-home</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
<type>tar.gz</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-http</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-client</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-common</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-hpack</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-http-client-transport</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-server</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-http-spi</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-infinispan</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-hazelcast</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jaas</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jaspi</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jmx</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jndi</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.memcached</groupId>
|
||||
<artifactId>jetty-memcached-sessions</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-nosql</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-osgi-boot</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-osgi-boot-jsp</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-osgi-boot-warurl</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-httpservice</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-plus</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-proxy</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-quickstart</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-rewrite</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlets</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-spring</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-unixsocket</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util-ajax</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>javax-websocket-client-impl</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>javax-websocket-server-impl</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-api</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-client</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-common</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-server</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-servlet</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-xml</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||
<artifactId>jetty-cdi-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cdi-2</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||
<artifactId>jetty-cdi-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cdi-core</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||
<artifactId>jetty-cdi-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cdi-full-servlet</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||
<artifactId>jetty-cdi-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cdi-servlet</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||
<artifactId>jetty-cdi-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cdi-websocket</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||
<artifactId>jetty-cdi-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>test-cdi-webapp</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -20,12 +20,14 @@ package org.eclipse.jetty.client;
|
|||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.client.api.Authentication;
|
||||
import org.eclipse.jetty.client.api.Authentication.HeaderInfo;
|
||||
import org.eclipse.jetty.client.api.Connection;
|
||||
import org.eclipse.jetty.client.api.ContentProvider;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
|
@ -35,6 +37,8 @@ import org.eclipse.jetty.client.api.Result;
|
|||
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.QuotedCSV;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
@ -42,7 +46,11 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
|||
{
|
||||
public static final int DEFAULT_MAX_CONTENT_LENGTH = 16*1024;
|
||||
public static final Logger LOG = Log.getLogger(AuthenticationProtocolHandler.class);
|
||||
private static final Pattern AUTHENTICATE_PATTERN = Pattern.compile("([^\\s]+)\\s+realm=\"([^\"]*)\"(.*)", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
private static final Pattern PARAM_PATTERN = Pattern.compile("([^=]+)=([^=]+)?");
|
||||
private static final Pattern TYPE_PATTERN = Pattern.compile("([^\\s]+)(\\s+(.*))?");
|
||||
private static final Pattern MULTIPLE_CHALLENGE_PATTERN = Pattern.compile("(.*?)\\s*,\\s*([^=\\s,]+(\\s+[^=\\s].*)?)");
|
||||
private static final Pattern BASE64_PATTERN = Pattern.compile("[\\+\\-\\.\\/\\dA-Z_a-z~]+=*");
|
||||
|
||||
private final HttpClient client;
|
||||
private final int maxContentLength;
|
||||
|
@ -74,6 +82,80 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
|||
// Return new instances every time to keep track of the response content
|
||||
return new AuthenticationListener();
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected List<HeaderInfo> getHeaderInfo(String value) throws IllegalArgumentException
|
||||
{
|
||||
String header = value;
|
||||
List<HeaderInfo> headerInfos = new ArrayList<>();
|
||||
|
||||
while(true)
|
||||
{
|
||||
Matcher m = MULTIPLE_CHALLENGE_PATTERN.matcher(header);
|
||||
if (m.matches())
|
||||
{
|
||||
headerInfos.add(newHeaderInfo(m.group(1)));
|
||||
header = m.group(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
headerInfos.add(newHeaderInfo(header));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return headerInfos;
|
||||
}
|
||||
|
||||
protected HeaderInfo newHeaderInfo(String value) throws IllegalArgumentException
|
||||
{
|
||||
String type;
|
||||
Map<String,String> params = new HashMap<>();
|
||||
|
||||
Matcher m = TYPE_PATTERN.matcher(value);
|
||||
if (m.matches())
|
||||
{
|
||||
type = m.group(1);
|
||||
if (m.group(2) != null)
|
||||
params = parseParameters(m.group(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid Authentication Format");
|
||||
}
|
||||
|
||||
return new HeaderInfo(getAuthorizationHeader(), type, params);
|
||||
}
|
||||
|
||||
protected Map<String, String> parseParameters(String wwwAuthenticate) throws IllegalArgumentException
|
||||
{
|
||||
Map<String, String> result = new HashMap<>();
|
||||
|
||||
Matcher b64 = BASE64_PATTERN.matcher(wwwAuthenticate);
|
||||
if (b64.matches())
|
||||
{
|
||||
result.put("base64", wwwAuthenticate);
|
||||
return result;
|
||||
}
|
||||
|
||||
QuotedCSV parts = new QuotedCSV(false, wwwAuthenticate);
|
||||
for (String part : parts)
|
||||
{
|
||||
Matcher params = PARAM_PATTERN.matcher(part);
|
||||
if (params.matches())
|
||||
{
|
||||
String name = StringUtil.asciiToLowerCase(params.group(1));
|
||||
String value = (params.group(2)==null) ? "" : params.group(2);
|
||||
result.put(name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid Authentication Format");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private class AuthenticationListener extends BufferingResponseListener
|
||||
{
|
||||
|
@ -234,17 +316,17 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
|||
{
|
||||
// TODO: these should be ordered by strength
|
||||
List<Authentication.HeaderInfo> result = new ArrayList<>();
|
||||
List<String> values = Collections.list(response.getHeaders().getValues(header.asString()));
|
||||
List<String> values = response.getHeaders().getValuesList(header);
|
||||
for (String value : values)
|
||||
{
|
||||
Matcher matcher = AUTHENTICATE_PATTERN.matcher(value);
|
||||
if (matcher.matches())
|
||||
try
|
||||
{
|
||||
String type = matcher.group(1);
|
||||
String realm = matcher.group(2);
|
||||
String params = matcher.group(3);
|
||||
Authentication.HeaderInfo headerInfo = new Authentication.HeaderInfo(type, realm, params, getAuthorizationHeader());
|
||||
result.add(headerInfo);
|
||||
result.addAll(getHeaderInfo(value));
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Failed to parse authentication header", e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -19,9 +19,11 @@
|
|||
package org.eclipse.jetty.client.api;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
||||
/**
|
||||
* {@link Authentication} represents a mechanism to authenticate requests for protected resources.
|
||||
|
@ -76,19 +78,18 @@ public interface Authentication
|
|||
*/
|
||||
public static class HeaderInfo
|
||||
{
|
||||
private final String type;
|
||||
private final String realm;
|
||||
private final String params;
|
||||
private final HttpHeader header;
|
||||
private final String type;
|
||||
private final Map<String,String> params;
|
||||
|
||||
public HeaderInfo(String type, String realm, String params, HttpHeader header)
|
||||
|
||||
public HeaderInfo(HttpHeader header, String type, Map<String,String> params) throws IllegalArgumentException
|
||||
{
|
||||
this.type = type;
|
||||
this.realm = realm;
|
||||
this.params = params;
|
||||
this.header = header;
|
||||
this.type = type;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the authentication type (for example "Basic" or "Digest")
|
||||
*/
|
||||
|
@ -98,20 +99,36 @@ public interface Authentication
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the realm name
|
||||
* @return the realm name or null if there is no realm parameter
|
||||
*/
|
||||
public String getRealm()
|
||||
{
|
||||
return realm;
|
||||
return params.get("realm");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the base64 content as a string if it exists otherwise null
|
||||
*/
|
||||
public String getBase64()
|
||||
{
|
||||
return params.get("base64");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return additional authentication parameters
|
||||
*/
|
||||
public String getParameters()
|
||||
public Map<String, String> getParameters()
|
||||
{
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return specified authentication parameter or null if does not exist
|
||||
*/
|
||||
public String getParameter(String paramName)
|
||||
{
|
||||
return params.get(StringUtil.asciiToLowerCase(paramName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@code Authorization} (or {@code Proxy-Authorization}) header
|
||||
|
|
|
@ -22,15 +22,11 @@ import java.net.URI;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.AuthenticationStore;
|
||||
|
@ -40,6 +36,7 @@ import org.eclipse.jetty.http.HttpHeader;
|
|||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
||||
/**
|
||||
* Implementation of the HTTP "Digest" authentication defined in RFC 2617.
|
||||
|
@ -50,8 +47,6 @@ import org.eclipse.jetty.util.TypeUtil;
|
|||
*/
|
||||
public class DigestAuthentication extends AbstractAuthentication
|
||||
{
|
||||
private static final Pattern PARAM_PATTERN = Pattern.compile("([^=]+)=(.*)");
|
||||
|
||||
private final String user;
|
||||
private final String password;
|
||||
|
||||
|
@ -74,10 +69,21 @@ public class DigestAuthentication extends AbstractAuthentication
|
|||
return "Digest";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matches(String type, URI uri, String realm)
|
||||
{
|
||||
// digest authenication requires a realm
|
||||
if (realm == null)
|
||||
return false;
|
||||
|
||||
return super.matches(type,uri,realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result authenticate(Request request, ContentResponse response, HeaderInfo headerInfo, Attributes context)
|
||||
{
|
||||
Map<String, String> params = parseParameters(headerInfo.getParameters());
|
||||
Map<String, String> params = headerInfo.getParameters();
|
||||
String nonce = params.get("nonce");
|
||||
if (nonce == null || nonce.length() == 0)
|
||||
return null;
|
||||
|
@ -105,58 +111,6 @@ public class DigestAuthentication extends AbstractAuthentication
|
|||
return new DigestResult(headerInfo.getHeader(), response.getContent(), realm, user, password, algorithm, nonce, clientQOP, opaque);
|
||||
}
|
||||
|
||||
private Map<String, String> parseParameters(String wwwAuthenticate)
|
||||
{
|
||||
Map<String, String> result = new HashMap<>();
|
||||
List<String> parts = splitParams(wwwAuthenticate);
|
||||
for (String part : parts)
|
||||
{
|
||||
Matcher matcher = PARAM_PATTERN.matcher(part);
|
||||
if (matcher.matches())
|
||||
{
|
||||
String name = matcher.group(1).trim().toLowerCase(Locale.ENGLISH);
|
||||
String value = matcher.group(2).trim();
|
||||
if (value.startsWith("\"") && value.endsWith("\""))
|
||||
value = value.substring(1, value.length() - 1);
|
||||
result.put(name, value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<String> splitParams(String paramString)
|
||||
{
|
||||
List<String> result = new ArrayList<>();
|
||||
int start = 0;
|
||||
for (int i = 0; i < paramString.length(); ++i)
|
||||
{
|
||||
int quotes = 0;
|
||||
char ch = paramString.charAt(i);
|
||||
switch (ch)
|
||||
{
|
||||
case '\\':
|
||||
++i;
|
||||
break;
|
||||
case '"':
|
||||
++quotes;
|
||||
break;
|
||||
case ',':
|
||||
if (quotes % 2 == 0)
|
||||
{
|
||||
String element = paramString.substring(start, i).trim();
|
||||
if (element.length() > 0)
|
||||
result.add(element);
|
||||
start = i + 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.add(paramString.substring(start, paramString.length()).trim());
|
||||
return result;
|
||||
}
|
||||
|
||||
private MessageDigest getMessageDigest(String algorithm)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.io.IOException;
|
|||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -43,6 +44,7 @@ import org.eclipse.jetty.client.api.Request;
|
|||
import org.eclipse.jetty.client.api.Response;
|
||||
import org.eclipse.jetty.client.api.Response.Listener;
|
||||
import org.eclipse.jetty.client.api.Result;
|
||||
import org.eclipse.jetty.client.api.Authentication.HeaderInfo;
|
||||
import org.eclipse.jetty.client.util.BasicAuthentication;
|
||||
import org.eclipse.jetty.client.util.DeferredContentProvider;
|
||||
import org.eclipse.jetty.client.util.DigestAuthentication;
|
||||
|
@ -63,6 +65,7 @@ import org.eclipse.jetty.util.IO;
|
|||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.security.Constraint;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -613,4 +616,120 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTestHeaderInfoParsing() {
|
||||
AuthenticationProtocolHandler aph = new WWWAuthenticationProtocolHandler(client);
|
||||
|
||||
HeaderInfo headerInfo = aph.getHeaderInfo("Digest realm=\"thermostat\", qop=\"auth\", nonce=\"1523430383\"").get(0);
|
||||
Assert.assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||
Assert.assertTrue(headerInfo.getParameter("qop").equals("auth"));
|
||||
Assert.assertTrue(headerInfo.getParameter("realm").equals("thermostat"));
|
||||
Assert.assertTrue(headerInfo.getParameter("nonce").equals("1523430383"));
|
||||
|
||||
headerInfo = aph.getHeaderInfo("Digest qop=\"auth\", realm=\"thermostat\", nonce=\"1523430383\"").get(0);
|
||||
Assert.assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||
Assert.assertTrue(headerInfo.getParameter("qop").equals("auth"));
|
||||
Assert.assertTrue(headerInfo.getParameter("realm").equals("thermostat"));
|
||||
Assert.assertTrue(headerInfo.getParameter("nonce").equals("1523430383"));
|
||||
|
||||
headerInfo = aph.getHeaderInfo("Digest qop=\"auth\", nonce=\"1523430383\", realm=\"thermostat\"").get(0);
|
||||
Assert.assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||
Assert.assertTrue(headerInfo.getParameter("qop").equals("auth"));
|
||||
Assert.assertTrue(headerInfo.getParameter("realm").equals("thermostat"));
|
||||
Assert.assertTrue(headerInfo.getParameter("nonce").equals("1523430383"));
|
||||
|
||||
headerInfo = aph.getHeaderInfo("Digest qop=\"auth\", nonce=\"1523430383\"").get(0);
|
||||
Assert.assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||
Assert.assertTrue(headerInfo.getParameter("qop").equals("auth"));
|
||||
Assert.assertTrue(headerInfo.getParameter("realm") == null);
|
||||
Assert.assertTrue(headerInfo.getParameter("nonce").equals("1523430383"));
|
||||
|
||||
|
||||
// test multiple authentications
|
||||
List<HeaderInfo> headerInfoList = aph.getHeaderInfo("Digest qop=\"auth\", realm=\"thermostat\", nonce=\"1523430383\", "
|
||||
+ "Digest realm=\"thermostat2\", qop=\"auth2\", nonce=\"4522530354\", "
|
||||
+ "Digest qop=\"auth3\", nonce=\"9523570528\", realm=\"thermostat3\", "
|
||||
+ "Digest qop=\"auth4\", nonce=\"3526435321\"");
|
||||
|
||||
Assert.assertTrue(headerInfoList.get(0).getType().equalsIgnoreCase("Digest"));
|
||||
Assert.assertTrue(headerInfoList.get(0).getParameter("qop").equals("auth"));
|
||||
Assert.assertTrue(headerInfoList.get(0).getParameter("realm").equals("thermostat"));
|
||||
Assert.assertTrue(headerInfoList.get(0).getParameter("nonce").equals("1523430383"));
|
||||
|
||||
Assert.assertTrue(headerInfoList.get(1).getType().equalsIgnoreCase("Digest"));
|
||||
Assert.assertTrue(headerInfoList.get(1).getParameter("qop").equals("auth2"));
|
||||
Assert.assertTrue(headerInfoList.get(1).getParameter("realm").equals("thermostat2"));
|
||||
Assert.assertTrue(headerInfoList.get(1).getParameter("nonce").equals("4522530354"));
|
||||
|
||||
Assert.assertTrue(headerInfoList.get(2).getType().equalsIgnoreCase("Digest"));
|
||||
Assert.assertTrue(headerInfoList.get(2).getParameter("qop").equals("auth3"));
|
||||
Assert.assertTrue(headerInfoList.get(2).getParameter("realm").equals("thermostat3"));
|
||||
Assert.assertTrue(headerInfoList.get(2).getParameter("nonce").equals("9523570528"));
|
||||
|
||||
Assert.assertTrue(headerInfoList.get(3).getType().equalsIgnoreCase("Digest"));
|
||||
Assert.assertTrue(headerInfoList.get(3).getParameter("qop").equals("auth4"));
|
||||
Assert.assertTrue(headerInfoList.get(3).getParameter("realm") == null);
|
||||
Assert.assertTrue(headerInfoList.get(3).getParameter("nonce").equals("3526435321"));
|
||||
|
||||
List<HeaderInfo> headerInfos = aph.getHeaderInfo("Newauth realm=\"apps\", type=1, title=\"Login to \\\"apps\\\"\", Basic realm=\"simple\"");
|
||||
Assert.assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Newauth"));
|
||||
Assert.assertTrue(headerInfos.get(0).getParameter("realm").equals("apps"));
|
||||
Assert.assertTrue(headerInfos.get(0).getParameter("type").equals("1"));
|
||||
Assert.assertThat(headerInfos.get(0).getParameter("title"), Matchers.equalTo("Login to \"apps\""));
|
||||
Assert.assertTrue(headerInfos.get(1).getType().equalsIgnoreCase("Basic"));
|
||||
Assert.assertTrue(headerInfos.get(1).getParameter("realm").equals("simple"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTestHeaderInfoParsingUnusualCases() {
|
||||
AuthenticationProtocolHandler aph = new WWWAuthenticationProtocolHandler(client);
|
||||
|
||||
HeaderInfo headerInfo = aph.getHeaderInfo("Scheme").get(0);
|
||||
Assert.assertTrue(headerInfo.getType().equalsIgnoreCase("Scheme"));
|
||||
Assert.assertTrue(headerInfo.getParameter("realm") == null);
|
||||
|
||||
List<HeaderInfo> headerInfos = aph.getHeaderInfo("Scheme1 , Scheme2 , Scheme3");
|
||||
Assert.assertEquals(3, headerInfos.size());
|
||||
Assert.assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Scheme1"));
|
||||
Assert.assertTrue(headerInfos.get(1).getType().equalsIgnoreCase("Scheme2"));
|
||||
Assert.assertTrue(headerInfos.get(2).getType().equalsIgnoreCase("Scheme3"));
|
||||
|
||||
headerInfo = aph.getHeaderInfo("Scheme name=\"value\", other=\"value2\"").get(0);
|
||||
Assert.assertTrue(headerInfo.getType().equalsIgnoreCase("Scheme"));
|
||||
Assert.assertTrue(headerInfo.getParameter("name").equals("value"));
|
||||
Assert.assertTrue(headerInfo.getParameter("other").equals("value2"));
|
||||
|
||||
headerInfo = aph.getHeaderInfo("Scheme name = value , other = \"value2\" ").get(0);
|
||||
Assert.assertTrue(headerInfo.getType().equalsIgnoreCase("Scheme"));
|
||||
Assert.assertTrue(headerInfo.getParameter("name").equals("value"));
|
||||
Assert.assertTrue(headerInfo.getParameter("other").equals("value2"));
|
||||
|
||||
headerInfos = aph.getHeaderInfo("Scheme name=value, Scheme2 name=value2");
|
||||
Assert.assertEquals(headerInfos.size(), 2);
|
||||
Assert.assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Scheme"));
|
||||
Assert.assertTrue(headerInfos.get(0).getParameter("nAmE").equals("value"));
|
||||
Assert.assertThat(headerInfos.get(1).getType(), Matchers.equalToIgnoringCase("Scheme2"));
|
||||
Assert.assertTrue(headerInfos.get(1).getParameter("nAmE").equals("value2"));
|
||||
|
||||
headerInfos = aph.getHeaderInfo("Scheme , ,, ,, name=value, Scheme2 name=value2");
|
||||
Assert.assertEquals(headerInfos.size(), 2);
|
||||
Assert.assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Scheme"));
|
||||
Assert.assertTrue(headerInfos.get(0).getParameter("name").equals("value"));
|
||||
Assert.assertTrue(headerInfos.get(1).getType().equalsIgnoreCase("Scheme2"));
|
||||
Assert.assertTrue(headerInfos.get(1).getParameter("name").equals("value2"));
|
||||
|
||||
//Negotiate with base64 Content
|
||||
headerInfo = aph.getHeaderInfo("Negotiate TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFAs4OAAAADw==").get(0);
|
||||
Assert.assertTrue(headerInfo.getType().equalsIgnoreCase("Negotiate"));
|
||||
Assert.assertTrue(headerInfo.getBase64().equals("TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFAs4OAAAADw=="));
|
||||
|
||||
headerInfos = aph.getHeaderInfo("Negotiate TlRMTVNTUAABAAAAAAAAAFAs4OAAAADw==, "
|
||||
+ "Negotiate YIIJvwYGKwYBBQUCoIIJszCCCa+gJDAi=");
|
||||
Assert.assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Negotiate"));
|
||||
Assert.assertTrue(headerInfos.get(0).getBase64().equals("TlRMTVNTUAABAAAAAAAAAFAs4OAAAADw=="));
|
||||
|
||||
Assert.assertTrue(headerInfos.get(1).getType().equalsIgnoreCase("Negotiate"));
|
||||
Assert.assertTrue(headerInfos.get(1).getBase64().equals("YIIJvwYGKwYBBQUCoIIJszCCCa+gJDAi="));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-continuation</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-deploy</artifactId>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-distribution</artifactId>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>jetty-documentation</artifactId>
|
||||
<name>Jetty :: Documentation</name>
|
||||
|
|
|
@ -344,6 +344,8 @@ The ALPN implementation, relying on modifications of OpenJDK classes, updates ev
|
|||
|1.8.0u152 |8.1.11.v20170118
|
||||
|1.8.0u161 |8.1.12.v20180117
|
||||
|1.8.0u162 |8.1.12.v20180117
|
||||
|1.8.0u171 |8.1.12.v20180117
|
||||
|1.8.0u172 |8.1.12.v20180117
|
||||
|=============================
|
||||
|
||||
[[alpn-build]]
|
||||
|
|
|
@ -258,3 +258,7 @@ This allows for some complex hierarchies of configuration details.
|
|||
If the file does not exist at the given location, download it from the given http URI.
|
||||
Note: location is always relative to `${jetty.base}`.
|
||||
You might need to escape the slash "\|" to use this on some environments.
|
||||
|
||||
maven.repo.uri=[url]::
|
||||
The url to use to download Maven dependencies.
|
||||
Default is http://central.maven.org/maven2/.
|
||||
|
|
|
@ -377,11 +377,15 @@ The `AbstractLoginModule` does not support any caching, so if you want to cache
|
|||
|
||||
==== Other Goodies
|
||||
|
||||
===== ServletRequestCallback
|
||||
|
||||
This callback gives you access to the ServletRequest that is involved in the authentication, and thus to other features like the current Session. This callback can be configured in your custom LoginModule implementation. Note that none of the LoginModule implementations provided with Jetty currently use this callback.
|
||||
|
||||
===== RequestParameterCallback
|
||||
|
||||
As all servlet containers intercept and process a form submission with action `j_security_check`, it is usually not possible to insert any extra input fields onto a login form with which to perform authentication: you may only pass `j_username` and `j_password`.
|
||||
For those rare occasions when this is not good enough, and you require more information from the user in order to authenticate them, you can use the JAAS callback handler `org.eclipse.jetty.jaas.callback.RequestParameterCallback`.
|
||||
This callback handler gives you access to all parameters that were passed in the form submission.
|
||||
This callback gives you access to all parameters that were passed in the form submission.
|
||||
To use it, in the `login()` method of your custom login module, add the `RequestParameterCallback` to the list of callback handlers the login module uses, tell it which params you are interested in, and then get the value of the parameter back.
|
||||
Here is an example:
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<copyright>
|
||||
<year>1995-2017</year>
|
||||
<year>1995-2018</year>
|
||||
<holder>Mort Bay Consulting Pty. Ltd.</holder>
|
||||
</copyright>
|
||||
<revhistory>
|
||||
|
|
|
@ -100,7 +100,7 @@ To test a Jetty release, complete the following steps for each release you want
|
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<jetty-version>7.6.2.v20120308</jetty-version>
|
||||
<jetty-plugin-version>${jetty-version}</jetty-plugin-version>
|
||||
<slf4j-version>1.6.4</slf4j-version>
|
||||
<slf4j.version>1.6.4</slf4j.version>
|
||||
<spring-version>3.1.0.RELEASE</spring-version>
|
||||
</properties>
|
||||
<repositories>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||
<artifactId>fcgi-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||
<artifactId>fcgi-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.gcloud</groupId>
|
||||
<artifactId>gcloud-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-home</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-http-spi</artifactId>
|
||||
|
@ -52,7 +52,7 @@
|
|||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-Description>Jetty Http SPI</Bundle-Description>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||
<Provide-Capability>osgi.serviceloader; osgi.serviceloader=com.sun.net.httpserver.spi.HttpServerProvider</Provide-Capability>
|
||||
<_nouses>true</_nouses>
|
||||
</instructions>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-http</artifactId>
|
||||
|
@ -55,9 +55,6 @@
|
|||
<configuration>
|
||||
<instructions>
|
||||
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.http.HttpFieldPreEncoder)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)";resolution:=optional, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||
<!--
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||
-->
|
||||
<Provide-Capability>osgi.serviceloader; osgi.serviceloader=org.eclipse.jetty.http.HttpFieldPreEncoder</Provide-Capability>
|
||||
</instructions>
|
||||
</configuration>
|
||||
|
|
|
@ -101,7 +101,7 @@ public class PreEncodedHttpField extends HttpField
|
|||
{
|
||||
super(header,name, value);
|
||||
for (int i=0;i<__encoders.length;i++)
|
||||
_encodedField[i]=__encoders[i].getEncodedField(header,header.asString(),value);
|
||||
_encodedField[i]=__encoders[i].getEncodedField(header,name,value);
|
||||
}
|
||||
|
||||
public PreEncodedHttpField(HttpHeader header,String value)
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.http;
|
|||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
@ -181,4 +182,14 @@ public class HttpFieldTest
|
|||
|
||||
assertEquals("Accept: something\r\n",s);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCachedFieldWithHeaderName()
|
||||
{
|
||||
PreEncodedHttpField field = new PreEncodedHttpField("X-My-Custom-Header", "something");
|
||||
|
||||
assertNull(field.getHeader());
|
||||
assertEquals("X-My-Custom-Header", field.getName());
|
||||
assertEquals("something", field.getValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -129,11 +129,12 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
|||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
super.onOpen();
|
||||
promise.succeeded(getSession());
|
||||
// Only start reading from server after we have sent the client preface,
|
||||
// otherwise we risk to read the server preface (a SETTINGS frame) and
|
||||
// reply to that before we have the chance to send the client preface.
|
||||
super.onOpen();
|
||||
promise.succeeded(getSession());
|
||||
produce();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -69,7 +69,6 @@ import org.eclipse.jetty.util.Promise;
|
|||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -314,7 +313,7 @@ public abstract class FlowControlStrategyTest
|
|||
{
|
||||
final int windowSize = 1536;
|
||||
final int length = 5 * windowSize;
|
||||
final CountDownLatch settingsLatch = new CountDownLatch(1);
|
||||
final CountDownLatch settingsLatch = new CountDownLatch(2);
|
||||
start(new ServerSessionListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
|
@ -343,7 +342,9 @@ public abstract class FlowControlStrategyTest
|
|||
|
||||
Map<Integer, Integer> settings = new HashMap<>();
|
||||
settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, windowSize);
|
||||
session.settings(new SettingsFrame(settings, false), Callback.NOOP);
|
||||
Callback.Completable completable = new Callback.Completable();
|
||||
session.settings(new SettingsFrame(settings, false), completable);
|
||||
completable.thenRun(settingsLatch::countDown);
|
||||
|
||||
Assert.assertTrue(settingsLatch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
|
@ -661,88 +662,6 @@ public abstract class FlowControlStrategyTest
|
|||
Assert.assertArrayEquals(data, bytes);
|
||||
}
|
||||
|
||||
// TODO
|
||||
// Since we changed the API to disallow consecutive data() calls without waiting
|
||||
// for the callback, it is now not possible to have DATA1, DATA2 in the queue for
|
||||
// the same stream. Perhaps this test should just be deleted.
|
||||
@Ignore
|
||||
@Test
|
||||
public void testServerTwoDataFramesWithStalledStream() throws Exception
|
||||
{
|
||||
// Frames in queue = DATA1, DATA2.
|
||||
// Server writes part of DATA1, then stalls.
|
||||
// A window update unstalls the session, verify that the data is correctly sent.
|
||||
|
||||
Random random = new Random();
|
||||
final byte[] chunk1 = new byte[1024];
|
||||
random.nextBytes(chunk1);
|
||||
final byte[] chunk2 = new byte[2048];
|
||||
random.nextBytes(chunk2);
|
||||
|
||||
// Two SETTINGS frames: the initial after the preface,
|
||||
// and the explicit where we set the stream window size to zero.
|
||||
final AtomicReference<CountDownLatch> settingsLatch = new AtomicReference<>(new CountDownLatch(2));
|
||||
final CountDownLatch dataLatch = new CountDownLatch(1);
|
||||
start(new ServerSessionListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onSettings(Session session, SettingsFrame frame)
|
||||
{
|
||||
settingsLatch.get().countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
stream.data(new DataFrame(stream.getId(), ByteBuffer.wrap(chunk1), false), Callback.NOOP);
|
||||
stream.data(new DataFrame(stream.getId(), ByteBuffer.wrap(chunk2), true), Callback.NOOP);
|
||||
dataLatch.countDown();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
Session session = newClient(new Session.Listener.Adapter());
|
||||
Map<Integer, Integer> settings = new HashMap<>();
|
||||
settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, 0);
|
||||
session.settings(new SettingsFrame(settings, false), Callback.NOOP);
|
||||
Assert.assertTrue(settingsLatch.get().await(5, TimeUnit.SECONDS));
|
||||
|
||||
byte[] content = new byte[chunk1.length + chunk2.length];
|
||||
final ByteBuffer buffer = ByteBuffer.wrap(content);
|
||||
MetaData.Request metaData = newRequest("GET", new HttpFields());
|
||||
HeadersFrame requestFrame = new HeadersFrame(metaData, null, true);
|
||||
final CountDownLatch responseLatch = new CountDownLatch(1);
|
||||
session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onData(Stream stream, DataFrame frame, Callback callback)
|
||||
{
|
||||
buffer.put(frame.getData());
|
||||
callback.succeeded();
|
||||
if (frame.isEndStream())
|
||||
responseLatch.countDown();
|
||||
}
|
||||
});
|
||||
Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
// Now we have the 2 DATA frames queued in the server.
|
||||
|
||||
// Unstall the stream window.
|
||||
settingsLatch.set(new CountDownLatch(1));
|
||||
settings.clear();
|
||||
settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, chunk1.length / 2);
|
||||
session.settings(new SettingsFrame(settings, false), Callback.NOOP);
|
||||
Assert.assertTrue(settingsLatch.get().await(5, TimeUnit.SECONDS));
|
||||
|
||||
Assert.assertTrue(responseLatch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
// Check that the data is sent correctly.
|
||||
byte[] expected = new byte[content.length];
|
||||
System.arraycopy(chunk1, 0, expected, 0, chunk1.length);
|
||||
System.arraycopy(chunk2, 0, expected, chunk1.length, chunk2.length);
|
||||
Assert.assertArrayEquals(expected, content);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientSendingInitialSmallWindow() throws Exception
|
||||
{
|
||||
|
|
|
@ -236,7 +236,7 @@ public class HTTP2Test extends AbstractTest
|
|||
});
|
||||
}
|
||||
|
||||
Assert.assertTrue(latch.await(requests, TimeUnit.SECONDS));
|
||||
Assert.assertTrue(server.dump() + System.lineSeparator() + client.dump(), latch.await(requests, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.client;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.http2.api.Session;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class InvalidServerTest extends AbstractTest
|
||||
{
|
||||
@Test
|
||||
public void testInvalidPreface() throws Exception
|
||||
{
|
||||
try (ServerSocket server = new ServerSocket(0))
|
||||
{
|
||||
prepareClient();
|
||||
client.start();
|
||||
|
||||
CountDownLatch failureLatch = new CountDownLatch(1);
|
||||
Promise.Completable<Session> promise = new Promise.Completable<>();
|
||||
InetSocketAddress address = new InetSocketAddress("localhost", server.getLocalPort());
|
||||
client.connect(address, new Session.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onFailure(Session session, Throwable failure)
|
||||
{
|
||||
failureLatch.countDown();
|
||||
}
|
||||
}, promise);
|
||||
|
||||
Socket socket = server.accept();
|
||||
OutputStream output = socket.getOutputStream();
|
||||
output.write("enough_junk_bytes".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
Session session = promise.get(5, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(session);
|
||||
|
||||
Assert.assertTrue(failureLatch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
// Verify that the client closed the socket.
|
||||
InputStream input = socket.getInputStream();
|
||||
while (true)
|
||||
{
|
||||
int read = input.read();
|
||||
if (read < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -263,6 +263,14 @@ public class RawHTTP2ProxyTest
|
|||
Assert.assertTrue(latch2.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
private static DataFrame copyDataFrame(DataFrame frame)
|
||||
{
|
||||
ByteBuffer data = frame.getData();
|
||||
ByteBuffer dataCopy = ByteBuffer.allocate(data.remaining());
|
||||
dataCopy.put(data).flip();
|
||||
return new DataFrame(frame.getStreamId(), dataCopy, frame.isEndStream(), frame.padding());
|
||||
}
|
||||
|
||||
private static class ClientToProxySessionListener extends ServerSessionListener.Adapter
|
||||
{
|
||||
private final Map<Integer, ClientToProxyToServer> forwarders = new ConcurrentHashMap<>();
|
||||
|
@ -497,7 +505,8 @@ public class RawHTTP2ProxyTest
|
|||
{
|
||||
if (LOGGER.isDebugEnabled())
|
||||
LOGGER.debug("CPS received {} on {}", frame, stream);
|
||||
offer(stream, frame, callback);
|
||||
// Must copy the bytes because they are not consumed here.
|
||||
offer(stream, copyDataFrame(frame), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -659,7 +668,8 @@ public class RawHTTP2ProxyTest
|
|||
{
|
||||
if (LOGGER.isDebugEnabled())
|
||||
LOGGER.debug("SPC received {} on {}", frame, stream);
|
||||
offer(stream, frame, callback);
|
||||
// Must copy the bytes because they are not consumed here.
|
||||
offer(stream, copyDataFrame(frame), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -20,6 +20,9 @@ package org.eclipse.jetty.http2.client;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -37,11 +40,14 @@ import org.eclipse.jetty.http2.api.Session;
|
|||
import org.eclipse.jetty.http2.api.Stream;
|
||||
import org.eclipse.jetty.http2.api.server.ServerSessionListener;
|
||||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
import org.eclipse.jetty.http2.frames.Frame;
|
||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.FuturePromise;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -223,4 +229,62 @@ public class TrailersTest extends AbstractTest
|
|||
|
||||
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrailersSentByServerShouldNotSendEmptyDataFrame() throws Exception
|
||||
{
|
||||
String trailerName = "X-Trailer";
|
||||
String trailerValue = "Zot!";
|
||||
start(new EmptyHttpServlet()
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
Request jettyRequest = (Request)request;
|
||||
Response jettyResponse = jettyRequest.getResponse();
|
||||
HttpFields trailers = new HttpFields();
|
||||
jettyResponse.setTrailers(() -> trailers);
|
||||
|
||||
jettyResponse.getOutputStream().write("hello_trailers".getBytes(StandardCharsets.UTF_8));
|
||||
jettyResponse.flushBuffer();
|
||||
// Force the content to be sent above, and then only send the trailers below.
|
||||
trailers.put(trailerName, trailerValue);
|
||||
}
|
||||
});
|
||||
|
||||
Session session = newClient(new Session.Listener.Adapter());
|
||||
MetaData.Request request = newRequest("GET", new HttpFields());
|
||||
HeadersFrame requestFrame = new HeadersFrame(request, null, true);
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
List<Frame> frames = new ArrayList<>();
|
||||
session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
frames.add(frame);
|
||||
if (frame.isEndStream())
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onData(Stream stream, DataFrame frame, Callback callback)
|
||||
{
|
||||
frames.add(frame);
|
||||
callback.succeeded();
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
|
||||
Assert.assertThat(frames.toString(), frames.size(), Matchers.is(3));
|
||||
|
||||
HeadersFrame headers = (HeadersFrame)frames.get(0);
|
||||
DataFrame data = (DataFrame)frames.get(1);
|
||||
HeadersFrame trailers = (HeadersFrame)frames.get(2);
|
||||
|
||||
Assert.assertFalse(headers.isEndStream());
|
||||
Assert.assertFalse(data.isEndStream());
|
||||
Assert.assertTrue(trailers.isEndStream());
|
||||
Assert.assertThat(trailers.getMetaData().getFields().get(trailerName), Matchers.equalTo(trailerValue));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -103,7 +103,6 @@ public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
|
|||
|
||||
float ratio = bufferRatio;
|
||||
|
||||
WindowUpdateFrame windowFrame = null;
|
||||
int level = sessionLevel.addAndGet(length);
|
||||
int maxLevel = (int)(maxSessionRecvWindow.get() * ratio);
|
||||
if (level > maxLevel)
|
||||
|
@ -113,7 +112,7 @@ public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
|
|||
session.updateRecvWindow(level);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Data consumed, {} bytes, updated session recv window by {}/{} for {}", length, level, maxLevel, session);
|
||||
windowFrame = new WindowUpdateFrame(0, level);
|
||||
session.frames(null, Callback.NOOP, new WindowUpdateFrame(0, level), Frame.EMPTY_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -127,7 +126,6 @@ public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
|
|||
LOG.debug("Data consumed, {} bytes, session recv window level {}/{} for {}", length, level, maxLevel, session);
|
||||
}
|
||||
|
||||
Frame[] windowFrames = Frame.EMPTY_ARRAY;
|
||||
if (stream != null)
|
||||
{
|
||||
if (stream.isRemotelyClosed())
|
||||
|
@ -148,11 +146,7 @@ public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
|
|||
stream.updateRecvWindow(level);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Data consumed, {} bytes, updated stream recv window by {}/{} for {}", length, level, maxLevel, stream);
|
||||
WindowUpdateFrame frame = new WindowUpdateFrame(stream.getId(), level);
|
||||
if (windowFrame == null)
|
||||
windowFrame = frame;
|
||||
else
|
||||
windowFrames = new Frame[]{frame};
|
||||
session.frames(stream, Callback.NOOP, new WindowUpdateFrame(stream.getId(), level), Frame.EMPTY_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -162,9 +156,6 @@ public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (windowFrame != null)
|
||||
session.frames(stream, Callback.NOOP, windowFrame, windowFrames);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -101,7 +101,6 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("HTTP2 Open {} ", this);
|
||||
super.onOpen();
|
||||
strategy.produce();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -119,7 +118,7 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("HTTP2 onFillable {} ", this);
|
||||
strategy.produce();
|
||||
produce();
|
||||
}
|
||||
|
||||
private int fill(EndPoint endPoint, ByteBuffer buffer)
|
||||
|
@ -154,9 +153,23 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
{
|
||||
offerTask(task);
|
||||
if (dispatch)
|
||||
strategy.dispatch();
|
||||
dispatch();
|
||||
else
|
||||
strategy.produce();
|
||||
produce();
|
||||
}
|
||||
|
||||
protected void produce()
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("HTTP2 produce {} ", this);
|
||||
strategy.produce();
|
||||
}
|
||||
|
||||
protected void dispatch()
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("HTTP2 dispatch {} ", this);
|
||||
strategy.dispatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -186,8 +199,7 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
@Override
|
||||
public void onFlushed(long bytes) throws IOException
|
||||
{
|
||||
// TODO: add method to ISession ?
|
||||
((HTTP2Session)session).onFlushed(bytes);
|
||||
session.onFlushed(bytes);
|
||||
}
|
||||
|
||||
protected class HTTP2Producer implements ExecutionStrategy.Producer
|
||||
|
|
|
@ -21,16 +21,17 @@ package org.eclipse.jetty.http2;
|
|||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.http2.frames.Frame;
|
||||
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.EofException;
|
||||
import org.eclipse.jetty.io.WriteFlusher;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.IteratingCallback;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
|
@ -41,15 +42,16 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(HTTP2Flusher.class);
|
||||
private static final ByteBuffer[] EMPTY_BYTE_BUFFERS = new ByteBuffer[0];
|
||||
|
||||
private final Queue<WindowEntry> windows = new ArrayDeque<>();
|
||||
private final Deque<Entry> frames = new ArrayDeque<>();
|
||||
private final Queue<Entry> entries = new ArrayDeque<>();
|
||||
private final List<Entry> actives = new ArrayList<>();
|
||||
private final Deque<Entry> entries = new ArrayDeque<>();
|
||||
private final Queue<Entry> pendingEntries = new ArrayDeque<>();
|
||||
private final Set<Entry> processedEntries = new HashSet<>();
|
||||
private final HTTP2Session session;
|
||||
private final ByteBufferPool.Lease lease;
|
||||
private Entry stalled;
|
||||
private Throwable terminated;
|
||||
private Entry stalledEntry;
|
||||
|
||||
public HTTP2Flusher(HTTP2Session session)
|
||||
{
|
||||
|
@ -79,9 +81,9 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
closed = terminated;
|
||||
if (closed == null)
|
||||
{
|
||||
frames.offerFirst(entry);
|
||||
entries.offerFirst(entry);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Prepended {}, frames={}", entry, frames.size());
|
||||
LOG.debug("Prepended {}, entries={}", entry, entries.size());
|
||||
}
|
||||
}
|
||||
if (closed == null)
|
||||
|
@ -98,9 +100,9 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
closed = terminated;
|
||||
if (closed == null)
|
||||
{
|
||||
frames.offer(entry);
|
||||
entries.offer(entry);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Appended {}, frames={}", entry, frames.size());
|
||||
LOG.debug("Appended {}, entries={}", entry, entries.size());
|
||||
}
|
||||
}
|
||||
if (closed == null)
|
||||
|
@ -121,7 +123,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
{
|
||||
synchronized (this)
|
||||
{
|
||||
return frames.size();
|
||||
return entries.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,143 +138,158 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
if (terminated != null)
|
||||
throw terminated;
|
||||
|
||||
while (!windows.isEmpty())
|
||||
{
|
||||
WindowEntry entry = windows.poll();
|
||||
entry.perform();
|
||||
}
|
||||
WindowEntry windowEntry;
|
||||
while ((windowEntry = windows.poll()) != null)
|
||||
windowEntry.perform();
|
||||
|
||||
for (Entry entry : frames)
|
||||
{
|
||||
entries.offer(entry);
|
||||
actives.add(entry);
|
||||
}
|
||||
frames.clear();
|
||||
Entry entry;
|
||||
while ((entry = entries.poll()) != null)
|
||||
pendingEntries.offer(entry);
|
||||
}
|
||||
|
||||
|
||||
if (entries.isEmpty())
|
||||
if (pendingEntries.isEmpty())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Flushed {}", session);
|
||||
return Action.IDLE;
|
||||
}
|
||||
|
||||
while (!entries.isEmpty())
|
||||
while (true)
|
||||
{
|
||||
Entry entry = entries.poll();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Processing {}", entry);
|
||||
boolean progress = false;
|
||||
|
||||
// If the stream has been reset or removed, don't send the frame.
|
||||
if (entry.isStale())
|
||||
if (pendingEntries.isEmpty())
|
||||
break;
|
||||
|
||||
Iterator<Entry> pending = pendingEntries.iterator();
|
||||
while (pending.hasNext())
|
||||
{
|
||||
Entry entry = pending.next();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Stale {}", entry);
|
||||
continue;
|
||||
}
|
||||
LOG.debug("Processing {}", entry);
|
||||
|
||||
try
|
||||
{
|
||||
if (entry.generate(lease))
|
||||
// If the stream has been reset or removed,
|
||||
// don't send the frame and fail it here.
|
||||
if (entry.isStale())
|
||||
{
|
||||
if (entry.getDataBytesRemaining() > 0)
|
||||
entries.offer(entry);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Stale {}", entry);
|
||||
entry.failed(new EofException("reset"));
|
||||
pending.remove();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
try
|
||||
{
|
||||
if (stalled == null)
|
||||
stalled = entry;
|
||||
if (entry.generate(lease))
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Generated {} frame bytes for {}", entry.getFrameBytesGenerated(), entry);
|
||||
|
||||
progress = true;
|
||||
|
||||
processedEntries.add(entry);
|
||||
|
||||
if (entry.getDataBytesRemaining() == 0)
|
||||
pending.remove();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (session.getSendWindow() <= 0 && stalledEntry == null)
|
||||
{
|
||||
stalledEntry = entry;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Flow control stalled at {}", entry);
|
||||
// Continue to process control frames.
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable failure)
|
||||
{
|
||||
// Failure to generate the entry is catastrophic.
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Failure generating " + entry, failure);
|
||||
failed(failure);
|
||||
return Action.SUCCEEDED;
|
||||
}
|
||||
}
|
||||
catch (Throwable failure)
|
||||
|
||||
if (!progress)
|
||||
break;
|
||||
|
||||
if (stalledEntry != null)
|
||||
break;
|
||||
|
||||
int writeThreshold = session.getWriteThreshold();
|
||||
if (lease.getTotalLength() >= writeThreshold)
|
||||
{
|
||||
// Failure to generate the entry is catastrophic.
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Failure generating frame " + entry.frame, failure);
|
||||
failed(failure);
|
||||
return Action.SUCCEEDED;
|
||||
LOG.debug("Write threshold {} exceeded", writeThreshold);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
List<ByteBuffer> byteBuffers = lease.getByteBuffers();
|
||||
if (byteBuffers.isEmpty())
|
||||
{
|
||||
complete();
|
||||
finish();
|
||||
return Action.IDLE;
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Writing {} buffers ({} bytes) for {} frames {}", byteBuffers.size(), lease.getTotalLength(), actives.size(), actives);
|
||||
session.getEndPoint().write(this, byteBuffers.toArray(new ByteBuffer[byteBuffers.size()]));
|
||||
LOG.debug("Writing {} buffers ({} bytes) - entries processed/pending {}/{}: {}/{}",
|
||||
byteBuffers.size(),
|
||||
lease.getTotalLength(),
|
||||
processedEntries.size(),
|
||||
pendingEntries.size(),
|
||||
processedEntries,
|
||||
pendingEntries);
|
||||
|
||||
session.getEndPoint().write(this, byteBuffers.toArray(EMPTY_BYTE_BUFFERS));
|
||||
return Action.SCHEDULED;
|
||||
}
|
||||
|
||||
void onFlushed(long bytes) throws IOException
|
||||
{
|
||||
// For the given flushed bytes, we want to only
|
||||
// forward those that belong to data frame content.
|
||||
for (Entry entry : actives)
|
||||
{
|
||||
int frameBytesLeft = entry.getFrameBytesRemaining();
|
||||
if (frameBytesLeft > 0)
|
||||
{
|
||||
int update = (int)Math.min(bytes, frameBytesLeft);
|
||||
entry.onFrameBytesFlushed(update);
|
||||
bytes -= update;
|
||||
IStream stream = entry.stream;
|
||||
if (stream != null && !entry.isControl())
|
||||
{
|
||||
Object channel = stream.getAttachment();
|
||||
if (channel instanceof WriteFlusher.Listener)
|
||||
((WriteFlusher.Listener)channel).onFlushed(update - Frame.HEADER_LENGTH);
|
||||
}
|
||||
if (bytes == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// A single EndPoint write may be flushed multiple times (for example with SSL).
|
||||
for (Entry entry : processedEntries)
|
||||
bytes = entry.onFlushed(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Written {} frames for {}", actives.size(), actives);
|
||||
|
||||
complete();
|
||||
|
||||
LOG.debug("Written {} buffers - entries processed/pending {}/{}: {}/{}",
|
||||
lease.getByteBuffers().size(),
|
||||
processedEntries.size(),
|
||||
pendingEntries.size(),
|
||||
processedEntries,
|
||||
pendingEntries);
|
||||
finish();
|
||||
super.succeeded();
|
||||
}
|
||||
|
||||
private void complete()
|
||||
private void finish()
|
||||
{
|
||||
lease.recycle();
|
||||
|
||||
actives.forEach(Entry::complete);
|
||||
processedEntries.forEach(Entry::succeeded);
|
||||
processedEntries.clear();
|
||||
|
||||
if (stalled != null)
|
||||
if (stalledEntry != null)
|
||||
{
|
||||
// We have written part of the frame, but there is more to write.
|
||||
// The API will not allow to send two data frames for the same
|
||||
// stream so we append the unfinished frame at the end to allow
|
||||
// better interleaving with other streams.
|
||||
int index = actives.indexOf(stalled);
|
||||
for (int i = index; i < actives.size(); ++i)
|
||||
int size = pendingEntries.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
Entry entry = actives.get(i);
|
||||
if (entry.getDataBytesRemaining() > 0)
|
||||
append(entry);
|
||||
Entry entry = pendingEntries.peek();
|
||||
if (entry == stalledEntry)
|
||||
break;
|
||||
pendingEntries.poll();
|
||||
pendingEntries.offer(entry);
|
||||
}
|
||||
for (int i = 0; i < index; ++i)
|
||||
{
|
||||
Entry entry = actives.get(i);
|
||||
if (entry.getDataBytesRemaining() > 0)
|
||||
append(entry);
|
||||
}
|
||||
stalled = null;
|
||||
stalledEntry = null;
|
||||
}
|
||||
|
||||
actives.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -287,18 +304,26 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
lease.recycle();
|
||||
|
||||
Throwable closed;
|
||||
Set<Entry> allEntries;
|
||||
synchronized (this)
|
||||
{
|
||||
closed = terminated;
|
||||
terminated = x;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{}, active/queued={}/{}", closed != null ? "Closing" : "Failing", actives.size(), frames.size());
|
||||
actives.addAll(frames);
|
||||
frames.clear();
|
||||
LOG.debug(String.format("%s, entries processed/pending/queued=%d/%d/%d",
|
||||
closed != null ? "Closing" : "Failing",
|
||||
processedEntries.size(),
|
||||
pendingEntries.size(),
|
||||
entries.size()), x);
|
||||
allEntries = new HashSet<>(entries);
|
||||
entries.clear();
|
||||
}
|
||||
|
||||
actives.forEach(entry -> entry.failed(x));
|
||||
actives.clear();
|
||||
allEntries.addAll(processedEntries);
|
||||
processedEntries.clear();
|
||||
allEntries.addAll(pendingEntries);
|
||||
pendingEntries.clear();
|
||||
allEntries.forEach(entry -> entry.failed(x));
|
||||
|
||||
// If the failure came from within the
|
||||
// flusher, we need to close the connection.
|
||||
|
@ -340,11 +365,12 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s[window_queue=%d,frame_queue=%d,actives=%d]",
|
||||
return String.format("%s[window_queue=%d,frame_queue=%d,processed/pending=%d/%d]",
|
||||
super.toString(),
|
||||
getWindowQueueSize(),
|
||||
getFrameQueueSize(),
|
||||
actives.size());
|
||||
processedEntries.size(),
|
||||
pendingEntries.size());
|
||||
}
|
||||
|
||||
public static abstract class Entry extends Callback.Nested
|
||||
|
@ -359,9 +385,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
this.stream = stream;
|
||||
}
|
||||
|
||||
public abstract int getFrameBytesRemaining();
|
||||
|
||||
public abstract void onFrameBytesFlushed(int bytesFlushed);
|
||||
public abstract int getFrameBytesGenerated();
|
||||
|
||||
public int getDataBytesRemaining()
|
||||
{
|
||||
|
@ -370,13 +394,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
|
||||
protected abstract boolean generate(ByteBufferPool.Lease lease);
|
||||
|
||||
private void complete()
|
||||
{
|
||||
if (isStale())
|
||||
failed(new EofException("reset"));
|
||||
else
|
||||
succeeded();
|
||||
}
|
||||
public abstract long onFlushed(long bytes) throws IOException;
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
|
@ -417,17 +435,6 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isControl()
|
||||
{
|
||||
switch (frame.getType())
|
||||
{
|
||||
case DATA:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.eclipse.jetty.http2.generator.Generator;
|
|||
import org.eclipse.jetty.http2.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.WriteFlusher;
|
||||
import org.eclipse.jetty.util.AtomicBiInteger;
|
||||
import org.eclipse.jetty.util.Atomics;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
@ -88,6 +89,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
private int maxRemoteStreams;
|
||||
private long streamIdleTimeout;
|
||||
private int initialSessionRecvWindow;
|
||||
private int writeThreshold;
|
||||
private boolean pushEnabled;
|
||||
private long idleTime;
|
||||
private GoAwayFrame closeFrame;
|
||||
|
@ -106,6 +108,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
this.streamIdleTimeout = endPoint.getIdleTimeout();
|
||||
this.sendWindow.set(FlowControlStrategy.DEFAULT_WINDOW_SIZE);
|
||||
this.recvWindow.set(FlowControlStrategy.DEFAULT_WINDOW_SIZE);
|
||||
this.writeThreshold = 32 * 1024;
|
||||
this.pushEnabled = true; // SPEC: by default, push is enabled.
|
||||
this.idleTime = System.nanoTime();
|
||||
addBean(flowControl);
|
||||
|
@ -186,6 +189,16 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
this.initialSessionRecvWindow = initialSessionRecvWindow;
|
||||
}
|
||||
|
||||
public int getWriteThreshold()
|
||||
{
|
||||
return writeThreshold;
|
||||
}
|
||||
|
||||
public void setWriteThreshold(int writeThreshold)
|
||||
{
|
||||
this.writeThreshold = writeThreshold;
|
||||
}
|
||||
|
||||
public EndPoint getEndPoint()
|
||||
{
|
||||
return endPoint;
|
||||
|
@ -962,7 +975,8 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
{
|
||||
}
|
||||
|
||||
void onFlushed(long bytes) throws IOException
|
||||
@Override
|
||||
public void onFlushed(long bytes) throws IOException
|
||||
{
|
||||
flusher.onFlushed(bytes);
|
||||
}
|
||||
|
@ -1144,7 +1158,6 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
|
||||
private class ControlEntry extends HTTP2Flusher.Entry
|
||||
{
|
||||
private int bytes;
|
||||
private int frameBytes;
|
||||
|
||||
private ControlEntry(Frame frame, IStream stream, Callback callback)
|
||||
|
@ -1153,25 +1166,27 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getFrameBytesRemaining()
|
||||
public int getFrameBytesGenerated()
|
||||
{
|
||||
return frameBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFrameBytesFlushed(int bytesFlushed)
|
||||
protected boolean generate(ByteBufferPool.Lease lease)
|
||||
{
|
||||
frameBytes -= bytesFlushed;
|
||||
frameBytes = generator.control(lease, frame);
|
||||
beforeSend();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean generate(ByteBufferPool.Lease lease)
|
||||
public long onFlushed(long bytes)
|
||||
{
|
||||
bytes = frameBytes = generator.control(lease, frame);
|
||||
long flushed = Math.min(frameBytes, bytes);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Generated {}", frame);
|
||||
beforeSend();
|
||||
return true;
|
||||
LOG.debug("Flushed {}/{} frame bytes for {}", flushed, bytes, this);
|
||||
frameBytes -= flushed;
|
||||
return bytes - flushed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1215,7 +1230,9 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
bytesWritten.addAndGet(bytes);
|
||||
bytesWritten.addAndGet(frameBytes);
|
||||
frameBytes = 0;
|
||||
|
||||
switch (frame.getType())
|
||||
{
|
||||
case HEADERS:
|
||||
|
@ -1264,6 +1281,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
super.succeeded();
|
||||
}
|
||||
|
||||
|
@ -1278,10 +1296,10 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
|
||||
private class DataEntry extends HTTP2Flusher.Entry
|
||||
{
|
||||
private int bytes;
|
||||
private int frameBytes;
|
||||
private int frameRemaining;
|
||||
private int dataBytes;
|
||||
private int dataWritten;
|
||||
private int dataRemaining;
|
||||
|
||||
private DataEntry(DataFrame frame, IStream stream, Callback callback)
|
||||
{
|
||||
|
@ -1291,61 +1309,74 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
// of data frames that cannot be completely written due to
|
||||
// the flow control window exhausting, since in that case
|
||||
// we would have to count the padding only once.
|
||||
dataBytes = frame.remaining();
|
||||
dataRemaining = frame.remaining();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrameBytesRemaining()
|
||||
public int getFrameBytesGenerated()
|
||||
{
|
||||
return frameBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFrameBytesFlushed(int bytesFlushed)
|
||||
{
|
||||
frameBytes -= bytesFlushed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDataBytesRemaining()
|
||||
{
|
||||
return dataBytes;
|
||||
return dataRemaining;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean generate(ByteBufferPool.Lease lease)
|
||||
{
|
||||
int dataBytes = getDataBytesRemaining();
|
||||
int dataRemaining = getDataBytesRemaining();
|
||||
|
||||
int sessionSendWindow = getSendWindow();
|
||||
int streamSendWindow = stream.updateSendWindow(0);
|
||||
int window = Math.min(streamSendWindow, sessionSendWindow);
|
||||
if (window <= 0 && dataBytes > 0)
|
||||
if (window <= 0 && dataRemaining > 0)
|
||||
return false;
|
||||
|
||||
int length = Math.min(dataBytes, window);
|
||||
int length = Math.min(dataRemaining, window);
|
||||
|
||||
// Only one DATA frame is generated.
|
||||
DataFrame dataFrame = (DataFrame)frame;
|
||||
bytes = frameBytes = generator.data(lease, dataFrame, length);
|
||||
int written = bytes - Frame.HEADER_LENGTH;
|
||||
int frameBytes = generator.data(lease, (DataFrame)frame, length);
|
||||
this.frameBytes += frameBytes;
|
||||
this.frameRemaining += frameBytes;
|
||||
|
||||
int dataBytes = frameBytes - Frame.HEADER_LENGTH;
|
||||
this.dataBytes += dataBytes;
|
||||
this.dataRemaining -= dataBytes;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Generated {}, length/window/data={}/{}/{}", dataFrame, written, window, dataBytes);
|
||||
LOG.debug("Generated {}, length/window/data={}/{}/{}", frame, dataBytes, window, dataRemaining);
|
||||
|
||||
this.dataWritten = written;
|
||||
this.dataBytes -= written;
|
||||
|
||||
flowControl.onDataSending(stream, written);
|
||||
stream.updateClose(dataFrame.isEndStream(), CloseState.Event.BEFORE_SEND);
|
||||
flowControl.onDataSending(stream, dataBytes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long onFlushed(long bytes) throws IOException
|
||||
{
|
||||
long flushed = Math.min(frameRemaining, bytes);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Flushed {}/{} frame bytes for {}", flushed, bytes, this);
|
||||
frameRemaining -= flushed;
|
||||
// We should only forward data (not frame) bytes,
|
||||
// but we trade precision for simplicity.
|
||||
Object channel = stream.getAttachment();
|
||||
if (channel instanceof WriteFlusher.Listener)
|
||||
((WriteFlusher.Listener)channel).onFlushed(flushed);
|
||||
return bytes - flushed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
bytesWritten.addAndGet(bytes);
|
||||
flowControl.onDataSent(stream, dataWritten);
|
||||
bytesWritten.addAndGet(frameBytes);
|
||||
frameBytes = 0;
|
||||
frameRemaining = 0;
|
||||
|
||||
flowControl.onDataSent(stream, dataBytes);
|
||||
dataBytes = 0;
|
||||
|
||||
// Do we have more to send ?
|
||||
DataFrame dataFrame = (DataFrame)frame;
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
package org.eclipse.jetty.http2;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jetty.http2.api.Session;
|
||||
import org.eclipse.jetty.http2.api.Stream;
|
||||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
|
@ -129,6 +131,14 @@ public interface ISession extends Session
|
|||
*/
|
||||
public void onFrame(Frame frame);
|
||||
|
||||
/**
|
||||
* <p>Callback method invoked when bytes are flushed to the network.</p>
|
||||
*
|
||||
* @param bytes the number of bytes flushed to the network
|
||||
* @throws IOException if the flush should fail
|
||||
*/
|
||||
public void onFlushed(long bytes) throws IOException;
|
||||
|
||||
/**
|
||||
* @return the number of bytes written by this session
|
||||
*/
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -51,7 +51,7 @@
|
|||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-Description>Http2 Hpack</Bundle-Description>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||
<Provide-Capability>osgi.serviceloader;osgi.serviceloader=org.eclipse.jetty.http.HttpFieldPreEncoder</Provide-Capability>
|
||||
<_nouses>true</_nouses>
|
||||
</instructions>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.eclipse.jetty.http2.BufferingFlowControlStrategy;
|
|||
import org.eclipse.jetty.http2.FlowControlStrategy;
|
||||
import org.eclipse.jetty.http2.HTTP2Connection;
|
||||
import org.eclipse.jetty.http2.api.server.ServerSessionListener;
|
||||
import org.eclipse.jetty.http2.frames.Frame;
|
||||
import org.eclipse.jetty.http2.generator.Generator;
|
||||
import org.eclipse.jetty.http2.parser.ServerParser;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
|
@ -62,6 +63,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
throw new IllegalArgumentException("Unsupported HTTP2 Protocol variant: "+p);
|
||||
this.httpConfiguration = Objects.requireNonNull(httpConfiguration);
|
||||
addBean(httpConfiguration);
|
||||
setInputBufferSize(Frame.DEFAULT_MAX_LENGTH + Frame.HEADER_LENGTH);
|
||||
}
|
||||
|
||||
@ManagedAttribute("The HPACK dynamic table maximum size")
|
||||
|
@ -185,7 +187,8 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
streamIdleTimeout = endPoint.getIdleTimeout();
|
||||
session.setStreamIdleTimeout(streamIdleTimeout);
|
||||
session.setInitialSessionRecvWindow(getInitialSessionRecvWindow());
|
||||
|
||||
session.setWriteThreshold(getHttpConfiguration().getOutputBufferSize());
|
||||
|
||||
ServerParser parser = newServerParser(connector, session);
|
||||
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
|
||||
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
|
||||
|
|
|
@ -145,6 +145,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
for (Frame frame : upgradeFrames)
|
||||
getSession().onFrame(frame);
|
||||
super.onOpen();
|
||||
produce();
|
||||
}
|
||||
|
||||
private void notifyAccept(ISession session)
|
||||
|
|
|
@ -91,41 +91,61 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
if (info != null)
|
||||
{
|
||||
metaData = info;
|
||||
|
||||
int status = info.getStatus();
|
||||
boolean informational = HttpStatus.isInformational(status) && status != HttpStatus.SWITCHING_PROTOCOLS_101;
|
||||
if (informational)
|
||||
boolean interimResponse = status == HttpStatus.CONTINUE_100 || status == HttpStatus.PROCESSING_102;
|
||||
if (interimResponse)
|
||||
{
|
||||
if (transportCallback.start(callback, false))
|
||||
sendHeaders(info, false, transportCallback);
|
||||
// Must not commit interim responses.
|
||||
if (hasContent)
|
||||
{
|
||||
callback.failed(new IllegalStateException("Interim response cannot have content"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transportCallback.start(callback, false))
|
||||
sendHeadersFrame(info, false, transportCallback);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean needsCommit = commit.compareAndSet(false, true);
|
||||
if (needsCommit)
|
||||
if (commit.compareAndSet(false, true))
|
||||
{
|
||||
Supplier<HttpFields> trailers = info.getTrailerSupplier();
|
||||
|
||||
if (hasContent)
|
||||
{
|
||||
Callback nested = trailers == null || !lastContent ? callback : new SendTrailers(callback);
|
||||
Callback commitCallback = new Callback.Nested(nested)
|
||||
Callback commitCallback = new Callback.Nested(callback)
|
||||
{
|
||||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
if (transportCallback.start(nested, false))
|
||||
sendContent(content, lastContent, trailers == null && lastContent, transportCallback);
|
||||
if (lastContent)
|
||||
{
|
||||
Supplier<HttpFields> trailers = info.getTrailerSupplier();
|
||||
if (transportCallback.start(new SendTrailers(getCallback(), trailers), false))
|
||||
sendDataFrame(content, true, trailers == null, transportCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transportCallback.start(getCallback(), false))
|
||||
sendDataFrame(content, false, false, transportCallback);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (transportCallback.start(commitCallback, true))
|
||||
sendHeaders(info, false, transportCallback);
|
||||
sendHeadersFrame(info, false, transportCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
Callback nested = trailers == null ? callback : new SendTrailers(callback);
|
||||
if (transportCallback.start(nested, true))
|
||||
sendHeaders(info, trailers == null && lastContent, transportCallback);
|
||||
if (lastContent)
|
||||
{
|
||||
Supplier<HttpFields> trailers = info.getTrailerSupplier();
|
||||
if (transportCallback.start(new SendTrailers(callback, trailers), true))
|
||||
sendHeadersFrame(info, trailers == null, transportCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transportCallback.start(callback, true))
|
||||
sendHeadersFrame(info, false, transportCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -138,10 +158,25 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
{
|
||||
if (hasContent || lastContent)
|
||||
{
|
||||
Supplier<HttpFields> trailers = metaData.getTrailerSupplier();
|
||||
Callback nested = trailers == null ? callback : new SendTrailers(callback);
|
||||
if (transportCallback.start(nested, false))
|
||||
sendContent(content, lastContent, trailers == null && lastContent, transportCallback);
|
||||
if (lastContent)
|
||||
{
|
||||
Supplier<HttpFields> trailers = metaData.getTrailerSupplier();
|
||||
SendTrailers sendTrailers = new SendTrailers(callback, trailers);
|
||||
if (hasContent || trailers == null)
|
||||
{
|
||||
if (transportCallback.start(sendTrailers, false))
|
||||
sendDataFrame(content, true, trailers == null, transportCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendTrailers.succeeded();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transportCallback.start(callback, false))
|
||||
sendDataFrame(content, false, false, transportCallback);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -186,7 +221,7 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
}, new Stream.Listener.Adapter()); // TODO: handle reset from the client ?
|
||||
}
|
||||
|
||||
private void sendHeaders(MetaData.Response info, boolean endStream, Callback callback)
|
||||
private void sendHeadersFrame(MetaData.Response info, boolean endStream, Callback callback)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
|
@ -200,7 +235,7 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
stream.headers(frame, callback);
|
||||
}
|
||||
|
||||
private void sendContent(ByteBuffer content, boolean lastContent, boolean endStream, Callback callback)
|
||||
private void sendDataFrame(ByteBuffer content, boolean lastContent, boolean endStream, Callback callback)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
|
@ -212,7 +247,7 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
stream.data(frame, callback);
|
||||
}
|
||||
|
||||
private void sendTrailers(MetaData metaData, Callback callback)
|
||||
private void sendTrailersFrame(MetaData metaData, Callback callback)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
|
@ -385,16 +420,26 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
|
||||
private class SendTrailers extends Callback.Nested
|
||||
{
|
||||
private SendTrailers(Callback callback)
|
||||
private final Supplier<HttpFields> trailers;
|
||||
|
||||
private SendTrailers(Callback callback, Supplier<HttpFields> trailers)
|
||||
{
|
||||
super(callback);
|
||||
this.trailers = trailers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
if (transportCallback.start(getCallback(), false))
|
||||
sendTrailers(new MetaData(HttpVersion.HTTP_2, metaData.getTrailerSupplier().get()), transportCallback);
|
||||
if (trailers != null)
|
||||
{
|
||||
if (transportCallback.start(getCallback(), false))
|
||||
sendTrailersFrame(new MetaData(HttpVersion.HTTP_2, trailers.get()), transportCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.succeeded();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-infinispan</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
|
|
|
@ -101,8 +101,8 @@ public interface ByteBufferPool
|
|||
public long getTotalLength()
|
||||
{
|
||||
long length = 0;
|
||||
for (int i = 0; i < buffers.size(); ++i)
|
||||
length += buffers.get(i).remaining();
|
||||
for (ByteBuffer buffer : buffers)
|
||||
length += buffer.remaining();
|
||||
return length;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-jaas</artifactId>
|
||||
|
@ -34,5 +34,10 @@
|
|||
<artifactId>jetty-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.eclipse.jetty.jaas;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
|
@ -32,25 +31,34 @@ import javax.security.auth.callback.CallbackHandler;
|
|||
import javax.security.auth.callback.NameCallback;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
import javax.security.auth.login.Configuration;
|
||||
import javax.security.auth.login.LoginContext;
|
||||
import javax.security.auth.login.LoginException;
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
import org.eclipse.jetty.jaas.callback.ServletRequestCallback;
|
||||
import org.eclipse.jetty.jaas.callback.DefaultCallbackHandler;
|
||||
import org.eclipse.jetty.jaas.callback.ObjectCallback;
|
||||
import org.eclipse.jetty.jaas.callback.RequestParameterCallback;
|
||||
import org.eclipse.jetty.security.DefaultIdentityService;
|
||||
import org.eclipse.jetty.security.IdentityService;
|
||||
import org.eclipse.jetty.security.LoginService;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.eclipse.jetty.util.ArrayUtil;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* JAASLoginService
|
||||
*
|
||||
*
|
||||
* Implementation of jetty's LoginService that works with JAAS for
|
||||
* authorization and authentication.
|
||||
*
|
||||
*/
|
||||
public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
||||
{
|
||||
|
@ -65,20 +73,17 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
protected String _loginModuleName;
|
||||
protected JAASUserPrincipal _defaultUser = new JAASUserPrincipal(null, null, null);
|
||||
protected IdentityService _identityService;
|
||||
protected Configuration _configuration;
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*/
|
||||
public JAASLoginService()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name the name of the realm
|
||||
*/
|
||||
|
@ -90,7 +95,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the name of the realm.
|
||||
*
|
||||
|
@ -103,7 +108,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Set the name of the realm
|
||||
*
|
||||
|
@ -114,8 +119,29 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
_realmName = name;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the identityService.
|
||||
|
||||
/**
|
||||
* @return the configuration
|
||||
*/
|
||||
public Configuration getConfiguration()
|
||||
{
|
||||
return _configuration;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param configuration the configuration to set
|
||||
*/
|
||||
public void setConfiguration(Configuration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the identityService.
|
||||
* @return the identityService
|
||||
*/
|
||||
@Override
|
||||
|
@ -124,8 +150,9 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
return _identityService;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the identityService.
|
||||
|
||||
/**
|
||||
* Set the identityService.
|
||||
* @param identityService the identityService to set
|
||||
*/
|
||||
@Override
|
||||
|
@ -134,7 +161,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
_identityService = identityService;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* Set the name to use to index into the config
|
||||
* file of LoginModules.
|
||||
|
@ -146,52 +173,47 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
_loginModuleName = name;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
public void setCallbackHandlerClass (String classname)
|
||||
{
|
||||
_callbackHandlerClass = classname;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
public void setRoleClassNames (String[] classnames)
|
||||
{
|
||||
ArrayList<String> tmp = new ArrayList<String>();
|
||||
|
||||
if (classnames != null)
|
||||
tmp.addAll(Arrays.asList(classnames));
|
||||
|
||||
if (!tmp.contains(DEFAULT_ROLE_CLASS_NAME))
|
||||
tmp.add(DEFAULT_ROLE_CLASS_NAME);
|
||||
_roleClassNames = tmp.toArray(new String[tmp.size()]);
|
||||
if (classnames == null || classnames.length == 0)
|
||||
{
|
||||
_roleClassNames = DEFAULT_ROLE_CLASS_NAMES;
|
||||
return;
|
||||
}
|
||||
|
||||
_roleClassNames = ArrayUtil.addToArray(classnames, DEFAULT_ROLE_CLASS_NAME, String.class);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
public String[] getRoleClassNames()
|
||||
{
|
||||
return _roleClassNames;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
|
||||
*/
|
||||
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
if (_identityService==null)
|
||||
_identityService=new DefaultIdentityService();
|
||||
_identityService = new DefaultIdentityService();
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
@Override
|
||||
public UserIdentity login(final String username,final Object credentials, final ServletRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
CallbackHandler callbackHandler = null;
|
||||
|
||||
|
||||
if (_callbackHandlerClass == null)
|
||||
{
|
||||
callbackHandler = new CallbackHandler()
|
||||
|
@ -207,7 +229,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
}
|
||||
else if (callback instanceof PasswordCallback)
|
||||
{
|
||||
((PasswordCallback)callback).setPassword((char[]) credentials.toString().toCharArray());
|
||||
((PasswordCallback)callback).setPassword(credentials.toString().toCharArray());
|
||||
}
|
||||
else if (callback instanceof ObjectCallback)
|
||||
{
|
||||
|
@ -219,6 +241,10 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
if (request!=null)
|
||||
rpc.setParameterValues(Arrays.asList(request.getParameterValues(rpc.getParameterName())));
|
||||
}
|
||||
else if (callback instanceof ServletRequestCallback)
|
||||
{
|
||||
((ServletRequestCallback)callback).setRequest(request);
|
||||
}
|
||||
else
|
||||
throw new UnsupportedCallbackException(callback);
|
||||
}
|
||||
|
@ -228,12 +254,21 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
else
|
||||
{
|
||||
Class<?> clazz = Loader.loadClass(_callbackHandlerClass);
|
||||
callbackHandler = (CallbackHandler)clazz.newInstance();
|
||||
callbackHandler = (CallbackHandler)clazz.getDeclaredConstructor().newInstance();
|
||||
if (DefaultCallbackHandler.class.isAssignableFrom(clazz))
|
||||
{
|
||||
DefaultCallbackHandler dch = (DefaultCallbackHandler)callbackHandler;
|
||||
if (request instanceof Request)
|
||||
dch.setRequest((Request)request);
|
||||
dch.setCredential(credentials);
|
||||
dch.setUserName(username);
|
||||
}
|
||||
}
|
||||
|
||||
//set up the login context
|
||||
//TODO jaspi requires we provide the Configuration parameter
|
||||
Subject subject = new Subject();
|
||||
LoginContext loginContext = new LoginContext(_loginModuleName, subject, callbackHandler);
|
||||
LoginContext loginContext = (_configuration==null?new LoginContext(_loginModuleName, subject, callbackHandler)
|
||||
:new LoginContext(_loginModuleName, subject, callbackHandler, _configuration));
|
||||
|
||||
loginContext.login();
|
||||
|
||||
|
@ -243,34 +278,14 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
|
||||
return _identityService.newUserIdentity(subject,userPrincipal,getGroups(subject));
|
||||
}
|
||||
catch (LoginException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
catch (UnsupportedCallbackException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
@Override
|
||||
public boolean validate(UserIdentity user)
|
||||
{
|
||||
|
@ -278,7 +293,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
private String getUserName(CallbackHandler callbackHandler) throws IOException, UnsupportedCallbackException
|
||||
{
|
||||
NameCallback nameCallback = new NameCallback("foo");
|
||||
|
@ -286,7 +301,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
return nameCallback.getName();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
@Override
|
||||
public void logout(UserIdentity user)
|
||||
{
|
||||
|
@ -303,31 +318,64 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private String[] getGroups (Subject subject)
|
||||
/**
|
||||
* Get all of the groups for the user.
|
||||
*
|
||||
* @param subject the Subject representing the user
|
||||
*
|
||||
* @return all the names of groups that the user is in, or 0 length array if none
|
||||
*/
|
||||
protected String[] getGroups (Subject subject)
|
||||
{
|
||||
//get all the roles of the various types
|
||||
String[] roleClassNames = getRoleClassNames();
|
||||
Collection<String> groups = new LinkedHashSet<String>();
|
||||
try
|
||||
Collection<String> groups = new LinkedHashSet<>();
|
||||
Set<Principal> principals = subject.getPrincipals();
|
||||
for (Principal principal : principals)
|
||||
{
|
||||
for (String roleClassName : roleClassNames)
|
||||
Class<?> c = principal.getClass();
|
||||
while (c!=null)
|
||||
{
|
||||
Class load_class = Thread.currentThread().getContextClassLoader().loadClass(roleClassName);
|
||||
Set<Principal> rolesForType = subject.getPrincipals(load_class);
|
||||
for (Principal principal : rolesForType)
|
||||
if (roleClassNameMatches(c.getName()))
|
||||
{
|
||||
groups.add(principal.getName());
|
||||
break;
|
||||
}
|
||||
|
||||
boolean added = false;
|
||||
for (Class<?> ci:c.getInterfaces())
|
||||
{
|
||||
if (roleClassNameMatches(ci.getName()))
|
||||
{
|
||||
groups.add(principal.getName());
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!added)
|
||||
{
|
||||
c = c.getSuperclass();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return groups.toArray(new String[groups.size()]);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
return groups.toArray(new String[groups.size()]);
|
||||
}
|
||||
|
||||
|
||||
private boolean roleClassNameMatches (String classname)
|
||||
{
|
||||
boolean result = false;
|
||||
for (String roleClassName:getRoleClassNames())
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
if (roleClassName.equals(classname))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,10 @@ import org.eclipse.jetty.server.Request;
|
|||
import org.eclipse.jetty.util.security.Password;
|
||||
|
||||
/**
|
||||
* DefaultUsernameCredentialCallbackHandler
|
||||
* DefaultCallbackHandler
|
||||
*
|
||||
* An implementation of the JAAS CallbackHandler. Users can provide
|
||||
* their own implementation instead and set the name of its class on the JAASLoginService.
|
||||
*/
|
||||
public class DefaultCallbackHandler extends AbstractCallbackHandler
|
||||
{
|
||||
|
@ -38,7 +41,7 @@ public class DefaultCallbackHandler extends AbstractCallbackHandler
|
|||
|
||||
public void setRequest (Request request)
|
||||
{
|
||||
this._request = request;
|
||||
_request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,6 +74,10 @@ public class DefaultCallbackHandler extends AbstractCallbackHandler
|
|||
RequestParameterCallback callback = (RequestParameterCallback)callbacks[i];
|
||||
callback.setParameterValues(Arrays.asList(_request.getParameterValues(callback.getParameterName())));
|
||||
}
|
||||
else if (callbacks[i] instanceof ServletRequestCallback)
|
||||
{
|
||||
((ServletRequestCallback)callbacks[i]).setRequest(_request);
|
||||
}
|
||||
else
|
||||
throw new UnsupportedCallbackException(callbacks[i]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.jaas.callback;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* ServletRequestCallback
|
||||
*
|
||||
* Provides access to the request associated with the authentication.
|
||||
*/
|
||||
public class ServletRequestCallback implements Callback
|
||||
{
|
||||
protected ServletRequest _request;
|
||||
|
||||
public void setRequest (ServletRequest request)
|
||||
{
|
||||
_request = request;
|
||||
}
|
||||
|
||||
public ServletRequest getRequest ()
|
||||
{
|
||||
return _request;
|
||||
}
|
||||
}
|
|
@ -115,6 +115,12 @@ public abstract class AbstractLoginModule implements LoginModule
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public abstract UserInfo getUserInfo (String username) throws Exception;
|
||||
|
||||
|
||||
|
||||
public Subject getSubject ()
|
||||
{
|
||||
return this.subject;
|
||||
|
@ -198,7 +204,6 @@ public abstract class AbstractLoginModule implements LoginModule
|
|||
|
||||
public Callback[] configureCallbacks ()
|
||||
{
|
||||
|
||||
Callback[] callbacks = new Callback[3];
|
||||
callbacks[0] = new NameCallback("Enter user name");
|
||||
callbacks[1] = new ObjectCallback();
|
||||
|
@ -211,9 +216,7 @@ public abstract class AbstractLoginModule implements LoginModule
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public abstract UserInfo getUserInfo (String username) throws Exception;
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -105,17 +105,9 @@ public class JDBCLoginModule extends AbstractDatabaseLoginModule
|
|||
dbPassword = "";
|
||||
|
||||
if (dbDriver != null)
|
||||
Loader.loadClass(dbDriver).newInstance();
|
||||
Loader.loadClass(dbDriver).getDeclaredConstructor().newInstance();
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
throw new IllegalStateException (e.toString());
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
throw new IllegalStateException (e.toString());
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalStateException (e.toString());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.jaas;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.security.auth.Subject;
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
|
||||
import javax.security.auth.login.Configuration;
|
||||
|
||||
import org.eclipse.jetty.security.DefaultIdentityService;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* JAASLoginServiceTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JAASLoginServiceTest
|
||||
{
|
||||
public static class TestConfiguration extends Configuration
|
||||
{
|
||||
AppConfigurationEntry _entry = new AppConfigurationEntry(TestLoginModule.class.getCanonicalName(), LoginModuleControlFlag.REQUIRED, Collections.emptyMap());
|
||||
|
||||
@Override
|
||||
public AppConfigurationEntry[] getAppConfigurationEntry(String name)
|
||||
{
|
||||
return new AppConfigurationEntry[] {_entry};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
interface SomeRole
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class TestRole implements Principal, SomeRole
|
||||
{
|
||||
String _name;
|
||||
|
||||
public TestRole (String name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class AnotherTestRole extends TestRole
|
||||
{
|
||||
public AnotherTestRole(String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
|
||||
public class NotTestRole implements Principal
|
||||
{
|
||||
String _name;
|
||||
|
||||
public NotTestRole (String n)
|
||||
{
|
||||
_name = n;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServletRequestCallback () throws Exception
|
||||
{
|
||||
//Test with the DefaultCallbackHandler
|
||||
JAASLoginService ls = new JAASLoginService("foo");
|
||||
ls.setCallbackHandlerClass("org.eclipse.jetty.jaas.callback.DefaultCallbackHandler");
|
||||
ls.setIdentityService(new DefaultIdentityService());
|
||||
ls.setConfiguration(new TestConfiguration());
|
||||
Request request = new Request(null, null);
|
||||
ls.login("aaardvaark", "aaa", request);
|
||||
|
||||
//Test with the fallback CallbackHandler
|
||||
ls = new JAASLoginService("foo");
|
||||
ls.setIdentityService(new DefaultIdentityService());
|
||||
ls.setConfiguration(new TestConfiguration());
|
||||
ls.login("aaardvaark", "aaa", request);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginServiceRoles () throws Exception
|
||||
{
|
||||
JAASLoginService ls = new JAASLoginService("foo");
|
||||
|
||||
//test that we always add in the DEFAULT ROLE CLASSNAME
|
||||
ls.setRoleClassNames(new String[] {"arole", "brole"});
|
||||
String[] roles = ls.getRoleClassNames();
|
||||
assertEquals(3, roles.length);
|
||||
assertEquals(JAASLoginService.DEFAULT_ROLE_CLASS_NAME, roles[2]);
|
||||
|
||||
ls.setRoleClassNames(new String[] {});
|
||||
assertEquals(1, ls.getRoleClassNames().length);
|
||||
assertEquals(JAASLoginService.DEFAULT_ROLE_CLASS_NAME, ls.getRoleClassNames()[0]);
|
||||
|
||||
ls.setRoleClassNames(null);
|
||||
assertEquals(1, ls.getRoleClassNames().length);
|
||||
assertEquals(JAASLoginService.DEFAULT_ROLE_CLASS_NAME, ls.getRoleClassNames()[0]);
|
||||
|
||||
//test a custom role class where some of the roles are subclasses of it
|
||||
ls.setRoleClassNames(new String[] {TestRole.class.getName()});
|
||||
Subject subject = new Subject();
|
||||
subject.getPrincipals().add(new NotTestRole("w"));
|
||||
subject.getPrincipals().add(new TestRole("x"));
|
||||
subject.getPrincipals().add(new TestRole("y"));
|
||||
subject.getPrincipals().add(new AnotherTestRole("z"));
|
||||
|
||||
String[] groups = ls.getGroups(subject);
|
||||
assertEquals(3, groups.length);
|
||||
for (String g:groups)
|
||||
assertTrue(g.equals("x") || g.equals("y") || g.equals("z"));
|
||||
|
||||
//test a custom role class
|
||||
ls.setRoleClassNames(new String[] {AnotherTestRole.class.getName()});
|
||||
Subject subject2 = new Subject();
|
||||
subject2.getPrincipals().add(new NotTestRole("w"));
|
||||
subject2.getPrincipals().add(new TestRole("x"));
|
||||
subject2.getPrincipals().add(new TestRole("y"));
|
||||
subject2.getPrincipals().add(new AnotherTestRole("z"));
|
||||
assertEquals(1, ls.getGroups(subject2).length);
|
||||
assertEquals("z", ls.getGroups(subject2)[0]);
|
||||
|
||||
//test a custom role class that implements an interface
|
||||
ls.setRoleClassNames(new String[] {SomeRole.class.getName()});
|
||||
Subject subject3 = new Subject();
|
||||
subject3.getPrincipals().add(new NotTestRole("w"));
|
||||
subject3.getPrincipals().add(new TestRole("x"));
|
||||
subject3.getPrincipals().add(new TestRole("y"));
|
||||
subject3.getPrincipals().add(new AnotherTestRole("z"));
|
||||
assertEquals(3, ls.getGroups(subject3).length);
|
||||
for (String g:groups)
|
||||
assertTrue(g.equals("x") || g.equals("y") || g.equals("z"));
|
||||
|
||||
//test a class that doesn't match
|
||||
ls.setRoleClassNames(new String[] {NotTestRole.class.getName()});
|
||||
Subject subject4 = new Subject();
|
||||
subject4.getPrincipals().add(new TestRole("x"));
|
||||
subject4.getPrincipals().add(new TestRole("y"));
|
||||
subject4.getPrincipals().add(new AnotherTestRole("z"));
|
||||
assertEquals(0, ls.getGroups(subject4).length);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.jaas;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.login.LoginException;
|
||||
|
||||
import org.eclipse.jetty.jaas.callback.ServletRequestCallback;
|
||||
import org.eclipse.jetty.jaas.spi.AbstractLoginModule;
|
||||
import org.eclipse.jetty.jaas.spi.UserInfo;
|
||||
import org.eclipse.jetty.util.ArrayUtil;
|
||||
import org.eclipse.jetty.util.security.Password;
|
||||
|
||||
|
||||
public class TestLoginModule extends AbstractLoginModule
|
||||
{
|
||||
public ServletRequestCallback _callback = new ServletRequestCallback();
|
||||
|
||||
@Override
|
||||
public UserInfo getUserInfo(String username) throws Exception
|
||||
{
|
||||
return new UserInfo(username, new Password("aaa"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Callback[] configureCallbacks()
|
||||
{
|
||||
return ArrayUtil.addToArray(super.configureCallbacks(), _callback, Callback.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean login() throws LoginException
|
||||
{
|
||||
boolean result = super.login();
|
||||
assertNotNull(_callback.getRequest());
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-jaspi</artifactId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-jmx</artifactId>
|
||||
|
|
|
@ -148,7 +148,7 @@ public class ObjectMBean implements DynamicMBean
|
|||
LOG.ignore(e);
|
||||
if (ModelMBean.class.isAssignableFrom(mClass))
|
||||
{
|
||||
mbean = mClass.newInstance();
|
||||
mbean = mClass.getDeclaredConstructor().newInstance();
|
||||
((ModelMBean)mbean).setManagedResource(o, "objectReference");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-jndi</artifactId>
|
||||
|
|
|
@ -187,7 +187,9 @@ public class ContextFactory implements ObjectFactory
|
|||
Reference ref = (Reference)obj;
|
||||
StringRefAddr parserAddr = (StringRefAddr)ref.get("parser");
|
||||
String parserClassName = (parserAddr==null?null:(String)parserAddr.getContent());
|
||||
NameParser parser = (NameParser)(parserClassName==null?null:loader.loadClass(parserClassName).newInstance());
|
||||
NameParser parser =
|
||||
(NameParser)(parserClassName==null?
|
||||
null:loader.loadClass(parserClassName).getDeclaredConstructor().newInstance());
|
||||
|
||||
return new NamingContext (env,
|
||||
name.get(0),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-jspc-maven-plugin</artifactId>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!-- ======================================================================== -->
|
||||
<!-- Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. -->
|
||||
<!-- 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 -->
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
<version>9.4.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
invoker.goals = test -fae
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue