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

This commit is contained in:
Joakim Erdfelt 2018-03-22 16:42:42 -05:00
commit 1c04f9838d
366 changed files with 4230 additions and 7961 deletions

7
Jenkinsfile vendored
View File

@ -41,8 +41,9 @@ def getFullBuild(jdk, os) {
maven: 'maven3',
jdk: "$jdk",
publisherStrategy: 'EXPLICIT',
globalMavenSettingsConfig: 'oss-settings.xml',
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") {
sh "mvn -V -B clean install -Dtest=None -T6"
sh "mvn -V -B clean install -DskipTests -T6"
}
}
@ -62,6 +63,7 @@ def getFullBuild(jdk, os) {
maven: 'maven3',
jdk: "$jdk",
publisherStrategy: 'EXPLICIT',
globalMavenSettingsConfig: 'oss-settings.xml',
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") {
sh "mvn -V -B javadoc:javadoc -T5"
}
@ -83,6 +85,8 @@ def getFullBuild(jdk, os) {
maven: 'maven3',
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}"
@ -137,6 +141,7 @@ def getFullBuild(jdk, os) {
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"
}

View File

@ -1,5 +1,97 @@
jetty-10.0.0-SNAPSHOT
jetty-9.4.9.v20180320 - 20 March 2018
+ 347 Avoid sending request using a connection that is idle timing out
+ 1416 GzipHandler generated ETag suffix has problems with If-Match header
logic
+ 1602 WebAppContext is started twice, once by deployer, again by lifecycle
+ 1614 AbstractNCSARequestLog does not extract the user from the http header
when it has not been authenticated
+ 1770 SniX509ExtendedKeyManager.chooseServerAlias() throws
NullPointerException when socket is null
+ 1797 JEP 238 - Multi-Release JAR files break bytecode scanning
+ 1832 Bad HTTP Close prevents proper TCP close
+ 1918 Scalable scheduler implementation
+ 1933 Use CLASSPATH for scanning java9 system classes
+ 1940 Embedded CDI: SessionScoped gives a NPE
+ 1949 Client-side problems with digest authentication
+ 1956 Store and report build information of Jetty
+ 1966 HttpMethod case sensitive
+ 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
+ 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
KeyManagers may be used"
+ 2014 Support unix domain sockets in HttpClient
+ 2015 jetty-alpn-conscrypt-server needs appropriate osgi headers in manifest
+ 2016 jetty-alpn-openjdk8-server needs correct osgi headers in manifest
+ 2019 Expose HttpClientTransport in JMX
+ 2020 Introduce a name for `HttpClient` instances
+ 2022 Fine grained RFC HTTP Compliance modes: including OWS prior to field
colon
+ 2028 Add osgi headers for alpn-java client and server
+ 2030 NPE in AnnotationConfiguration with DEBUG enabled
+ 2033 Improve HTTP/2 session and stream stall times report
+ 2034 Improve HTTP2Session dump
+ 2035 FlowControlStrategy keeps around reset streams
+ 2037 HTTP/2 stream reset leaves stream frames in the flusher
+ 2038 FileSessionDataStore.deleteAllFiles(File, String) can become slow
+ 2043 ConcurrentModificationException during annotation parsing
+ 2046 Server.stop not closing connections
+ 2050 Clarify ObjectMBean getObject[Name|Context]Basis() methods
+ 2079 Upgrade to apache jasper 8.5.24
+ 2080 Exclude more maven machinery dependencies from the jetty-maven-plugin
server path
+ 2081 No idle timeout exception when dispatch is delayed
+ 2088 Recycle HTTP/2 channels on the client
+ 2090 Jetty fails to start on OpenJDK 9: "Invalid Java version 9.0.1.3"
+ 2093 Correcting Bom managed dependencies that do not exist
+ 2114 Fix NPE in JettyHttpServerProvider
+ 2117 Allow to configure HttpClient default request Content-Type
+ 2130 Introduce thread pool module for simpler configuration of thread pool
in standalone
+ 2131 Introduce a monitored thread pool
+ 2136 maven & jetty-maven-plugin & offline
error:java.net.UnknownHostException: www.eclipse.org
+ 2148 Limit BufferUtil.toDetailString() raw character display to USASCII
7-bit printable characters
+ 2152 Produce jetty-home-source artifacts for Eclipse Jetty source jars
+ 2160 Digest authentication should use absolute path
+ 2164 Ensure all jetty modules that use ServiceLoader have correct OSGi
manifest headers
+ 2190 HTTP/2 close and GOAWAY behavior
+ 2203 Use GlobalWebAppConfigBinding rather than special methods on
DeploymentManager/WebAppProvider
+ 2209 jetty-maven-plugin deploy-war silently fails (unless the pom has war
packaging)
+ 2210 NPE at org.eclipse.jetty.client.HttpDestination.newExchangeQueue
+ 2218 Adding workaround for Windows NIO Selector Bug
+ 2232 Dependency Conflict: Conflicting JARs org.apache.maven:maven-project
+ 2255 Notify SSL handshake failures on write failures
+ 2275 jetty.server.ResourceService.doGet() + RequestDispatcher INCLUDE
+ 2278 Could not find artifact
org.eclipse.jetty.tests:test-webapps-parent:pom:9.4.8.v20171121
+ 2279 Jetty 9.4.x start.jar: "?=" in [ini] defeats Issue #1139 functionality
+ 2280 Default application/json to utf-8 encoding in encoding.properties
+ 2284 NPE from start.jar during JVM version parsing
+ 2288 Cleanup the statistics classes
+ 2291 Expose HTTP/2 close reason in dumps
+ 2293 HTTP/2 client multiplexed connection pool creates too many connections
+ 2297 HTTP/2 client transport should honor HttpClient.connectBlocking
+ 2298 Override the processor number with an environment variable
+ 2307 Error page can have null charset in content type
+ 2308 Type change in MonitorTask - int cannot be converted to
ThreadPoolExecutor
+ 2312 HTTP/2 Connection.Listener notified after first request
+ 2313 Dump HTTP/2 channel state
+ 2318 HttpParser.Listener.onBadMessage() should take BadMessageException
+ 2346 Missing stack traces in HTTPChannel.onException
+ 2358 Add ALPN module file for JDK 10
jetty-9.4.8.v20171121 - 21 November 2017
+ 212 HttpClient should support pluggable AuthenticationStore
+ 215 Add Conscrypt for native ALPN/TLS/SSL

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables use of the apache implementation of JSP

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables the apache version of JSTL

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Selects an ALPN (Application Layer Protocol Negotiation) implementation by java version.

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[files]
maven://org.mortbay.jetty.alpn/alpn-boot/8.1.0.v20141016|lib/alpn/alpn-boot-8.1.0.v20141016.jar

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[files]
maven://org.mortbay.jetty.alpn/alpn-boot/8.1.0.v20141016|lib/alpn/alpn-boot-8.1.0.v20141016.jar

View File

@ -1,3 +1,5 @@
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.9.v20160720/alpn-boot-8.1.9.v20160720.jar|lib/alpn/alpn-boot-8.1.9.v20160720.jar

View File

@ -1,3 +1,5 @@
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.9.v20160720/alpn-boot-8.1.9.v20160720.jar|lib/alpn/alpn-boot-8.1.9.v20160720.jar

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[files]
maven://org.mortbay.jetty.alpn/alpn-boot/8.1.0.v20141016|lib/alpn/alpn-boot-8.1.0.v20141016.jar

View File

@ -1,3 +1,5 @@
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.9.v20160720/alpn-boot-8.1.9.v20160720.jar|lib/alpn/alpn-boot-8.1.9.v20160720.jar

View File

@ -1,3 +1,5 @@
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.10.v20161026/alpn-boot-8.1.10.v20161026.jar|lib/alpn/alpn-boot-8.1.10.v20161026.jar

View File

@ -1,3 +1,5 @@
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.11.v20170118/alpn-boot-8.1.11.v20170118.jar|lib/alpn/alpn-boot-8.1.11.v20170118.jar

View File

@ -1,3 +1,5 @@
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.11.v20170118/alpn-boot-8.1.11.v20170118.jar|lib/alpn/alpn-boot-8.1.11.v20170118.jar

View File

@ -1,3 +1,5 @@
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.11.v20170118/alpn-boot-8.1.11.v20170118.jar|lib/alpn/alpn-boot-8.1.11.v20170118.jar

View File

@ -1,3 +1,5 @@
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.11.v20170118/alpn-boot-8.1.11.v20170118.jar|lib/alpn/alpn-boot-8.1.11.v20170118.jar

View File

@ -1,3 +1,5 @@
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.11.v20170118/alpn-boot-8.1.11.v20170118.jar|lib/alpn/alpn-boot-8.1.11.v20170118.jar

View File

@ -1,3 +1,5 @@
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.11.v20170118/alpn-boot-8.1.11.v20170118.jar|lib/alpn/alpn-boot-8.1.11.v20170118.jar

View File

@ -1,3 +1,5 @@
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

View File

@ -1,3 +1,5 @@
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

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[files]
maven://org.mortbay.jetty.alpn/alpn-boot/8.1.0.v20141016|lib/alpn/alpn-boot-8.1.0.v20141016.jar

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[files]
maven://org.mortbay.jetty.alpn/alpn-boot/8.1.2.v20141202|lib/alpn/alpn-boot-8.1.2.v20141202.jar

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[files]
maven://org.mortbay.jetty.alpn/alpn-boot/8.1.3.v20150130|lib/alpn/alpn-boot-8.1.3.v20150130.jar

View File

@ -1,3 +1,5 @@
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.3.v20150130/alpn-boot-8.1.3.v20150130.jar|lib/alpn/alpn-boot-8.1.3.v20150130.jar

View File

@ -1,3 +1,5 @@
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.3.v20150130/alpn-boot-8.1.3.v20150130.jar|lib/alpn/alpn-boot-8.1.3.v20150130.jar

View File

@ -1,3 +1,5 @@
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.4.v20150727/alpn-boot-8.1.4.v20150727.jar|lib/alpn/alpn-boot-8.1.4.v20150727.jar

View File

@ -1,3 +1,5 @@
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.5.v20150921/alpn-boot-8.1.5.v20150921.jar|lib/alpn/alpn-boot-8.1.5.v20150921.jar

View File

@ -1,3 +1,5 @@
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.6.v20151105/alpn-boot-8.1.6.v20151105.jar|lib/alpn/alpn-boot-8.1.6.v20151105.jar

View File

@ -1,3 +1,5 @@
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.6.v20151105/alpn-boot-8.1.6.v20151105.jar|lib/alpn/alpn-boot-8.1.6.v20151105.jar

View File

@ -1,3 +1,5 @@
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.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar

View File

@ -1,3 +1,5 @@
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.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar

View File

@ -1,3 +1,5 @@
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.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar

View File

@ -1,3 +1,5 @@
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.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar

View File

@ -1,3 +1,5 @@
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.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar

View File

@ -1,3 +1,5 @@
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.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar

View File

@ -1,3 +1,5 @@
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.8.v20160420/alpn-boot-8.1.8.v20160420.jar|lib/alpn/alpn-boot-8.1.8.v20160420.jar

View File

@ -0,0 +1,4 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[depend]
alpn-impl/alpn-9

View File

@ -0,0 +1,4 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[depend]
alpn-impl/alpn-9

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Provides ALPN support for JDK 8, modifying the sun.security.ssl
classes and adding them to the JVM boot classpath.

View File

@ -1,5 +1,7 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Provides support for ALPN based on JDK 9 APIs.
Provides support for ALPN based on JDK 9+ APIs.
[lib]
lib/jetty-alpn-java-server-${jetty.version}.jar

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables the ALPN (Application Layer Protocol Negotiation) TLS extension.

View File

@ -1,8 +0,0 @@
[name]
protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.11.v20170118/alpn-boot-8.1.11.v20170118.jar|lib/alpn/alpn-boot-8.1.11.v20170118.jar
[exec]
-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.11.v20170118.jar

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables Annotation scanning for deployed webapplications.

View File

@ -48,6 +48,7 @@ import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.util.JavaVersion;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.ProcessorUtils;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
@ -467,7 +468,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
start = System.nanoTime();
//execute scan, either effectively synchronously (1 thread only), or asynchronously (limited by number of processors available)
final Semaphore task_limit = (isUseMultiThreading(context)? new Semaphore(Runtime.getRuntime().availableProcessors()):new Semaphore(1));
final Semaphore task_limit = (isUseMultiThreading(context)? new Semaphore(ProcessorUtils.availableProcessors()):new Semaphore( 1));
final CountDownLatch latch = new CountDownLatch(_parserTasks.size());
final MultiException me = new MultiException();

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Jetty setup to support Weld/CDI2 with WELD inside the webapp

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Adds the Jetty HTTP client to the server classpath.

View File

@ -20,10 +20,10 @@ package org.eclipse.jetty.client;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.util.AtomicBiInteger;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
@ -39,7 +39,12 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
private static final Logger LOG = Log.getLogger(AbstractConnectionPool.class);
private final AtomicBoolean closed = new AtomicBoolean();
private final AtomicInteger connectionCount = new AtomicInteger();
/**
* The connectionCount encodes both the total connections plus the pending connection counts, so both can be atomically changed.
* The bottom 32 bits represent the total connections and the top 32 bits represent the pending connections.
*/
private final AtomicBiInteger connections = new AtomicBiInteger();
private final Destination destination;
private final int maxConnections;
private final Callback requester;
@ -60,13 +65,19 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
@ManagedAttribute(value = "The number of connections", readonly = true)
public int getConnectionCount()
{
return connectionCount.get();
return connections.getLo();
}
@ManagedAttribute(value = "The number of pending connections", readonly = true)
public int getPendingCount()
{
return connections.getHi();
}
@Override
public boolean isEmpty()
{
return connectionCount.get() == 0;
return connections.getLo() == 0;
}
@Override
@ -80,29 +91,34 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
{
Connection connection = activate();
if (connection == null)
connection = tryCreate();
{
tryCreate(-1);
connection = activate();
}
return connection;
}
private Connection tryCreate()
protected void tryCreate(int maxPending)
{
while (true)
{
int current = getConnectionCount();
final int next = current + 1;
long encoded = connections.get();
int pending = AtomicBiInteger.getHi(encoded);
int total = AtomicBiInteger.getLo(encoded);
if (next > maxConnections)
if (LOG.isDebugEnabled())
LOG.debug("tryCreate {}/{} connections {}/{} pending",total,maxConnections,pending,maxPending);
if (total >= maxConnections)
return;
if (maxPending>=0 && pending>=maxPending)
return;
if (connections.compareAndSet(encoded,pending+1,total+1))
{
if (LOG.isDebugEnabled())
LOG.debug("Max connections {}/{} reached", current, maxConnections);
// Try again the idle connections
return activate();
}
if (connectionCount.compareAndSet(current, next))
{
if (LOG.isDebugEnabled())
LOG.debug("Connection {}/{} creation", next, maxConnections);
LOG.debug("newConnection {}/{} connections {}/{} pending", total+1, maxConnections, pending+1, maxPending);
destination.newConnection(new Promise<Connection>()
{
@ -110,7 +126,8 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
public void succeeded(Connection connection)
{
if (LOG.isDebugEnabled())
LOG.debug("Connection {}/{} creation succeeded {}", next, maxConnections, connection);
LOG.debug("Connection {}/{} creation succeeded {}", total+1, maxConnections, connection);
connections.update(-1,0);
onCreated(connection);
proceed();
}
@ -119,14 +136,13 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
public void failed(Throwable x)
{
if (LOG.isDebugEnabled())
LOG.debug("Connection " + next + "/" + maxConnections + " creation failed", x);
connectionCount.decrementAndGet();
LOG.debug("Connection " + (total+1) + "/" + maxConnections + " creation failed", x);
connections.update(-1,-1);
requester.failed(x);
}
});
// Try again the idle connections
return activate();
return;
}
}
}
@ -174,7 +190,7 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
protected void removed(Connection connection)
{
int pooled = connectionCount.decrementAndGet();
int pooled = connections.updateLo(-1);
if (LOG.isDebugEnabled())
LOG.debug("Connection removed {} - pooled: {}", connection, pooled);
}
@ -184,7 +200,7 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
{
if (closed.compareAndSet(false, true))
{
connectionCount.set(0);
connections.set(0,0);
}
}

View File

@ -88,21 +88,22 @@ public abstract class AbstractConnectorHttpClientTransport extends AbstractHttpC
context.put(SslClientConnectionFactory.SSL_PEER_HOST_CONTEXT_KEY, destination.getHost());
context.put(SslClientConnectionFactory.SSL_PEER_PORT_CONTEXT_KEY, destination.getPort());
boolean connected = true;
if (client.isConnectBlocking())
{
channel.socket().connect(address, (int)client.getConnectTimeout());
channel.configureBlocking(false);
selectorManager.accept(channel, context);
}
else
{
channel.configureBlocking(false);
if (channel.connect(address))
connected = channel.connect(address);
}
if (connected)
selectorManager.accept(channel, context);
else
selectorManager.connect(channel, context);
}
}
// Must catch all exceptions, since some like
// UnresolvedAddressException are not IOExceptions.
catch (Throwable x)

View File

@ -91,4 +91,20 @@ public interface ConnectionPool extends Closeable
*/
ConnectionPool newConnectionPool(HttpDestination destination);
}
/**
* Marks a connection pool as supporting multiplexed connections.
*/
interface Multiplexable
{
/**
* @return the max number of requests multiplexable on a single connection
*/
int getMaxMultiplex();
/**
* @param maxMultiplex the max number of requests multiplexable on a single connection
*/
void setMaxMultiplex(int maxMultiplex);
}
}

View File

@ -70,10 +70,14 @@ public abstract class HttpChannel
}
if (abort)
{
exchange.getRequest().abort(new UnsupportedOperationException("Pipelined requests not supported"));
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("{} associated {} to {}", exchange, result, this);
}
return result;
}

View File

@ -64,6 +64,7 @@ import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Jetty;
import org.eclipse.jetty.util.ProcessorUtils;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.SocketAddressResolver;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
@ -213,7 +214,7 @@ public class HttpClient extends ContainerLifeCycle
byteBufferPool = new MappedByteBufferPool(2048,
executor instanceof ThreadPool.SizedThreadPool
? ((ThreadPool.SizedThreadPool)executor).getMaxThreads()/2
: Runtime.getRuntime().availableProcessors()*2);
: ProcessorUtils.availableProcessors()*2);
addBean(byteBufferPool);
if (scheduler == null)

View File

@ -81,6 +81,17 @@ public class HttpContent implements Callback, Closeable
this.iterator = provider == null ? Collections.<ByteBuffer>emptyIterator() : provider.iterator();
}
/**
* @param buffer
* @return true if the buffer is the sentinel instance {@link CLOSE}
*/
private static boolean isTheCloseBuffer(ByteBuffer buffer)
{
@SuppressWarnings("ReferenceEquality")
boolean isTheCloseBuffer = (buffer == CLOSE);
return isTheCloseBuffer;
}
/**
* @return whether there is any content at all
*/
@ -177,6 +188,7 @@ public class HttpContent implements Callback, Closeable
/**
* @return whether the cursor has been advanced past the {@link #isLast() last} position.
*/
@SuppressWarnings("ReferenceEquality")
public boolean isConsumed()
{
return buffer == AFTER;
@ -187,7 +199,7 @@ public class HttpContent implements Callback, Closeable
{
if (isConsumed())
return;
if (buffer == CLOSE)
if (isTheCloseBuffer(buffer))
return;
if (iterator instanceof Callback)
((Callback)iterator).succeeded();
@ -198,7 +210,7 @@ public class HttpContent implements Callback, Closeable
{
if (isConsumed())
return;
if (buffer == CLOSE)
if (isTheCloseBuffer(buffer))
return;
if (iterator instanceof Callback)
((Callback)iterator).failed(x);

View File

@ -204,7 +204,10 @@ public class HttpRequest implements Request
{
if (uri == null)
uri = buildURI(true);
return uri == NULL_URI ? null : uri;
@SuppressWarnings("ReferenceEquality")
boolean isNullURI = (uri == NULL_URI);
return isNullURI ? null : uri;
}
@Override

View File

@ -36,11 +36,12 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Sweeper;
public class MultiplexConnectionPool extends AbstractConnectionPool implements Sweeper.Sweepable
public class MultiplexConnectionPool extends AbstractConnectionPool implements ConnectionPool.Multiplexable, Sweeper.Sweepable
{
private static final Logger LOG = Log.getLogger(MultiplexConnectionPool.class);
private final ReentrantLock lock = new ReentrantLock();
private final HttpDestination destination;
private final Deque<Holder> idleConnections;
private final Map<Connection, Holder> muxedConnections;
private final Map<Connection, Holder> busyConnections;
@ -49,12 +50,26 @@ public class MultiplexConnectionPool extends AbstractConnectionPool implements S
public MultiplexConnectionPool(HttpDestination destination, int maxConnections, Callback requester, int maxMultiplex)
{
super(destination, maxConnections, requester);
this.destination = destination;
this.idleConnections = new ArrayDeque<>(maxConnections);
this.muxedConnections = new HashMap<>(maxConnections);
this.busyConnections = new HashMap<>(maxConnections);
this.maxMultiplex = maxMultiplex;
}
@Override
public Connection acquire()
{
Connection connection = activate();
if (connection == null)
{
int maxPending = 1 + destination.getQueuedRequestCount() / getMaxMultiplex();
tryCreate(maxPending);
connection = activate();
}
return connection;
}
protected void lock()
{
lock.lock();
@ -65,6 +80,7 @@ public class MultiplexConnectionPool extends AbstractConnectionPool implements S
lock.unlock();
}
@Override
public int getMaxMultiplex()
{
lock();
@ -78,6 +94,7 @@ public class MultiplexConnectionPool extends AbstractConnectionPool implements S
}
}
@Override
public void setMaxMultiplex(int maxMultiplex)
{
lock();

View File

@ -28,15 +28,15 @@ public abstract class MultiplexHttpDestination extends HttpDestination
public int getMaxRequestsPerConnection()
{
ConnectionPool connectionPool = getConnectionPool();
if (connectionPool instanceof MultiplexConnectionPool)
return ((MultiplexConnectionPool)connectionPool).getMaxMultiplex();
if (connectionPool instanceof ConnectionPool.Multiplexable)
return ((ConnectionPool.Multiplexable)connectionPool).getMaxMultiplex();
return 1;
}
public void setMaxRequestsPerConnection(int maxRequestsPerConnection)
{
ConnectionPool connectionPool = getConnectionPool();
if (connectionPool instanceof MultiplexConnectionPool)
((MultiplexConnectionPool)connectionPool).setMaxMultiplex(maxRequestsPerConnection);
if (connectionPool instanceof ConnectionPool.Multiplexable)
((ConnectionPool.Multiplexable)connectionPool).setMaxMultiplex(maxRequestsPerConnection);
}
}

View File

@ -29,17 +29,42 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
@ManagedObject
public class RoundRobinConnectionPool extends AbstractConnectionPool
public class RoundRobinConnectionPool extends AbstractConnectionPool implements ConnectionPool.Multiplexable
{
private final List<Entry> entries;
private int maxMultiplex;
private int index;
public RoundRobinConnectionPool(Destination destination, int maxConnections, Callback requester)
{
this(destination, maxConnections, requester, 1);
}
public RoundRobinConnectionPool(Destination destination, int maxConnections, Callback requester, int maxMultiplex)
{
super(destination, maxConnections, requester);
entries = new ArrayList<>(maxConnections);
for (int i = 0; i < maxConnections; ++i)
entries.add(new Entry());
this.maxMultiplex = maxMultiplex;
}
@Override
public int getMaxMultiplex()
{
synchronized (this)
{
return maxMultiplex;
}
}
@Override
public void setMaxMultiplex(int maxMultiplex)
{
synchronized (this)
{
this.maxMultiplex = maxMultiplex;
}
}
@Override
@ -78,10 +103,10 @@ public class RoundRobinConnectionPool extends AbstractConnectionPool
if (entry.connection == null)
break;
if (!entry.active)
if (entry.active < getMaxMultiplex())
{
entry.active = true;
entry.used++;
++entry.active;
++entry.used;
connection = entry.connection;
index += offset + 1;
if (index >= capacity)
@ -103,7 +128,7 @@ public class RoundRobinConnectionPool extends AbstractConnectionPool
for (Entry entry : entries)
{
if (entry.connection == connection)
return entry.active;
return entry.active > 0;
}
return false;
}
@ -112,56 +137,60 @@ public class RoundRobinConnectionPool extends AbstractConnectionPool
@Override
public boolean release(Connection connection)
{
boolean active = false;
boolean found = false;
boolean idle = false;
synchronized (this)
{
for (Entry entry : entries)
{
if (entry.connection == connection)
{
entry.active = false;
active = true;
found = true;
int active = --entry.active;
idle = active == 0;
break;
}
}
}
if (active)
if (!found)
return false;
released(connection);
if (idle)
return idle(connection, isClosed());
return true;
}
@Override
public boolean remove(Connection connection)
{
boolean active = false;
boolean removed = false;
boolean found = false;
synchronized (this)
{
for (Entry entry : entries)
{
if (entry.connection == connection)
{
active = entry.active;
found = true;
entry.reset();
removed = true;
break;
}
}
}
if (active)
if (found)
{
released(connection);
if (removed)
removed(connection);
return removed;
}
return found;
}
@Override
public void dump(Appendable out, String indent) throws IOException
{
List<Entry> connections = new ArrayList<>();
List<Entry> connections;
synchronized (this)
{
connections.addAll(entries);
connections = new ArrayList<>(entries);
}
ContainerLifeCycle.dumpObject(out, this);
ContainerLifeCycle.dump(out, indent, connections);
@ -179,7 +208,7 @@ public class RoundRobinConnectionPool extends AbstractConnectionPool
if (entry.connection != null)
{
++present;
if (entry.active)
if (entry.active > 0)
++active;
}
}
@ -196,13 +225,13 @@ public class RoundRobinConnectionPool extends AbstractConnectionPool
private static class Entry
{
private Connection connection;
private boolean active;
private int active;
private long used;
private void reset()
{
connection = null;
active = false;
active = 0;
used = 0;
}

View File

@ -27,6 +27,7 @@ import org.eclipse.jetty.client.HttpDestination;
import org.eclipse.jetty.client.Origin;
import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.ProcessorUtils;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedObject;
@ -35,7 +36,7 @@ public class HttpClientTransportOverHTTP extends AbstractConnectorHttpClientTran
{
public HttpClientTransportOverHTTP()
{
this(Math.max(1, Runtime.getRuntime().availableProcessors() / 2));
this(Math.max( 1, ProcessorUtils.availableProcessors() / 2));
}
public HttpClientTransportOverHTTP(int selectors)

View File

@ -26,7 +26,7 @@ import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.client.HttpReceiver;
import org.eclipse.jetty.client.HttpResponse;
import org.eclipse.jetty.client.HttpResponseException;
import org.eclipse.jetty.http.HttpCompliance;
import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpParser;
@ -42,6 +42,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
private final HttpParser parser;
private ByteBuffer buffer;
private boolean shutdown;
private boolean complete;
public HttpReceiverOverHTTP(HttpChannelOverHTTP channel)
{
@ -168,13 +169,22 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
{
while (true)
{
// Must parse even if the buffer is fully consumed, to allow the
// parser to advance from asynchronous content to response complete.
boolean handle = parser.parseNext(buffer);
boolean complete = this.complete;
this.complete = false;
if (LOG.isDebugEnabled())
LOG.debug("Parsed {}, remaining {} {}", handle, buffer.remaining(), parser);
if (handle || !buffer.hasRemaining())
return handle;
if (handle)
return true;
if (!buffer.hasRemaining())
return false;
if (complete)
{
if (LOG.isDebugEnabled())
LOG.debug("Discarding unexpected content after response: {}", BufferUtil.toDetailString(buffer));
BufferUtil.clear(buffer);
return false;
}
}
}
@ -298,11 +308,15 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
if (exchange == null)
return false;
int status = exchange.getResponse().getStatus();
if (status != HttpStatus.CONTINUE_100)
complete = true;
boolean proceed = responseSuccess(exchange);
if (!proceed)
return true;
int status = exchange.getResponse().getStatus();
if (status == HttpStatus.SWITCHING_PROTOCOLS_101)
return true;
@ -325,13 +339,13 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
}
@Override
public void badMessage(int status, String reason)
public void badMessage(BadMessageException failure)
{
HttpExchange exchange = getHttpExchange();
if (exchange != null)
{
HttpResponse response = exchange.getResponse();
response.status(status).reason(reason);
response.status(failure.getCode()).reason(failure.getReason());
failAndClose(new HttpResponseException("HTTP protocol violation: bad response on " + getHttpConnection(), response));
}
}

View File

@ -321,10 +321,10 @@ public class HttpSenderOverHTTP extends HttpSender
private void release()
{
ByteBufferPool bufferPool = httpClient.getByteBufferPool();
if (headerBuffer != BufferUtil.EMPTY_BUFFER)
if (!BufferUtil.isTheEmptyBuffer(headerBuffer))
bufferPool.release(headerBuffer);
headerBuffer = null;
if (chunkBuffer != BufferUtil.EMPTY_BUFFER)
if (!BufferUtil.isTheEmptyBuffer(chunkBuffer))
bufferPool.release(chunkBuffer);
chunkBuffer = null;
contentBuffer = null;

View File

@ -589,6 +589,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
public ByteBuffer current;
@Override
@SuppressWarnings("ReferenceEquality")
public boolean hasNext()
{
if (current == null)

View File

@ -18,8 +18,6 @@
package org.eclipse.jetty.client;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -1297,8 +1295,8 @@ public class HttpClientTest extends AbstractHttpClientServerTest
}
catch(ExecutionException e)
{
assertThat(e.getCause(), Matchers.instanceOf(BadMessageException.class));
assertThat(e.getCause().getMessage(), Matchers.containsString("Unknown content"));
Assert.assertThat(e.getCause(), Matchers.instanceOf(BadMessageException.class));
Assert.assertThat(e.getCause().getMessage(), Matchers.containsString("Unknown content"));
}
}
@ -1311,8 +1309,8 @@ public class HttpClientTest extends AbstractHttpClientServerTest
}
catch(ExecutionException e)
{
assertThat(e.getCause(), Matchers.instanceOf(BadMessageException.class));
assertThat(e.getCause().getMessage(), Matchers.containsString("Unknown content"));
Assert.assertThat(e.getCause(), Matchers.instanceOf(BadMessageException.class));
Assert.assertThat(e.getCause().getMessage(), Matchers.containsString("Unknown content"));
}
}
@ -1650,6 +1648,70 @@ public class HttpClientTest extends AbstractHttpClientServerTest
Assert.assertEquals(200, response.getStatus());
}
@Test
public void test204WithContent() throws Exception
{
// This test only works with clear-text HTTP.
Assume.assumeTrue(sslContextFactory == null);
try (ServerSocket server = new ServerSocket(0))
{
startClient();
client.setMaxConnectionsPerDestination(1);
int idleTimeout = 2000;
client.setIdleTimeout(idleTimeout);
Request request = client.newRequest("localhost", server.getLocalPort())
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS);
FutureResponseListener listener = new FutureResponseListener(request);
request.send(listener);
try (Socket socket = server.accept())
{
socket.setSoTimeout(idleTimeout / 2);
InputStream input = socket.getInputStream();
consume(input, false);
// Send a bad response.
String httpResponse = "" +
"HTTP/1.1 204 No Content\r\n" +
"\r\n" +
"No Content";
OutputStream output = socket.getOutputStream();
output.write(httpResponse.getBytes(StandardCharsets.UTF_8));
output.flush();
ContentResponse response = listener.get(5, TimeUnit.SECONDS);
Assert.assertEquals(204, response.getStatus());
byte[] responseContent = response.getContent();
Assert.assertNotNull(responseContent);
Assert.assertEquals(0, responseContent.length);
// Send another request to verify we have handled the wrong response correctly.
request = client.newRequest("localhost", server.getLocalPort())
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS);
listener = new FutureResponseListener(request);
request.send(listener);
consume(input, false);
httpResponse = "" +
"HTTP/1.1 200 OK\r\n" +
"Content-Length: 0\r\n" +
"\r\n";
output.write(httpResponse.getBytes(StandardCharsets.UTF_8));
output.flush();
response = listener.get(5, TimeUnit.SECONDS);
Assert.assertEquals(200, response.getStatus());
}
}
}
private void assertCopyRequest(Request original)
{
Request copy = client.copyRequest((HttpRequest) original, original.getURI());

View File

@ -19,6 +19,8 @@
package org.eclipse.jetty.client;
import java.nio.channels.Selector;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@ -30,14 +32,37 @@ import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.SocketAddressResolver;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class LivelockTest
{
@Parameterized.Parameters(name = "server={0}, client={1}")
public static List<Object[]> data()
{
List<Object[]> data = new ArrayList<>();
// Server-live-lock, Client-live-lock
data.add(new Object[] { true, true });
data.add(new Object[] { true, false });
data.add(new Object[] { false, true });
data.add(new Object[] { false, false });
return data;
}
@Parameterized.Parameter(0)
public boolean serverLiveLock;
@Parameterized.Parameter(1)
public boolean clientLiveLock;
private Server server;
private ServerConnector connector;
private HttpClient client;
@ -73,7 +98,7 @@ public class LivelockTest
// ManagedSelectors that submit themselves in an attempt to cause a live lock
// as there will always be an action available to run.
int count = 25;
int count = 5;
HttpClientTransport transport = new HttpClientTransportOverHTTP(1);
client = new HttpClient(transport, null);
client.setMaxConnectionsPerDestination(2 * count);
@ -88,34 +113,21 @@ public class LivelockTest
AtomicBoolean busy = new AtomicBoolean(true);
if (clientLiveLock)
{
ManagedSelector clientSelector = client.getContainedBeans(ManagedSelector.class).stream().findAny().get();
ManagedSelector.SelectorUpdate clientLivelock = new ManagedSelector.SelectorUpdate()
{
@Override
public void update(Selector selector)
{
sleep(10);
if (busy.get())
clientSelector.submit(this);
busyLiveLock(busy, clientSelector);
}
};
clientSelector.submit(clientLivelock);
if (serverLiveLock)
{
ManagedSelector serverSelector = connector.getContainedBeans(ManagedSelector.class).stream().findAny().get();
ManagedSelector.SelectorUpdate serverLivelock = new ManagedSelector.SelectorUpdate()
{
@Override
public void update(Selector selector)
{
sleep(10);
if (busy.get())
serverSelector.submit(this);
busyLiveLock(busy, serverSelector);
}
};
serverSelector.submit(serverLivelock);
int requestRate = 5;
long pause = 1000 / requestRate;
Logger clientLog = Log.getLogger("TESTClient");
CountDownLatch latch = new CountDownLatch(count);
for (int i = 0; i < count; ++i)
{
@ -125,6 +137,13 @@ public class LivelockTest
{
if (result.isSucceeded() && result.getResponse().getStatus() == HttpStatus.OK_200)
latch.countDown();
else
{
if(result.getRequestFailure() != null)
clientLog.warn(result.getRequestFailure());
if(result.getResponseFailure() != null)
clientLog.warn(result.getResponseFailure());
}
});
sleep(pause);
}
@ -134,11 +153,26 @@ public class LivelockTest
busy.set(false);
}
private void sleep(long time)
private void busyLiveLock(AtomicBoolean busy, ManagedSelector managedSelector)
{
ManagedSelector.SelectorUpdate liveLock = new ManagedSelector.SelectorUpdate()
{
@Override
public void update(Selector selector)
{
sleep(10);
if (busy.get())
managedSelector.submit(this);
}
};
managedSelector.submit(liveLock);
}
private void sleep(long millis)
{
try
{
Thread.sleep(time);
TimeUnit.MILLISECONDS.sleep(millis);
}
catch (InterruptedException x)
{

View File

@ -1,99 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
public class RoundRobinConnectionPoolTest extends AbstractHttpClientServerTest
{
public RoundRobinConnectionPoolTest(SslContextFactory sslContextFactory)
{
super(sslContextFactory);
}
@Test
public void testRoundRobin() throws Exception
{
AtomicBoolean record = new AtomicBoolean();
List<Integer> remotePorts = new ArrayList<>();
start(new EmptyServerHandler()
{
@Override
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (record.get())
remotePorts.add(request.getRemotePort());
}
});
int maxConnections = 3;
client.getTransport().setConnectionPoolFactory(destination -> new RoundRobinConnectionPool(destination, maxConnections, destination));
// Prime the connections, so that they are all opened
// before we actually test the round robin behavior.
String host = "localhost";
int port = connector.getLocalPort();
for (int i = 0; i < maxConnections; ++i)
{
ContentResponse response = client.newRequest(host, port)
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
record.set(true);
int requests = 2 * maxConnections - 1;
for (int i = 0; i < requests; ++i)
{
ContentResponse response = client.newRequest(host, port)
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
Assert.assertThat(remotePorts.size(), Matchers.equalTo(requests));
for (int i = 0; i < requests; ++i)
{
int base = i % maxConnections;
int expected = remotePorts.get(base);
int candidate = remotePorts.get(i);
Assert.assertThat(client.dump() + System.lineSeparator() + remotePorts.toString(), expected, Matchers.equalTo(candidate));
if (i > 0)
Assert.assertThat(remotePorts.get(i - 1), Matchers.not(Matchers.equalTo(candidate)));
}
}
}

View File

@ -1,5 +1,5 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
#org.eclipse.jetty.LEVEL=DEBUG
class=org.eclipse.jetty.util.log.StdErrLog
#org.eclipse.jetty.LEVEL=INFO
#org.eclipse.jetty.client.LEVEL=DEBUG
#org.eclipse.jetty.io.ChannelEndPoint.LEVEL=DEBUG
#org.eclipse.jetty.http.LEVEL=DEBUG

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables webapplication deployment from the webapps directory.

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Ref refid="DeploymentManager">

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables Deployer to apply common configuration to all webapp deployments

View File

@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
@ -311,10 +312,12 @@ public class DeploymentManager extends ContainerLifeCycle
*/
public Collection<App> getApps(Node node)
{
Objects.requireNonNull(node);
List<App> ret = new ArrayList<>();
for (AppEntry entry : _apps)
{
if (entry.lifecyleNode == node)
if (node.equals(entry.lifecyleNode))
{
ret.add(entry.app);
}

View File

@ -28,7 +28,9 @@ public final class Edge
public Edge(Node from, Node to)
{
if (from==null || to==null || from==to)
@SuppressWarnings("ReferenceEquality")
boolean sameObject = (from==to);
if (from==null || to==null || sameObject)
throw new IllegalArgumentException("from "+from+" to "+to);
_from = from;
_to = to;

View File

@ -40,7 +40,7 @@ public class Graph
addNode(toNode=edge.getTo());
// replace edge with normalized edge
if (edge.getFrom()!=fromNode || edge.getTo()!=toNode)
if (!edge.getFrom().equals(fromNode) || !edge.getTo().equals(toNode))
edge=new Edge(fromNode,toNode);
this._edges.add(edge);
@ -129,7 +129,7 @@ public class Graph
for (Edge edge : this._edges)
{
if ((edge.getFrom() == node) || (edge.getTo() == node))
if (edge.getFrom().equals(node) || edge.getTo().equals(node))
{
fromedges.add(edge);
}
@ -151,7 +151,7 @@ public class Graph
for (Edge edge : this._edges)
{
if (edge.getFrom() == from)
if (edge.getFrom().equals(from))
{
fromedges.add(edge);
}
@ -192,7 +192,9 @@ public class Graph
*/
public Path getPath(Node from, Node to)
{
if (from == to)
@SuppressWarnings("ReferenceEquality")
boolean sameObject = (from==to);
if (sameObject)
{
return new Path();
}

View File

@ -74,7 +74,7 @@ public class DeploymentManagerMBean extends ObjectMBean
List<String> ret = new ArrayList<>();
for (DeploymentManager.AppEntry entry : _manager.getAppEntries())
{
if (entry.getLifecyleNode() == node)
if (node.equals(entry.getLifecyleNode()))
{
ret.add(toRef(entry.getApp()));
}

View File

@ -59,10 +59,6 @@ System Properties:
Properties:
-----------
java.version = 1.8.0_92
java.version.major = 1
java.version.minor = 8
java.version.revision = 0
java.version.update = 92
Jetty Server Classpath:
-----------------------

View File

@ -59,10 +59,6 @@ System Properties:
Properties:
-----------
java.version = 1.8.0_92
java.version.major = 1
java.version.minor = 8
java.version.revision = 0
java.version.update = 92
Jetty Server Classpath:
-----------------------

View File

@ -148,6 +148,14 @@ This is done by editing the associated ini file for the module.
If your server setup is using a centralized ini configuration, you will edit the `${jetty.base}/server.ini` file.
If you have elected to manage each module within it's own ini file, you can find these files in the `${jetty.base}/start.d` directory.
____
[IMPORTANT]
It is important that you *do not* modify the module files in the `$JETTY_HOME/modules` directory.
$JETTY_HOME should always remain a standard of truth.
If you want to make a change to an actual module file (not the values in its `ini-template`), either edit its associated `ini` file in the `$JETTY_BASE/start.d` directory or make a copy of the desired module file and copy it to the `$JETTY_BASE` directory and edit it there.
The start.jar reads local `$JETTY_BASE/modules` files (if they exist) before scanning `$JETTY_HOME`.
____
When a module is activated, a number of properties are set by default.
To view these defaults, open up the associated ini file.
Listed in the ini file is the associated module file and any properties that can be set.

View File

@ -719,10 +719,10 @@ This is _not_ a recommended usage.
____
[[conscrypt]]
===== Conscrypt SSL
==== Conscrypt SSL
Jetty also includes support for Google's https://github.com/google/conscrypt/[Conscrypt SSL], which is built on their fork of https://www.openssl.org/[OpenSSL], https://boringssl.googlesource.com/boringssl/[BoringSSL].
Implementing Conscrypt is very straightforward process - simply instantiate an instance of Conscrypt's `OpenSSLProvider` and set `Conscrypt` as a provider for Jetty's `SslContextFactory`:
Jetty includes support for Google's https://github.com/google/conscrypt/[Conscrypt SSL], which is built on their fork of https://www.openssl.org/[OpenSSL], https://boringssl.googlesource.com/boringssl/[BoringSSL].
Implementing Conscrypt for the link:{GITBROWSEURL}/jetty-alpn/jetty-alpn-conscrypt-server/src/test/java/org/eclipse/jetty/alpn/conscrypt/server/ConscryptHTTP2Server.java[server] or link:{GITBROWSEURL}/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2Client.java[client] is very straightforward process - simply instantiate an instance of Conscrypt's `OpenSSLProvider` and set `Conscrypt` as a provider for Jetty's `SslContextFactory`:
[source, java, subs="{sub-order}"]
----

View File

@ -75,6 +75,17 @@ URI uri = URI.create("http://domain.com/secure");
auth.addAuthenticationResult(new BasicAuthentication.BasicResult(uri, "username", "password"));
----
In this way, the original request is enriched by `HttpClient` immediately with the `Authorization` header, and the server should respond with a 200 and the resource content rather than with the 401 and the challenge.
In this way, requests for the given URI are enriched by `HttpClient` immediately with the `Authorization` header, and the server should respond with a 200 and the resource content rather than with the 401 and the challenge.
It is also possible to preempt the authentication for a single request only, in this way:
[source, java, subs="{sub-order}"]
----
URI uri = URI.create("http://domain.com/secure");
Authentication.Result authn = new BasicAuthentication.BasicResult(uri, "username", "password")
Request request = httpClient.newRequest(uri);
authn.apply(request);
request.send();
----
See also the link:#http-client-proxy-authentication[proxy authentication section] for further information about how authentication works with HTTP proxies.

View File

@ -35,7 +35,7 @@ _____
|Version |Year |Home |JVM |Protocols |Servlet |JSP |Status
|9.4 |2016- |Eclipse |1.8 |HTTP/1.1 (RFC 7230), HTTP/2 (RFC 7540), WebSocket (RFC 6455, JSR 356), FastCGI |3.1 |2.3 |Stable
|9.3 |2015- |Eclipse |1.8 |HTTP/1.1 (RFC 7230), HTTP/2 (RFC 7540), WebSocket (RFC 6455, JSR 356), FastCGI |3.1 |2.3 |Stable
|9.2 |2014- |Eclipse |1.7 |HTTP/1.1 RFC2616, javax.websocket, SPDY v3 |3.1 |2.3 |Deprecated / *End of Life January 2018*
|9.2 |2014-2018 |Eclipse |1.7 |HTTP/1.1 RFC2616, javax.websocket, SPDY v3 |3.1 |2.3 |Deprecated / *End of Life January 2018*
|8 |2009-2014 |Eclipse/Codehaus |1.6 |HTTP/1.1 RFC2616, WebSocket RFC 6455, SPDY v3 |3.0 |2.2 |Deprecated / *End of Life November 2014*
|7 |2008-2014 |Eclipse/Codehaus |1.5 |HTTP/1.1 RFC2616, WebSocket RFC 6455, SPDY v3 |2.5 |2.1 |Deprecated / *End of Life November 2014*
|6 |2006-2010 |Codehaus |1.4-1.5 |HTTP/1.1 RFC2616 |2.5 |2.0 |Deprecated / *End of Life November 2010*

View File

@ -32,6 +32,7 @@ import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.fcgi.FCGI;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.ProcessorUtils;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
@ -44,7 +45,7 @@ public class HttpClientTransportOverFCGI extends AbstractConnectorHttpClientTran
public HttpClientTransportOverFCGI(String scriptRoot)
{
this(Math.max(1, Runtime.getRuntime().availableProcessors() / 2), false, scriptRoot);
this( Math.max( 1, ProcessorUtils.availableProcessors() / 2), false, scriptRoot);
}
public HttpClientTransportOverFCGI(int selectors, boolean multiplexed, String scriptRoot)

View File

@ -127,7 +127,9 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
private void releaseBuffer(ByteBuffer buffer)
{
assert this.buffer == buffer;
@SuppressWarnings("ReferenceEquality")
boolean isCurrentBuffer = (this.buffer == buffer);
assert(isCurrentBuffer);
HttpClient client = destination.getHttpClient();
ByteBufferPool bufferPool = client.getByteBufferPool();
bufferPool.release(buffer);

View File

@ -306,9 +306,9 @@ public class ResponseContentParser extends StreamContentParser
}
@Override
public void badMessage(int status, String reason)
public void badMessage(BadMessageException failure)
{
fail(new BadMessageException(status, reason));
fail(failure);
}
protected void fail(Throwable failure)

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Adds the FastCGI implementation to the classpath.

View File

@ -25,7 +25,9 @@ import java.util.concurrent.ConcurrentMap;
import org.eclipse.jetty.fcgi.FCGI;
import org.eclipse.jetty.fcgi.generator.Flusher;
import org.eclipse.jetty.fcgi.parser.ServerParser;
import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint;
@ -187,9 +189,7 @@ public class ServerFCGIConnection extends AbstractConnection
if (LOG.isDebugEnabled())
LOG.debug("Request {} failure on {}: {}", request, channel, failure);
if (channel != null)
{
channel.onBadMessage(400, failure.toString());
}
channel.onBadMessage(new BadMessageException(HttpStatus.BAD_REQUEST_400, null, failure));
}
}
}

View File

@ -40,6 +40,7 @@ import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.proxy.AsyncProxyServlet;
import org.eclipse.jetty.util.ProcessorUtils;
/**
* Specific implementation of {@link org.eclipse.jetty.proxy.AsyncProxyServlet.Transparent} for FastCGI.
@ -111,7 +112,7 @@ public class FastCGIProxyServlet extends AsyncProxyServlet.Transparent
String scriptRoot = config.getInitParameter(SCRIPT_ROOT_INIT_PARAM);
if (scriptRoot == null)
throw new IllegalArgumentException("Mandatory parameter '" + SCRIPT_ROOT_INIT_PARAM + "' not configured");
int selectors = Math.max(1, Runtime.getRuntime().availableProcessors() / 2);
int selectors = Math.max( 1, ProcessorUtils.availableProcessors() / 2);
String value = config.getInitParameter("selectors");
if (value != null)
selectors = Integer.parseInt(value);

View File

@ -34,6 +34,7 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.LeakDetector;
import org.eclipse.jetty.util.ProcessorUtils;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.hamcrest.Matchers;
import org.junit.After;
@ -59,8 +60,8 @@ public abstract class AbstractHttpClientServerTest
ServerFCGIConnectionFactory fcgiConnectionFactory = new ServerFCGIConnectionFactory(new HttpConfiguration());
serverBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());
connector = new ServerConnector(server, null, null, serverBufferPool,
1, Math.max(1, Runtime.getRuntime().availableProcessors() / 2), fcgiConnectionFactory);
connector = new ServerConnector( server, null, null, serverBufferPool,
1, Math.max( 1, ProcessorUtils.availableProcessors() / 2), fcgiConnectionFactory);
// connector.setPort(9000);
server.addConnector(connector);

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables GCloud Datastore API and implementation

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Control GCloud API classpath

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables GCloudDatastore session management.

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables session data store in an embedded Hazelcast Map

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables session data store in a remote Hazelcast Map

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Installs the Conscrypt JSSE provider

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Deploys the Hawtio console as a webapplication.

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Deploys the JAMon webapplication

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Deploys the Jminix JMX Console within the server

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Deploys the Jolokia console as a web application.

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables JSP for all webapplications deployed on the server.

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables JSTL for all webapplications deployed on the server

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables the unix setUID configuration so that the server
may be started as root to open privileged ports/files before

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
This module causes jetty to stop immediately after starting. This is good for testing configuration and/or precompiling quickstart webapps

View File

@ -417,7 +417,9 @@ public class GZIPContentDecoder implements Destroyable
*/
public void release(ByteBuffer buffer)
{
if (_pool!=null && buffer!=BufferUtil.EMPTY_BUFFER)
@SuppressWarnings("ReferenceEquality")
boolean isTheEmptyBuffer = (buffer==BufferUtil.EMPTY_BUFFER);
if (_pool!=null && !isTheEmptyBuffer)
_pool.release(buffer);
}
}

View File

@ -276,9 +276,12 @@ public class HttpField
public boolean isSameName(HttpField field)
{
@SuppressWarnings("ReferenceEquality")
boolean sameObject = (field==this);
if (field==null)
return false;
if (field==this)
if (sameObject)
return true;
if (_header!=null && _header==field.getHeader())
return true;

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